Path: blob/main/contrib/llvm-project/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
35294 views
//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "MCTargetDesc/MipsABIFlagsSection.h"9#include "MCTargetDesc/MipsABIInfo.h"10#include "MCTargetDesc/MipsBaseInfo.h"11#include "MCTargetDesc/MipsMCExpr.h"12#include "MCTargetDesc/MipsMCTargetDesc.h"13#include "MipsTargetStreamer.h"14#include "TargetInfo/MipsTargetInfo.h"15#include "llvm/ADT/APFloat.h"16#include "llvm/ADT/STLExtras.h"17#include "llvm/ADT/SmallVector.h"18#include "llvm/ADT/StringRef.h"19#include "llvm/ADT/StringSwitch.h"20#include "llvm/ADT/Twine.h"21#include "llvm/BinaryFormat/ELF.h"22#include "llvm/MC/MCContext.h"23#include "llvm/MC/MCExpr.h"24#include "llvm/MC/MCInst.h"25#include "llvm/MC/MCInstrDesc.h"26#include "llvm/MC/MCInstrInfo.h"27#include "llvm/MC/MCObjectFileInfo.h"28#include "llvm/MC/MCParser/MCAsmLexer.h"29#include "llvm/MC/MCParser/MCAsmParser.h"30#include "llvm/MC/MCParser/MCAsmParserExtension.h"31#include "llvm/MC/MCParser/MCAsmParserUtils.h"32#include "llvm/MC/MCParser/MCParsedAsmOperand.h"33#include "llvm/MC/MCParser/MCTargetAsmParser.h"34#include "llvm/MC/MCSectionELF.h"35#include "llvm/MC/MCStreamer.h"36#include "llvm/MC/MCSubtargetInfo.h"37#include "llvm/MC/MCSymbol.h"38#include "llvm/MC/MCSymbolELF.h"39#include "llvm/MC/MCValue.h"40#include "llvm/MC/TargetRegistry.h"41#include "llvm/Support/Alignment.h"42#include "llvm/Support/Casting.h"43#include "llvm/Support/CommandLine.h"44#include "llvm/Support/Compiler.h"45#include "llvm/Support/Debug.h"46#include "llvm/Support/ErrorHandling.h"47#include "llvm/Support/MathExtras.h"48#include "llvm/Support/SMLoc.h"49#include "llvm/Support/SourceMgr.h"50#include "llvm/Support/raw_ostream.h"51#include "llvm/TargetParser/SubtargetFeature.h"52#include "llvm/TargetParser/Triple.h"53#include <algorithm>54#include <cassert>55#include <cstdint>56#include <memory>57#include <string>58#include <utility>5960using namespace llvm;6162#define DEBUG_TYPE "mips-asm-parser"6364namespace llvm {6566class MCInstrInfo;6768} // end namespace llvm6970extern cl::opt<bool> EmitJalrReloc;7172namespace {7374class MipsAssemblerOptions {75public:76MipsAssemblerOptions(const FeatureBitset &Features_) : Features(Features_) {}7778MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {79ATReg = Opts->getATRegIndex();80Reorder = Opts->isReorder();81Macro = Opts->isMacro();82Features = Opts->getFeatures();83}8485unsigned getATRegIndex() const { return ATReg; }86bool setATRegIndex(unsigned Reg) {87if (Reg > 31)88return false;8990ATReg = Reg;91return true;92}9394bool isReorder() const { return Reorder; }95void setReorder() { Reorder = true; }96void setNoReorder() { Reorder = false; }9798bool isMacro() const { return Macro; }99void setMacro() { Macro = true; }100void setNoMacro() { Macro = false; }101102const FeatureBitset &getFeatures() const { return Features; }103void setFeatures(const FeatureBitset &Features_) { Features = Features_; }104105// Set of features that are either architecture features or referenced106// by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).107// The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).108// The reason we need this mask is explained in the selectArch function.109// FIXME: Ideally we would like TableGen to generate this information.110static const FeatureBitset AllArchRelatedMask;111112private:113unsigned ATReg = 1;114bool Reorder = true;115bool Macro = true;116FeatureBitset Features;117};118119} // end anonymous namespace120121const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {122Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,123Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,124Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,125Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,126Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,127Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,128Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,129Mips::FeatureCnMipsP, Mips::FeatureFP64Bit, Mips::FeatureGP64Bit,130Mips::FeatureNaN2008131};132133namespace {134135class MipsAsmParser : public MCTargetAsmParser {136MipsTargetStreamer &getTargetStreamer() {137assert(getParser().getStreamer().getTargetStreamer() &&138"do not have a target streamer");139MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();140return static_cast<MipsTargetStreamer &>(TS);141}142143MipsABIInfo ABI;144SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;145MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a146// nullptr, which indicates that no function is currently147// selected. This usually happens after an '.end func'148// directive.149bool IsLittleEndian;150bool IsPicEnabled;151bool IsCpRestoreSet;152bool CurForbiddenSlotAttr;153int CpRestoreOffset;154unsigned GPReg;155unsigned CpSaveLocation;156/// If true, then CpSaveLocation is a register, otherwise it's an offset.157bool CpSaveLocationIsRegister;158159// Map of register aliases created via the .set directive.160StringMap<AsmToken> RegisterSets;161162// Print a warning along with its fix-it message at the given range.163void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,164SMRange Range, bool ShowColors = true);165166void ConvertXWPOperands(MCInst &Inst, const OperandVector &Operands);167168#define GET_ASSEMBLER_HEADER169#include "MipsGenAsmMatcher.inc"170171unsigned172checkEarlyTargetMatchPredicate(MCInst &Inst,173const OperandVector &Operands) override;174unsigned checkTargetMatchPredicate(MCInst &Inst) override;175176bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,177OperandVector &Operands, MCStreamer &Out,178uint64_t &ErrorInfo,179bool MatchingInlineAsm) override;180181/// Parse a register as used in CFI directives182bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;183ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,184SMLoc &EndLoc) override;185186bool parseParenSuffix(StringRef Name, OperandVector &Operands);187188bool parseBracketSuffix(StringRef Name, OperandVector &Operands);189190bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);191192bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,193SMLoc NameLoc, OperandVector &Operands) override;194195bool ParseDirective(AsmToken DirectiveID) override;196197ParseStatus parseMemOperand(OperandVector &Operands);198ParseStatus matchAnyRegisterNameWithoutDollar(OperandVector &Operands,199StringRef Identifier, SMLoc S);200ParseStatus matchAnyRegisterWithoutDollar(OperandVector &Operands,201const AsmToken &Token, SMLoc S);202ParseStatus matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);203ParseStatus parseAnyRegister(OperandVector &Operands);204ParseStatus parseImm(OperandVector &Operands);205ParseStatus parseJumpTarget(OperandVector &Operands);206ParseStatus parseInvNum(OperandVector &Operands);207ParseStatus parseRegisterList(OperandVector &Operands);208209bool searchSymbolAlias(OperandVector &Operands);210211bool parseOperand(OperandVector &, StringRef Mnemonic);212213enum MacroExpanderResultTy {214MER_NotAMacro,215MER_Success,216MER_Fail,217};218219// Expands assembly pseudo instructions.220MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,221MCStreamer &Out,222const MCSubtargetInfo *STI);223224bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,225const MCSubtargetInfo *STI);226227bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,228bool Is32BitImm, bool IsAddress, SMLoc IDLoc,229MCStreamer &Out, const MCSubtargetInfo *STI);230231bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,232unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,233MCStreamer &Out, const MCSubtargetInfo *STI);234235bool emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc, MCSymbol *Sym);236237bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,238MCStreamer &Out, const MCSubtargetInfo *STI);239240bool expandLoadSingleImmToGPR(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,241const MCSubtargetInfo *STI);242bool expandLoadSingleImmToFPR(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,243const MCSubtargetInfo *STI);244bool expandLoadDoubleImmToGPR(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,245const MCSubtargetInfo *STI);246bool expandLoadDoubleImmToFPR(MCInst &Inst, bool Is64FPU, SMLoc IDLoc,247MCStreamer &Out, const MCSubtargetInfo *STI);248249bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,250const MCOperand &Offset, bool Is32BitAddress,251SMLoc IDLoc, MCStreamer &Out,252const MCSubtargetInfo *STI);253254bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,255const MCSubtargetInfo *STI);256257void expandMem16Inst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,258const MCSubtargetInfo *STI, bool IsLoad);259void expandMem9Inst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,260const MCSubtargetInfo *STI, bool IsLoad);261262bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,263const MCSubtargetInfo *STI);264265bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,266const MCSubtargetInfo *STI);267268bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,269const MCSubtargetInfo *STI);270271bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,272const MCSubtargetInfo *STI);273274bool expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,275const MCSubtargetInfo *STI, const bool IsMips64,276const bool Signed);277278bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,279MCStreamer &Out, const MCSubtargetInfo *STI);280281bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out,282const MCSubtargetInfo *STI);283284bool expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,285const MCSubtargetInfo *STI);286287bool expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,288const MCSubtargetInfo *STI);289290bool expandSge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,291const MCSubtargetInfo *STI);292293bool expandSgeImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,294const MCSubtargetInfo *STI);295296bool expandSgtImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,297const MCSubtargetInfo *STI);298299bool expandSle(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,300const MCSubtargetInfo *STI);301302bool expandSleImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,303const MCSubtargetInfo *STI);304305bool expandRotation(MCInst &Inst, SMLoc IDLoc,306MCStreamer &Out, const MCSubtargetInfo *STI);307bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,308const MCSubtargetInfo *STI);309bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,310const MCSubtargetInfo *STI);311bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,312const MCSubtargetInfo *STI);313314bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,315const MCSubtargetInfo *STI);316317bool expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,318const MCSubtargetInfo *STI);319320bool expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,321const MCSubtargetInfo *STI);322323bool expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,324const MCSubtargetInfo *STI);325326bool expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,327const MCSubtargetInfo *STI);328329bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,330const MCSubtargetInfo *STI, bool IsLoad);331332bool expandStoreDM1Macro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,333const MCSubtargetInfo *STI);334335bool expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,336const MCSubtargetInfo *STI);337338bool expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,339const MCSubtargetInfo *STI);340341bool expandSne(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,342const MCSubtargetInfo *STI);343344bool expandSneI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,345const MCSubtargetInfo *STI);346347bool expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,348const MCSubtargetInfo *STI);349350bool expandSaaAddr(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,351const MCSubtargetInfo *STI);352353bool reportParseError(const Twine &ErrorMsg);354bool reportParseError(SMLoc Loc, const Twine &ErrorMsg);355356bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);357358bool parseSetMips0Directive();359bool parseSetArchDirective();360bool parseSetFeature(uint64_t Feature);361bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.362bool parseDirectiveCpAdd(SMLoc Loc);363bool parseDirectiveCpLoad(SMLoc Loc);364bool parseDirectiveCpLocal(SMLoc Loc);365bool parseDirectiveCpRestore(SMLoc Loc);366bool parseDirectiveCPSetup();367bool parseDirectiveCPReturn();368bool parseDirectiveNaN();369bool parseDirectiveSet();370bool parseDirectiveOption();371bool parseInsnDirective();372bool parseRSectionDirective(StringRef Section);373bool parseSSectionDirective(StringRef Section, unsigned Type);374375bool parseSetAtDirective();376bool parseSetNoAtDirective();377bool parseSetMacroDirective();378bool parseSetNoMacroDirective();379bool parseSetMsaDirective();380bool parseSetNoMsaDirective();381bool parseSetNoDspDirective();382bool parseSetNoMips3DDirective();383bool parseSetReorderDirective();384bool parseSetNoReorderDirective();385bool parseSetMips16Directive();386bool parseSetNoMips16Directive();387bool parseSetFpDirective();388bool parseSetOddSPRegDirective();389bool parseSetNoOddSPRegDirective();390bool parseSetPopDirective();391bool parseSetPushDirective();392bool parseSetSoftFloatDirective();393bool parseSetHardFloatDirective();394bool parseSetMtDirective();395bool parseSetNoMtDirective();396bool parseSetNoCRCDirective();397bool parseSetNoVirtDirective();398bool parseSetNoGINVDirective();399400bool parseSetAssignment();401402bool parseDirectiveGpWord();403bool parseDirectiveGpDWord();404bool parseDirectiveDtpRelWord();405bool parseDirectiveDtpRelDWord();406bool parseDirectiveTpRelWord();407bool parseDirectiveTpRelDWord();408bool parseDirectiveModule();409bool parseDirectiveModuleFP();410bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,411StringRef Directive);412413bool parseInternalDirectiveReallowModule();414415bool eatComma(StringRef ErrorStr);416417int matchCPURegisterName(StringRef Symbol);418419int matchHWRegsRegisterName(StringRef Symbol);420421int matchFPURegisterName(StringRef Name);422423int matchFCCRegisterName(StringRef Name);424425int matchACRegisterName(StringRef Name);426427int matchMSA128RegisterName(StringRef Name);428429int matchMSA128CtrlRegisterName(StringRef Name);430431unsigned getReg(int RC, int RegNo);432433/// Returns the internal register number for the current AT. Also checks if434/// the current AT is unavailable (set to $0) and gives an error if it is.435/// This should be used in pseudo-instruction expansions which need AT.436unsigned getATReg(SMLoc Loc);437438bool canUseATReg();439440bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,441const MCSubtargetInfo *STI);442443// Helper function that checks if the value of a vector index is within the444// boundaries of accepted values for each RegisterKind445// Example: INSERT.B $w0[n], $1 => 16 > n >= 0446bool validateMSAIndex(int Val, int RegKind);447448// Selects a new architecture by updating the FeatureBits with the necessary449// info including implied dependencies.450// Internally, it clears all the feature bits related to *any* architecture451// and selects the new one using the ToggleFeature functionality of the452// MCSubtargetInfo object that handles implied dependencies. The reason we453// clear all the arch related bits manually is because ToggleFeature only454// clears the features that imply the feature being cleared and not the455// features implied by the feature being cleared. This is easier to see456// with an example:457// --------------------------------------------------458// | Feature | Implies |459// | -------------------------------------------------|460// | FeatureMips1 | None |461// | FeatureMips2 | FeatureMips1 |462// | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |463// | FeatureMips4 | FeatureMips3 |464// | ... | |465// --------------------------------------------------466//467// Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |468// FeatureMipsGP64 | FeatureMips1)469// Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).470void selectArch(StringRef ArchFeature) {471MCSubtargetInfo &STI = copySTI();472FeatureBitset FeatureBits = STI.getFeatureBits();473FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;474STI.setFeatureBits(FeatureBits);475setAvailableFeatures(476ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));477AssemblerOptions.back()->setFeatures(STI.getFeatureBits());478}479480void setFeatureBits(uint64_t Feature, StringRef FeatureString) {481if (!(getSTI().hasFeature(Feature))) {482MCSubtargetInfo &STI = copySTI();483setAvailableFeatures(484ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));485AssemblerOptions.back()->setFeatures(STI.getFeatureBits());486}487}488489void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {490if (getSTI().hasFeature(Feature)) {491MCSubtargetInfo &STI = copySTI();492setAvailableFeatures(493ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));494AssemblerOptions.back()->setFeatures(STI.getFeatureBits());495}496}497498void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {499setFeatureBits(Feature, FeatureString);500AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());501}502503void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {504clearFeatureBits(Feature, FeatureString);505AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());506}507508public:509enum MipsMatchResultTy {510Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,511Match_RequiresDifferentOperands,512Match_RequiresNoZeroRegister,513Match_RequiresSameSrcAndDst,514Match_NoFCCRegisterForCurrentISA,515Match_NonZeroOperandForSync,516Match_NonZeroOperandForMTCX,517Match_RequiresPosSizeRange0_32,518Match_RequiresPosSizeRange33_64,519Match_RequiresPosSizeUImm6,520#define GET_OPERAND_DIAGNOSTIC_TYPES521#include "MipsGenAsmMatcher.inc"522#undef GET_OPERAND_DIAGNOSTIC_TYPES523};524525MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,526const MCInstrInfo &MII, const MCTargetOptions &Options)527: MCTargetAsmParser(Options, sti, MII),528ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),529sti.getCPU(), Options)) {530MCAsmParserExtension::Initialize(parser);531532parser.addAliasForDirective(".asciiz", ".asciz");533parser.addAliasForDirective(".hword", ".2byte");534parser.addAliasForDirective(".word", ".4byte");535parser.addAliasForDirective(".dword", ".8byte");536537// Initialize the set of available features.538setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));539540// Remember the initial assembler options. The user can not modify these.541AssemblerOptions.push_back(542std::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));543544// Create an assembler options environment for the user to modify.545AssemblerOptions.push_back(546std::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));547548getTargetStreamer().updateABIInfo(*this);549550if (!isABI_O32() && !useOddSPReg() != 0)551report_fatal_error("-mno-odd-spreg requires the O32 ABI");552553CurrentFn = nullptr;554555CurForbiddenSlotAttr = false;556IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();557558IsCpRestoreSet = false;559CpRestoreOffset = -1;560GPReg = ABI.GetGlobalPtr();561562const Triple &TheTriple = sti.getTargetTriple();563IsLittleEndian = TheTriple.isLittleEndian();564565if (getSTI().getCPU() == "mips64r6" && inMicroMipsMode())566report_fatal_error("microMIPS64R6 is not supported", false);567568if (!isABI_O32() && inMicroMipsMode())569report_fatal_error("microMIPS64 is not supported", false);570}571572/// True if all of $fcc0 - $fcc7 exist for the current ISA.573bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }574575bool isGP64bit() const {576return getSTI().hasFeature(Mips::FeatureGP64Bit);577}578579bool isFP64bit() const {580return getSTI().hasFeature(Mips::FeatureFP64Bit);581}582583bool isJalrRelocAvailable(const MCExpr *JalExpr) {584if (!EmitJalrReloc)585return false;586MCValue Res;587if (!JalExpr->evaluateAsRelocatable(Res, nullptr, nullptr))588return false;589if (Res.getSymB() != nullptr)590return false;591if (Res.getConstant() != 0)592return ABI.IsN32() || ABI.IsN64();593return true;594}595596const MipsABIInfo &getABI() const { return ABI; }597bool isABI_N32() const { return ABI.IsN32(); }598bool isABI_N64() const { return ABI.IsN64(); }599bool isABI_O32() const { return ABI.IsO32(); }600bool isABI_FPXX() const {601return getSTI().hasFeature(Mips::FeatureFPXX);602}603604bool useOddSPReg() const {605return !(getSTI().hasFeature(Mips::FeatureNoOddSPReg));606}607608bool inMicroMipsMode() const {609return getSTI().hasFeature(Mips::FeatureMicroMips);610}611612bool hasMips1() const {613return getSTI().hasFeature(Mips::FeatureMips1);614}615616bool hasMips2() const {617return getSTI().hasFeature(Mips::FeatureMips2);618}619620bool hasMips3() const {621return getSTI().hasFeature(Mips::FeatureMips3);622}623624bool hasMips4() const {625return getSTI().hasFeature(Mips::FeatureMips4);626}627628bool hasMips5() const {629return getSTI().hasFeature(Mips::FeatureMips5);630}631632bool hasMips32() const {633return getSTI().hasFeature(Mips::FeatureMips32);634}635636bool hasMips64() const {637return getSTI().hasFeature(Mips::FeatureMips64);638}639640bool hasMips32r2() const {641return getSTI().hasFeature(Mips::FeatureMips32r2);642}643644bool hasMips64r2() const {645return getSTI().hasFeature(Mips::FeatureMips64r2);646}647648bool hasMips32r3() const {649return (getSTI().hasFeature(Mips::FeatureMips32r3));650}651652bool hasMips64r3() const {653return (getSTI().hasFeature(Mips::FeatureMips64r3));654}655656bool hasMips32r5() const {657return (getSTI().hasFeature(Mips::FeatureMips32r5));658}659660bool hasMips64r5() const {661return (getSTI().hasFeature(Mips::FeatureMips64r5));662}663664bool hasMips32r6() const {665return getSTI().hasFeature(Mips::FeatureMips32r6);666}667668bool hasMips64r6() const {669return getSTI().hasFeature(Mips::FeatureMips64r6);670}671672bool hasDSP() const {673return getSTI().hasFeature(Mips::FeatureDSP);674}675676bool hasDSPR2() const {677return getSTI().hasFeature(Mips::FeatureDSPR2);678}679680bool hasDSPR3() const {681return getSTI().hasFeature(Mips::FeatureDSPR3);682}683684bool hasMSA() const {685return getSTI().hasFeature(Mips::FeatureMSA);686}687688bool hasCnMips() const {689return (getSTI().hasFeature(Mips::FeatureCnMips));690}691692bool hasCnMipsP() const {693return (getSTI().hasFeature(Mips::FeatureCnMipsP));694}695696bool inPicMode() {697return IsPicEnabled;698}699700bool inMips16Mode() const {701return getSTI().hasFeature(Mips::FeatureMips16);702}703704bool useTraps() const {705return getSTI().hasFeature(Mips::FeatureUseTCCInDIV);706}707708bool useSoftFloat() const {709return getSTI().hasFeature(Mips::FeatureSoftFloat);710}711bool hasMT() const {712return getSTI().hasFeature(Mips::FeatureMT);713}714715bool hasCRC() const {716return getSTI().hasFeature(Mips::FeatureCRC);717}718719bool hasVirt() const {720return getSTI().hasFeature(Mips::FeatureVirt);721}722723bool hasGINV() const {724return getSTI().hasFeature(Mips::FeatureGINV);725}726727bool hasForbiddenSlot(const MCInstrDesc &MCID) const {728return !inMicroMipsMode() && (MCID.TSFlags & MipsII::HasForbiddenSlot);729}730731bool SafeInForbiddenSlot(const MCInstrDesc &MCID) const {732return !(MCID.TSFlags & MipsII::IsCTI);733}734735void onEndOfFile() override;736737/// Warn if RegIndex is the same as the current AT.738void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);739740void warnIfNoMacro(SMLoc Loc);741742bool isLittle() const { return IsLittleEndian; }743744const MCExpr *createTargetUnaryExpr(const MCExpr *E,745AsmToken::TokenKind OperatorToken,746MCContext &Ctx) override {747switch(OperatorToken) {748default:749llvm_unreachable("Unknown token");750return nullptr;751case AsmToken::PercentCall16:752return MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, E, Ctx);753case AsmToken::PercentCall_Hi:754return MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16, E, Ctx);755case AsmToken::PercentCall_Lo:756return MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16, E, Ctx);757case AsmToken::PercentDtprel_Hi:758return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_HI, E, Ctx);759case AsmToken::PercentDtprel_Lo:760return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_LO, E, Ctx);761case AsmToken::PercentGot:762return MipsMCExpr::create(MipsMCExpr::MEK_GOT, E, Ctx);763case AsmToken::PercentGot_Disp:764return MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, E, Ctx);765case AsmToken::PercentGot_Hi:766return MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, E, Ctx);767case AsmToken::PercentGot_Lo:768return MipsMCExpr::create(MipsMCExpr::MEK_GOT_LO16, E, Ctx);769case AsmToken::PercentGot_Ofst:770return MipsMCExpr::create(MipsMCExpr::MEK_GOT_OFST, E, Ctx);771case AsmToken::PercentGot_Page:772return MipsMCExpr::create(MipsMCExpr::MEK_GOT_PAGE, E, Ctx);773case AsmToken::PercentGottprel:774return MipsMCExpr::create(MipsMCExpr::MEK_GOTTPREL, E, Ctx);775case AsmToken::PercentGp_Rel:776return MipsMCExpr::create(MipsMCExpr::MEK_GPREL, E, Ctx);777case AsmToken::PercentHi:778return MipsMCExpr::create(MipsMCExpr::MEK_HI, E, Ctx);779case AsmToken::PercentHigher:780return MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, E, Ctx);781case AsmToken::PercentHighest:782return MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, E, Ctx);783case AsmToken::PercentLo:784return MipsMCExpr::create(MipsMCExpr::MEK_LO, E, Ctx);785case AsmToken::PercentNeg:786return MipsMCExpr::create(MipsMCExpr::MEK_NEG, E, Ctx);787case AsmToken::PercentPcrel_Hi:788return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_HI16, E, Ctx);789case AsmToken::PercentPcrel_Lo:790return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_LO16, E, Ctx);791case AsmToken::PercentTlsgd:792return MipsMCExpr::create(MipsMCExpr::MEK_TLSGD, E, Ctx);793case AsmToken::PercentTlsldm:794return MipsMCExpr::create(MipsMCExpr::MEK_TLSLDM, E, Ctx);795case AsmToken::PercentTprel_Hi:796return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_HI, E, Ctx);797case AsmToken::PercentTprel_Lo:798return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_LO, E, Ctx);799}800}801802bool areEqualRegs(const MCParsedAsmOperand &Op1,803const MCParsedAsmOperand &Op2) const override;804};805806/// MipsOperand - Instances of this class represent a parsed Mips machine807/// instruction.808class MipsOperand : public MCParsedAsmOperand {809public:810/// Broad categories of register classes811/// The exact class is finalized by the render method.812enum RegKind {813RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())814RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and815/// isFP64bit())816RegKind_FCC = 4, /// FCC817RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)818RegKind_MSACtrl = 16, /// MSA control registers819RegKind_COP2 = 32, /// COP2820RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on821/// context).822RegKind_CCR = 128, /// CCR823RegKind_HWRegs = 256, /// HWRegs824RegKind_COP3 = 512, /// COP3825RegKind_COP0 = 1024, /// COP0826/// Potentially any (e.g. $1)827RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |828RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |829RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0830};831832private:833enum KindTy {834k_Immediate, /// An immediate (possibly involving symbol references)835k_Memory, /// Base + Offset Memory Address836k_RegisterIndex, /// A register index in one or more RegKind.837k_Token, /// A simple token838k_RegList, /// A physical register list839} Kind;840841public:842MipsOperand(KindTy K, MipsAsmParser &Parser) : Kind(K), AsmParser(Parser) {}843844~MipsOperand() override {845switch (Kind) {846case k_Memory:847delete Mem.Base;848break;849case k_RegList:850delete RegList.List;851break;852case k_Immediate:853case k_RegisterIndex:854case k_Token:855break;856}857}858859private:860/// For diagnostics, and checking the assembler temporary861MipsAsmParser &AsmParser;862863struct Token {864const char *Data;865unsigned Length;866};867868struct RegIdxOp {869unsigned Index; /// Index into the register class870RegKind Kind; /// Bitfield of the kinds it could possibly be871struct Token Tok; /// The input token this operand originated from.872const MCRegisterInfo *RegInfo;873};874875struct ImmOp {876const MCExpr *Val;877};878879struct MemOp {880MipsOperand *Base;881const MCExpr *Off;882};883884struct RegListOp {885SmallVector<unsigned, 10> *List;886};887888union {889struct Token Tok;890struct RegIdxOp RegIdx;891struct ImmOp Imm;892struct MemOp Mem;893struct RegListOp RegList;894};895896SMLoc StartLoc, EndLoc;897898/// Internal constructor for register kinds899static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str,900RegKind RegKind,901const MCRegisterInfo *RegInfo,902SMLoc S, SMLoc E,903MipsAsmParser &Parser) {904auto Op = std::make_unique<MipsOperand>(k_RegisterIndex, Parser);905Op->RegIdx.Index = Index;906Op->RegIdx.RegInfo = RegInfo;907Op->RegIdx.Kind = RegKind;908Op->RegIdx.Tok.Data = Str.data();909Op->RegIdx.Tok.Length = Str.size();910Op->StartLoc = S;911Op->EndLoc = E;912return Op;913}914915public:916/// Coerce the register to GPR32 and return the real register for the current917/// target.918unsigned getGPR32Reg() const {919assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");920AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);921unsigned ClassID = Mips::GPR32RegClassID;922return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);923}924925/// Coerce the register to GPR32 and return the real register for the current926/// target.927unsigned getGPRMM16Reg() const {928assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");929unsigned ClassID = Mips::GPR32RegClassID;930return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);931}932933/// Coerce the register to GPR64 and return the real register for the current934/// target.935unsigned getGPR64Reg() const {936assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");937unsigned ClassID = Mips::GPR64RegClassID;938return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);939}940941private:942/// Coerce the register to AFGR64 and return the real register for the current943/// target.944unsigned getAFGR64Reg() const {945assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");946if (RegIdx.Index % 2 != 0)947AsmParser.Warning(StartLoc, "Float register should be even.");948return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)949.getRegister(RegIdx.Index / 2);950}951952/// Coerce the register to FGR64 and return the real register for the current953/// target.954unsigned getFGR64Reg() const {955assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");956return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)957.getRegister(RegIdx.Index);958}959960/// Coerce the register to FGR32 and return the real register for the current961/// target.962unsigned getFGR32Reg() const {963assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");964return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)965.getRegister(RegIdx.Index);966}967968/// Coerce the register to FCC and return the real register for the current969/// target.970unsigned getFCCReg() const {971assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");972return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)973.getRegister(RegIdx.Index);974}975976/// Coerce the register to MSA128 and return the real register for the current977/// target.978unsigned getMSA128Reg() const {979assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");980// It doesn't matter which of the MSA128[BHWD] classes we use. They are all981// identical982unsigned ClassID = Mips::MSA128BRegClassID;983return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);984}985986/// Coerce the register to MSACtrl and return the real register for the987/// current target.988unsigned getMSACtrlReg() const {989assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");990unsigned ClassID = Mips::MSACtrlRegClassID;991return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);992}993994/// Coerce the register to COP0 and return the real register for the995/// current target.996unsigned getCOP0Reg() const {997assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");998unsigned ClassID = Mips::COP0RegClassID;999return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);1000}10011002/// Coerce the register to COP2 and return the real register for the1003/// current target.1004unsigned getCOP2Reg() const {1005assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");1006unsigned ClassID = Mips::COP2RegClassID;1007return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);1008}10091010/// Coerce the register to COP3 and return the real register for the1011/// current target.1012unsigned getCOP3Reg() const {1013assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");1014unsigned ClassID = Mips::COP3RegClassID;1015return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);1016}10171018/// Coerce the register to ACC64DSP and return the real register for the1019/// current target.1020unsigned getACC64DSPReg() const {1021assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");1022unsigned ClassID = Mips::ACC64DSPRegClassID;1023return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);1024}10251026/// Coerce the register to HI32DSP and return the real register for the1027/// current target.1028unsigned getHI32DSPReg() const {1029assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");1030unsigned ClassID = Mips::HI32DSPRegClassID;1031return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);1032}10331034/// Coerce the register to LO32DSP and return the real register for the1035/// current target.1036unsigned getLO32DSPReg() const {1037assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");1038unsigned ClassID = Mips::LO32DSPRegClassID;1039return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);1040}10411042/// Coerce the register to CCR and return the real register for the1043/// current target.1044unsigned getCCRReg() const {1045assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");1046unsigned ClassID = Mips::CCRRegClassID;1047return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);1048}10491050/// Coerce the register to HWRegs and return the real register for the1051/// current target.1052unsigned getHWRegsReg() const {1053assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");1054unsigned ClassID = Mips::HWRegsRegClassID;1055return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);1056}10571058public:1059void addExpr(MCInst &Inst, const MCExpr *Expr) const {1060// Add as immediate when possible. Null MCExpr = 0.1061if (!Expr)1062Inst.addOperand(MCOperand::createImm(0));1063else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))1064Inst.addOperand(MCOperand::createImm(CE->getValue()));1065else1066Inst.addOperand(MCOperand::createExpr(Expr));1067}10681069void addRegOperands(MCInst &Inst, unsigned N) const {1070llvm_unreachable("Use a custom parser instead");1071}10721073/// Render the operand to an MCInst as a GPR321074/// Asserts if the wrong number of operands are requested, or the operand1075/// is not a k_RegisterIndex compatible with RegKind_GPR1076void addGPR32ZeroAsmRegOperands(MCInst &Inst, unsigned N) const {1077assert(N == 1 && "Invalid number of operands!");1078Inst.addOperand(MCOperand::createReg(getGPR32Reg()));1079}10801081void addGPR32NonZeroAsmRegOperands(MCInst &Inst, unsigned N) const {1082assert(N == 1 && "Invalid number of operands!");1083Inst.addOperand(MCOperand::createReg(getGPR32Reg()));1084}10851086void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {1087assert(N == 1 && "Invalid number of operands!");1088Inst.addOperand(MCOperand::createReg(getGPR32Reg()));1089}10901091void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {1092assert(N == 1 && "Invalid number of operands!");1093Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));1094}10951096void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {1097assert(N == 1 && "Invalid number of operands!");1098Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));1099}11001101void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {1102assert(N == 1 && "Invalid number of operands!");1103Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));1104}11051106void addGPRMM16AsmRegMovePPairFirstOperands(MCInst &Inst, unsigned N) const {1107assert(N == 1 && "Invalid number of operands!");1108Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));1109}11101111void addGPRMM16AsmRegMovePPairSecondOperands(MCInst &Inst,1112unsigned N) const {1113assert(N == 1 && "Invalid number of operands!");1114Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));1115}11161117/// Render the operand to an MCInst as a GPR641118/// Asserts if the wrong number of operands are requested, or the operand1119/// is not a k_RegisterIndex compatible with RegKind_GPR1120void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {1121assert(N == 1 && "Invalid number of operands!");1122Inst.addOperand(MCOperand::createReg(getGPR64Reg()));1123}11241125void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {1126assert(N == 1 && "Invalid number of operands!");1127Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));1128}11291130void addStrictlyAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {1131assert(N == 1 && "Invalid number of operands!");1132Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));1133}11341135void addStrictlyFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {1136assert(N == 1 && "Invalid number of operands!");1137Inst.addOperand(MCOperand::createReg(getFGR64Reg()));1138}11391140void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {1141assert(N == 1 && "Invalid number of operands!");1142Inst.addOperand(MCOperand::createReg(getFGR64Reg()));1143}11441145void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {1146assert(N == 1 && "Invalid number of operands!");1147Inst.addOperand(MCOperand::createReg(getFGR32Reg()));1148// FIXME: We ought to do this for -integrated-as without -via-file-asm too.1149// FIXME: This should propagate failure up to parseStatement.1150if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)1151AsmParser.getParser().printError(1152StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "1153"registers");1154}11551156void addStrictlyFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {1157assert(N == 1 && "Invalid number of operands!");1158Inst.addOperand(MCOperand::createReg(getFGR32Reg()));1159// FIXME: We ought to do this for -integrated-as without -via-file-asm too.1160if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)1161AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "1162"registers");1163}11641165void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {1166assert(N == 1 && "Invalid number of operands!");1167Inst.addOperand(MCOperand::createReg(getFCCReg()));1168}11691170void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {1171assert(N == 1 && "Invalid number of operands!");1172Inst.addOperand(MCOperand::createReg(getMSA128Reg()));1173}11741175void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {1176assert(N == 1 && "Invalid number of operands!");1177Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));1178}11791180void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {1181assert(N == 1 && "Invalid number of operands!");1182Inst.addOperand(MCOperand::createReg(getCOP0Reg()));1183}11841185void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {1186assert(N == 1 && "Invalid number of operands!");1187Inst.addOperand(MCOperand::createReg(getCOP2Reg()));1188}11891190void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {1191assert(N == 1 && "Invalid number of operands!");1192Inst.addOperand(MCOperand::createReg(getCOP3Reg()));1193}11941195void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {1196assert(N == 1 && "Invalid number of operands!");1197Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));1198}11991200void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {1201assert(N == 1 && "Invalid number of operands!");1202Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));1203}12041205void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {1206assert(N == 1 && "Invalid number of operands!");1207Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));1208}12091210void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {1211assert(N == 1 && "Invalid number of operands!");1212Inst.addOperand(MCOperand::createReg(getCCRReg()));1213}12141215void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {1216assert(N == 1 && "Invalid number of operands!");1217Inst.addOperand(MCOperand::createReg(getHWRegsReg()));1218}12191220template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>1221void addConstantUImmOperands(MCInst &Inst, unsigned N) const {1222assert(N == 1 && "Invalid number of operands!");1223uint64_t Imm = getConstantImm() - Offset;1224Imm &= (1ULL << Bits) - 1;1225Imm += Offset;1226Imm += AdjustOffset;1227Inst.addOperand(MCOperand::createImm(Imm));1228}12291230template <unsigned Bits>1231void addSImmOperands(MCInst &Inst, unsigned N) const {1232if (isImm() && !isConstantImm()) {1233addExpr(Inst, getImm());1234return;1235}1236addConstantSImmOperands<Bits, 0, 0>(Inst, N);1237}12381239template <unsigned Bits>1240void addUImmOperands(MCInst &Inst, unsigned N) const {1241if (isImm() && !isConstantImm()) {1242addExpr(Inst, getImm());1243return;1244}1245addConstantUImmOperands<Bits, 0, 0>(Inst, N);1246}12471248template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>1249void addConstantSImmOperands(MCInst &Inst, unsigned N) const {1250assert(N == 1 && "Invalid number of operands!");1251int64_t Imm = getConstantImm() - Offset;1252Imm = SignExtend64<Bits>(Imm);1253Imm += Offset;1254Imm += AdjustOffset;1255Inst.addOperand(MCOperand::createImm(Imm));1256}12571258void addImmOperands(MCInst &Inst, unsigned N) const {1259assert(N == 1 && "Invalid number of operands!");1260const MCExpr *Expr = getImm();1261addExpr(Inst, Expr);1262}12631264void addMemOperands(MCInst &Inst, unsigned N) const {1265assert(N == 2 && "Invalid number of operands!");12661267Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()1268? getMemBase()->getGPR64Reg()1269: getMemBase()->getGPR32Reg()));12701271const MCExpr *Expr = getMemOff();1272addExpr(Inst, Expr);1273}12741275void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {1276assert(N == 2 && "Invalid number of operands!");12771278Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));12791280const MCExpr *Expr = getMemOff();1281addExpr(Inst, Expr);1282}12831284void addRegListOperands(MCInst &Inst, unsigned N) const {1285assert(N == 1 && "Invalid number of operands!");12861287for (auto RegNo : getRegList())1288Inst.addOperand(MCOperand::createReg(RegNo));1289}12901291bool isReg() const override {1292// As a special case until we sort out the definition of div/divu, accept1293// $0/$zero here so that MCK_ZERO works correctly.1294return isGPRAsmReg() && RegIdx.Index == 0;1295}12961297bool isRegIdx() const { return Kind == k_RegisterIndex; }1298bool isImm() const override { return Kind == k_Immediate; }12991300bool isConstantImm() const {1301int64_t Res;1302return isImm() && getImm()->evaluateAsAbsolute(Res);1303}13041305bool isConstantImmz() const {1306return isConstantImm() && getConstantImm() == 0;1307}13081309template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {1310return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);1311}13121313template <unsigned Bits> bool isSImm() const {1314return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();1315}13161317template <unsigned Bits> bool isUImm() const {1318return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();1319}13201321template <unsigned Bits> bool isAnyImm() const {1322return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||1323isUInt<Bits>(getConstantImm()))1324: isImm();1325}13261327template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {1328return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);1329}13301331template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {1332return isConstantImm() && getConstantImm() >= Bottom &&1333getConstantImm() <= Top;1334}13351336bool isToken() const override {1337// Note: It's not possible to pretend that other operand kinds are tokens.1338// The matcher emitter checks tokens first.1339return Kind == k_Token;1340}13411342bool isMem() const override { return Kind == k_Memory; }13431344bool isConstantMemOff() const {1345return isMem() && isa<MCConstantExpr>(getMemOff());1346}13471348// Allow relocation operators.1349template <unsigned Bits, unsigned ShiftAmount = 0>1350bool isMemWithSimmOffset() const {1351if (!isMem())1352return false;1353if (!getMemBase()->isGPRAsmReg())1354return false;1355if (isa<MCTargetExpr>(getMemOff()) ||1356(isConstantMemOff() &&1357isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))1358return true;1359MCValue Res;1360bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);1361return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());1362}13631364bool isMemWithPtrSizeOffset() const {1365if (!isMem())1366return false;1367if (!getMemBase()->isGPRAsmReg())1368return false;1369const unsigned PtrBits = AsmParser.getABI().ArePtrs64bit() ? 64 : 32;1370if (isa<MCTargetExpr>(getMemOff()) ||1371(isConstantMemOff() && isIntN(PtrBits, getConstantMemOff())))1372return true;1373MCValue Res;1374bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);1375return IsReloc && isIntN(PtrBits, Res.getConstant());1376}13771378bool isMemWithGRPMM16Base() const {1379return isMem() && getMemBase()->isMM16AsmReg();1380}13811382template <unsigned Bits> bool isMemWithUimmOffsetSP() const {1383return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())1384&& getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);1385}13861387template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {1388return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())1389&& (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()1390&& (getMemBase()->getGPR32Reg() == Mips::SP);1391}13921393template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {1394return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())1395&& (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()1396&& (getMemBase()->getGPR32Reg() == Mips::GP);1397}13981399template <unsigned Bits, unsigned ShiftLeftAmount>1400bool isScaledUImm() const {1401return isConstantImm() &&1402isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());1403}14041405template <unsigned Bits, unsigned ShiftLeftAmount>1406bool isScaledSImm() const {1407if (isConstantImm() &&1408isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))1409return true;1410// Operand can also be a symbol or symbol plus1411// offset in case of relocations.1412if (Kind != k_Immediate)1413return false;1414MCValue Res;1415bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr);1416return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());1417}14181419bool isRegList16() const {1420if (!isRegList())1421return false;14221423int Size = RegList.List->size();1424if (Size < 2 || Size > 5)1425return false;14261427unsigned R0 = RegList.List->front();1428unsigned R1 = RegList.List->back();1429if (!((R0 == Mips::S0 && R1 == Mips::RA) ||1430(R0 == Mips::S0_64 && R1 == Mips::RA_64)))1431return false;14321433int PrevReg = *RegList.List->begin();1434for (int i = 1; i < Size - 1; i++) {1435int Reg = (*(RegList.List))[i];1436if ( Reg != PrevReg + 1)1437return false;1438PrevReg = Reg;1439}14401441return true;1442}14431444bool isInvNum() const { return Kind == k_Immediate; }14451446bool isLSAImm() const {1447if (!isConstantImm())1448return false;1449int64_t Val = getConstantImm();1450return 1 <= Val && Val <= 4;1451}14521453bool isRegList() const { return Kind == k_RegList; }14541455StringRef getToken() const {1456assert(Kind == k_Token && "Invalid access!");1457return StringRef(Tok.Data, Tok.Length);1458}14591460MCRegister getReg() const override {1461// As a special case until we sort out the definition of div/divu, accept1462// $0/$zero here so that MCK_ZERO works correctly.1463if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&1464RegIdx.Kind & RegKind_GPR)1465return getGPR32Reg(); // FIXME: GPR64 too14661467llvm_unreachable("Invalid access!");1468return 0;1469}14701471const MCExpr *getImm() const {1472assert((Kind == k_Immediate) && "Invalid access!");1473return Imm.Val;1474}14751476int64_t getConstantImm() const {1477const MCExpr *Val = getImm();1478int64_t Value = 0;1479(void)Val->evaluateAsAbsolute(Value);1480return Value;1481}14821483MipsOperand *getMemBase() const {1484assert((Kind == k_Memory) && "Invalid access!");1485return Mem.Base;1486}14871488const MCExpr *getMemOff() const {1489assert((Kind == k_Memory) && "Invalid access!");1490return Mem.Off;1491}14921493int64_t getConstantMemOff() const {1494return static_cast<const MCConstantExpr *>(getMemOff())->getValue();1495}14961497const SmallVectorImpl<unsigned> &getRegList() const {1498assert((Kind == k_RegList) && "Invalid access!");1499return *(RegList.List);1500}15011502static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,1503MipsAsmParser &Parser) {1504auto Op = std::make_unique<MipsOperand>(k_Token, Parser);1505Op->Tok.Data = Str.data();1506Op->Tok.Length = Str.size();1507Op->StartLoc = S;1508Op->EndLoc = S;1509return Op;1510}15111512/// Create a numeric register (e.g. $1). The exact register remains1513/// unresolved until an instruction successfully matches1514static std::unique_ptr<MipsOperand>1515createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,1516SMLoc S, SMLoc E, MipsAsmParser &Parser) {1517LLVM_DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");1518return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);1519}15201521/// Create a register that is definitely a GPR.1522/// This is typically only used for named registers such as $gp.1523static std::unique_ptr<MipsOperand>1524createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,1525SMLoc S, SMLoc E, MipsAsmParser &Parser) {1526return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser);1527}15281529/// Create a register that is definitely a FGR.1530/// This is typically only used for named registers such as $f0.1531static std::unique_ptr<MipsOperand>1532createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,1533SMLoc S, SMLoc E, MipsAsmParser &Parser) {1534return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser);1535}15361537/// Create a register that is definitely a HWReg.1538/// This is typically only used for named registers such as $hwr_cpunum.1539static std::unique_ptr<MipsOperand>1540createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,1541SMLoc S, SMLoc E, MipsAsmParser &Parser) {1542return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, Parser);1543}15441545/// Create a register that is definitely an FCC.1546/// This is typically only used for named registers such as $fcc0.1547static std::unique_ptr<MipsOperand>1548createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,1549SMLoc S, SMLoc E, MipsAsmParser &Parser) {1550return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser);1551}15521553/// Create a register that is definitely an ACC.1554/// This is typically only used for named registers such as $ac0.1555static std::unique_ptr<MipsOperand>1556createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,1557SMLoc S, SMLoc E, MipsAsmParser &Parser) {1558return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser);1559}15601561/// Create a register that is definitely an MSA128.1562/// This is typically only used for named registers such as $w0.1563static std::unique_ptr<MipsOperand>1564createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,1565SMLoc S, SMLoc E, MipsAsmParser &Parser) {1566return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser);1567}15681569/// Create a register that is definitely an MSACtrl.1570/// This is typically only used for named registers such as $msaaccess.1571static std::unique_ptr<MipsOperand>1572createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,1573SMLoc S, SMLoc E, MipsAsmParser &Parser) {1574return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser);1575}15761577static std::unique_ptr<MipsOperand>1578CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {1579auto Op = std::make_unique<MipsOperand>(k_Immediate, Parser);1580Op->Imm.Val = Val;1581Op->StartLoc = S;1582Op->EndLoc = E;1583return Op;1584}15851586static std::unique_ptr<MipsOperand>1587CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,1588SMLoc E, MipsAsmParser &Parser) {1589auto Op = std::make_unique<MipsOperand>(k_Memory, Parser);1590Op->Mem.Base = Base.release();1591Op->Mem.Off = Off;1592Op->StartLoc = S;1593Op->EndLoc = E;1594return Op;1595}15961597static std::unique_ptr<MipsOperand>1598CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,1599MipsAsmParser &Parser) {1600assert(Regs.size() > 0 && "Empty list not allowed");16011602auto Op = std::make_unique<MipsOperand>(k_RegList, Parser);1603Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());1604Op->StartLoc = StartLoc;1605Op->EndLoc = EndLoc;1606return Op;1607}16081609bool isGPRZeroAsmReg() const {1610return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index == 0;1611}16121613bool isGPRNonZeroAsmReg() const {1614return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index > 0 &&1615RegIdx.Index <= 31;1616}16171618bool isGPRAsmReg() const {1619return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;1620}16211622bool isMM16AsmReg() const {1623if (!(isRegIdx() && RegIdx.Kind))1624return false;1625return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)1626|| RegIdx.Index == 16 || RegIdx.Index == 17);16271628}1629bool isMM16AsmRegZero() const {1630if (!(isRegIdx() && RegIdx.Kind))1631return false;1632return (RegIdx.Index == 0 ||1633(RegIdx.Index >= 2 && RegIdx.Index <= 7) ||1634RegIdx.Index == 17);1635}16361637bool isMM16AsmRegMoveP() const {1638if (!(isRegIdx() && RegIdx.Kind))1639return false;1640return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||1641(RegIdx.Index >= 16 && RegIdx.Index <= 20));1642}16431644bool isMM16AsmRegMovePPairFirst() const {1645if (!(isRegIdx() && RegIdx.Kind))1646return false;1647return RegIdx.Index >= 4 && RegIdx.Index <= 6;1648}16491650bool isMM16AsmRegMovePPairSecond() const {1651if (!(isRegIdx() && RegIdx.Kind))1652return false;1653return (RegIdx.Index == 21 || RegIdx.Index == 22 ||1654(RegIdx.Index >= 5 && RegIdx.Index <= 7));1655}16561657bool isFGRAsmReg() const {1658// AFGR64 is $0-$15 but we handle this in getAFGR64()1659return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;1660}16611662bool isStrictlyFGRAsmReg() const {1663// AFGR64 is $0-$15 but we handle this in getAFGR64()1664return isRegIdx() && RegIdx.Kind == RegKind_FGR && RegIdx.Index <= 31;1665}16661667bool isHWRegsAsmReg() const {1668return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;1669}16701671bool isCCRAsmReg() const {1672return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;1673}16741675bool isFCCAsmReg() const {1676if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))1677return false;1678return RegIdx.Index <= 7;1679}16801681bool isACCAsmReg() const {1682return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;1683}16841685bool isCOP0AsmReg() const {1686return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;1687}16881689bool isCOP2AsmReg() const {1690return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;1691}16921693bool isCOP3AsmReg() const {1694return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;1695}16961697bool isMSA128AsmReg() const {1698return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;1699}17001701bool isMSACtrlAsmReg() const {1702return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;1703}17041705/// getStartLoc - Get the location of the first token of this operand.1706SMLoc getStartLoc() const override { return StartLoc; }1707/// getEndLoc - Get the location of the last token of this operand.1708SMLoc getEndLoc() const override { return EndLoc; }17091710void print(raw_ostream &OS) const override {1711switch (Kind) {1712case k_Immediate:1713OS << "Imm<";1714OS << *Imm.Val;1715OS << ">";1716break;1717case k_Memory:1718OS << "Mem<";1719Mem.Base->print(OS);1720OS << ", ";1721OS << *Mem.Off;1722OS << ">";1723break;1724case k_RegisterIndex:1725OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "1726<< StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";1727break;1728case k_Token:1729OS << getToken();1730break;1731case k_RegList:1732OS << "RegList< ";1733for (auto Reg : (*RegList.List))1734OS << Reg << " ";1735OS << ">";1736break;1737}1738}17391740bool isValidForTie(const MipsOperand &Other) const {1741if (Kind != Other.Kind)1742return false;17431744switch (Kind) {1745default:1746llvm_unreachable("Unexpected kind");1747return false;1748case k_RegisterIndex: {1749StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);1750StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);1751return Token == OtherToken;1752}1753}1754}1755}; // class MipsOperand17561757} // end anonymous namespace17581759static bool hasShortDelaySlot(MCInst &Inst) {1760switch (Inst.getOpcode()) {1761case Mips::BEQ_MM:1762case Mips::BNE_MM:1763case Mips::BLTZ_MM:1764case Mips::BGEZ_MM:1765case Mips::BLEZ_MM:1766case Mips::BGTZ_MM:1767case Mips::JRC16_MM:1768case Mips::JALS_MM:1769case Mips::JALRS_MM:1770case Mips::JALRS16_MM:1771case Mips::BGEZALS_MM:1772case Mips::BLTZALS_MM:1773return true;1774case Mips::J_MM:1775return !Inst.getOperand(0).isReg();1776default:1777return false;1778}1779}17801781static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {1782if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {1783return &SRExpr->getSymbol();1784}17851786if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {1787const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());1788const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());17891790if (LHSSym)1791return LHSSym;17921793if (RHSSym)1794return RHSSym;17951796return nullptr;1797}17981799if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))1800return getSingleMCSymbol(UExpr->getSubExpr());18011802return nullptr;1803}18041805static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {1806if (isa<MCSymbolRefExpr>(Expr))1807return 1;18081809if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))1810return countMCSymbolRefExpr(BExpr->getLHS()) +1811countMCSymbolRefExpr(BExpr->getRHS());18121813if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))1814return countMCSymbolRefExpr(UExpr->getSubExpr());18151816return 0;1817}18181819static bool isEvaluated(const MCExpr *Expr) {1820switch (Expr->getKind()) {1821case MCExpr::Constant:1822return true;1823case MCExpr::SymbolRef:1824return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);1825case MCExpr::Binary: {1826const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);1827if (!isEvaluated(BE->getLHS()))1828return false;1829return isEvaluated(BE->getRHS());1830}1831case MCExpr::Unary:1832return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());1833case MCExpr::Target:1834return true;1835}1836return false;1837}18381839static bool needsExpandMemInst(MCInst &Inst, const MCInstrDesc &MCID) {1840unsigned NumOp = MCID.getNumOperands();1841if (NumOp != 3 && NumOp != 4)1842return false;18431844const MCOperandInfo &OpInfo = MCID.operands()[NumOp - 1];1845if (OpInfo.OperandType != MCOI::OPERAND_MEMORY &&1846OpInfo.OperandType != MCOI::OPERAND_UNKNOWN &&1847OpInfo.OperandType != MipsII::OPERAND_MEM_SIMM9)1848return false;18491850MCOperand &Op = Inst.getOperand(NumOp - 1);1851if (Op.isImm()) {1852if (OpInfo.OperandType == MipsII::OPERAND_MEM_SIMM9)1853return !isInt<9>(Op.getImm());1854// Offset can't exceed 16bit value.1855return !isInt<16>(Op.getImm());1856}18571858if (Op.isExpr()) {1859const MCExpr *Expr = Op.getExpr();1860if (Expr->getKind() != MCExpr::SymbolRef)1861return !isEvaluated(Expr);18621863// Expand symbol.1864const MCSymbolRefExpr *SR = static_cast<const MCSymbolRefExpr *>(Expr);1865return SR->getKind() == MCSymbolRefExpr::VK_None;1866}18671868return false;1869}18701871bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,1872MCStreamer &Out,1873const MCSubtargetInfo *STI) {1874MipsTargetStreamer &TOut = getTargetStreamer();1875const unsigned Opcode = Inst.getOpcode();1876const MCInstrDesc &MCID = MII.get(Opcode);1877bool ExpandedJalSym = false;18781879Inst.setLoc(IDLoc);18801881if (MCID.isBranch() || MCID.isCall()) {1882MCOperand Offset;18831884switch (Opcode) {1885default:1886break;1887case Mips::BBIT0:1888case Mips::BBIT032:1889case Mips::BBIT1:1890case Mips::BBIT132:1891assert(hasCnMips() && "instruction only valid for octeon cpus");1892[[fallthrough]];18931894case Mips::BEQ:1895case Mips::BNE:1896case Mips::BEQ_MM:1897case Mips::BNE_MM:1898assert(MCID.getNumOperands() == 3 && "unexpected number of operands");1899Offset = Inst.getOperand(2);1900if (!Offset.isImm())1901break; // We'll deal with this situation later on when applying fixups.1902if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))1903return Error(IDLoc, "branch target out of range");1904if (offsetToAlignment(Offset.getImm(),1905(inMicroMipsMode() ? Align(2) : Align(4))))1906return Error(IDLoc, "branch to misaligned address");1907break;1908case Mips::BGEZ:1909case Mips::BGTZ:1910case Mips::BLEZ:1911case Mips::BLTZ:1912case Mips::BGEZAL:1913case Mips::BLTZAL:1914case Mips::BC1F:1915case Mips::BC1T:1916case Mips::BGEZ_MM:1917case Mips::BGTZ_MM:1918case Mips::BLEZ_MM:1919case Mips::BLTZ_MM:1920case Mips::BGEZAL_MM:1921case Mips::BLTZAL_MM:1922case Mips::BC1F_MM:1923case Mips::BC1T_MM:1924case Mips::BC1EQZC_MMR6:1925case Mips::BC1NEZC_MMR6:1926case Mips::BC2EQZC_MMR6:1927case Mips::BC2NEZC_MMR6:1928assert(MCID.getNumOperands() == 2 && "unexpected number of operands");1929Offset = Inst.getOperand(1);1930if (!Offset.isImm())1931break; // We'll deal with this situation later on when applying fixups.1932if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))1933return Error(IDLoc, "branch target out of range");1934if (offsetToAlignment(Offset.getImm(),1935(inMicroMipsMode() ? Align(2) : Align(4))))1936return Error(IDLoc, "branch to misaligned address");1937break;1938case Mips::BGEC: case Mips::BGEC_MMR6:1939case Mips::BLTC: case Mips::BLTC_MMR6:1940case Mips::BGEUC: case Mips::BGEUC_MMR6:1941case Mips::BLTUC: case Mips::BLTUC_MMR6:1942case Mips::BEQC: case Mips::BEQC_MMR6:1943case Mips::BNEC: case Mips::BNEC_MMR6:1944assert(MCID.getNumOperands() == 3 && "unexpected number of operands");1945Offset = Inst.getOperand(2);1946if (!Offset.isImm())1947break; // We'll deal with this situation later on when applying fixups.1948if (!isIntN(18, Offset.getImm()))1949return Error(IDLoc, "branch target out of range");1950if (offsetToAlignment(Offset.getImm(), Align(4)))1951return Error(IDLoc, "branch to misaligned address");1952break;1953case Mips::BLEZC: case Mips::BLEZC_MMR6:1954case Mips::BGEZC: case Mips::BGEZC_MMR6:1955case Mips::BGTZC: case Mips::BGTZC_MMR6:1956case Mips::BLTZC: case Mips::BLTZC_MMR6:1957assert(MCID.getNumOperands() == 2 && "unexpected number of operands");1958Offset = Inst.getOperand(1);1959if (!Offset.isImm())1960break; // We'll deal with this situation later on when applying fixups.1961if (!isIntN(18, Offset.getImm()))1962return Error(IDLoc, "branch target out of range");1963if (offsetToAlignment(Offset.getImm(), Align(4)))1964return Error(IDLoc, "branch to misaligned address");1965break;1966case Mips::BEQZC: case Mips::BEQZC_MMR6:1967case Mips::BNEZC: case Mips::BNEZC_MMR6:1968assert(MCID.getNumOperands() == 2 && "unexpected number of operands");1969Offset = Inst.getOperand(1);1970if (!Offset.isImm())1971break; // We'll deal with this situation later on when applying fixups.1972if (!isIntN(23, Offset.getImm()))1973return Error(IDLoc, "branch target out of range");1974if (offsetToAlignment(Offset.getImm(), Align(4)))1975return Error(IDLoc, "branch to misaligned address");1976break;1977case Mips::BEQZ16_MM:1978case Mips::BEQZC16_MMR6:1979case Mips::BNEZ16_MM:1980case Mips::BNEZC16_MMR6:1981assert(MCID.getNumOperands() == 2 && "unexpected number of operands");1982Offset = Inst.getOperand(1);1983if (!Offset.isImm())1984break; // We'll deal with this situation later on when applying fixups.1985if (!isInt<8>(Offset.getImm()))1986return Error(IDLoc, "branch target out of range");1987if (offsetToAlignment(Offset.getImm(), Align(2)))1988return Error(IDLoc, "branch to misaligned address");1989break;1990}1991}19921993// SSNOP is deprecated on MIPS32r6/MIPS64r61994// We still accept it but it is a normal nop.1995if (hasMips32r6() && Opcode == Mips::SSNOP) {1996std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";1997Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "1998"nop instruction");1999}20002001if (hasCnMips()) {2002MCOperand Opnd;2003int Imm;20042005switch (Opcode) {2006default:2007break;20082009case Mips::BBIT0:2010case Mips::BBIT032:2011case Mips::BBIT1:2012case Mips::BBIT132:2013assert(MCID.getNumOperands() == 3 && "unexpected number of operands");2014// The offset is handled above2015Opnd = Inst.getOperand(1);2016if (!Opnd.isImm())2017return Error(IDLoc, "expected immediate operand kind");2018Imm = Opnd.getImm();2019if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||2020Opcode == Mips::BBIT1 ? 63 : 31))2021return Error(IDLoc, "immediate operand value out of range");2022if (Imm > 31) {2023Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT0322024: Mips::BBIT132);2025Inst.getOperand(1).setImm(Imm - 32);2026}2027break;20282029case Mips::SEQi:2030case Mips::SNEi:2031assert(MCID.getNumOperands() == 3 && "unexpected number of operands");2032Opnd = Inst.getOperand(2);2033if (!Opnd.isImm())2034return Error(IDLoc, "expected immediate operand kind");2035Imm = Opnd.getImm();2036if (!isInt<10>(Imm))2037return Error(IDLoc, "immediate operand value out of range");2038break;2039}2040}20412042// Warn on division by zero. We're checking here as all instructions get2043// processed here, not just the macros that need expansion.2044//2045// The MIPS backend models most of the divison instructions and macros as2046// three operand instructions. The pre-R6 divide instructions however have2047// two operands and explicitly define HI/LO as part of the instruction,2048// not in the operands.2049unsigned FirstOp = 1;2050unsigned SecondOp = 2;2051switch (Opcode) {2052default:2053break;2054case Mips::SDivIMacro:2055case Mips::UDivIMacro:2056case Mips::DSDivIMacro:2057case Mips::DUDivIMacro:2058if (Inst.getOperand(2).getImm() == 0) {2059if (Inst.getOperand(1).getReg() == Mips::ZERO ||2060Inst.getOperand(1).getReg() == Mips::ZERO_64)2061Warning(IDLoc, "dividing zero by zero");2062else2063Warning(IDLoc, "division by zero");2064}2065break;2066case Mips::DSDIV:2067case Mips::SDIV:2068case Mips::UDIV:2069case Mips::DUDIV:2070case Mips::UDIV_MM:2071case Mips::SDIV_MM:2072FirstOp = 0;2073SecondOp = 1;2074[[fallthrough]];2075case Mips::SDivMacro:2076case Mips::DSDivMacro:2077case Mips::UDivMacro:2078case Mips::DUDivMacro:2079case Mips::DIV:2080case Mips::DIVU:2081case Mips::DDIV:2082case Mips::DDIVU:2083case Mips::DIVU_MMR6:2084case Mips::DIV_MMR6:2085if (Inst.getOperand(SecondOp).getReg() == Mips::ZERO ||2086Inst.getOperand(SecondOp).getReg() == Mips::ZERO_64) {2087if (Inst.getOperand(FirstOp).getReg() == Mips::ZERO ||2088Inst.getOperand(FirstOp).getReg() == Mips::ZERO_64)2089Warning(IDLoc, "dividing zero by zero");2090else2091Warning(IDLoc, "division by zero");2092}2093break;2094}20952096// For PIC code convert unconditional jump to unconditional branch.2097if ((Opcode == Mips::J || Opcode == Mips::J_MM) && inPicMode()) {2098MCInst BInst;2099BInst.setOpcode(inMicroMipsMode() ? Mips::BEQ_MM : Mips::BEQ);2100BInst.addOperand(MCOperand::createReg(Mips::ZERO));2101BInst.addOperand(MCOperand::createReg(Mips::ZERO));2102BInst.addOperand(Inst.getOperand(0));2103Inst = BInst;2104}21052106// This expansion is not in a function called by tryExpandInstruction()2107// because the pseudo-instruction doesn't have a distinct opcode.2108if ((Opcode == Mips::JAL || Opcode == Mips::JAL_MM) && inPicMode()) {2109warnIfNoMacro(IDLoc);21102111const MCExpr *JalExpr = Inst.getOperand(0).getExpr();21122113// We can do this expansion if there's only 1 symbol in the argument2114// expression.2115if (countMCSymbolRefExpr(JalExpr) > 1)2116return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");21172118// FIXME: This is checking the expression can be handled by the later stages2119// of the assembler. We ought to leave it to those later stages.2120const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);21212122if (expandLoadAddress(Mips::T9, Mips::NoRegister, Inst.getOperand(0),2123!isGP64bit(), IDLoc, Out, STI))2124return true;21252126MCInst JalrInst;2127if (inMicroMipsMode())2128JalrInst.setOpcode(IsCpRestoreSet ? Mips::JALRS_MM : Mips::JALR_MM);2129else2130JalrInst.setOpcode(Mips::JALR);2131JalrInst.addOperand(MCOperand::createReg(Mips::RA));2132JalrInst.addOperand(MCOperand::createReg(Mips::T9));21332134if (isJalrRelocAvailable(JalExpr)) {2135// As an optimization hint for the linker, before the JALR we add:2136// .reloc tmplabel, R_{MICRO}MIPS_JALR, symbol2137// tmplabel:2138MCSymbol *TmpLabel = getContext().createTempSymbol();2139const MCExpr *TmpExpr = MCSymbolRefExpr::create(TmpLabel, getContext());2140const MCExpr *RelocJalrExpr =2141MCSymbolRefExpr::create(JalSym, MCSymbolRefExpr::VK_None,2142getContext(), IDLoc);21432144TOut.getStreamer().emitRelocDirective(2145*TmpExpr, inMicroMipsMode() ? "R_MICROMIPS_JALR" : "R_MIPS_JALR",2146RelocJalrExpr, IDLoc, *STI);2147TOut.getStreamer().emitLabel(TmpLabel);2148}21492150Inst = JalrInst;2151ExpandedJalSym = true;2152}21532154if (MCID.mayLoad() || MCID.mayStore()) {2155// Check the offset of memory operand, if it is a symbol2156// reference or immediate we may have to expand instructions.2157if (needsExpandMemInst(Inst, MCID)) {2158switch (MCID.operands()[MCID.getNumOperands() - 1].OperandType) {2159case MipsII::OPERAND_MEM_SIMM9:2160expandMem9Inst(Inst, IDLoc, Out, STI, MCID.mayLoad());2161break;2162default:2163expandMem16Inst(Inst, IDLoc, Out, STI, MCID.mayLoad());2164break;2165}2166return getParser().hasPendingError();2167}2168}21692170if (inMicroMipsMode()) {2171if (MCID.mayLoad() && Opcode != Mips::LWP_MM) {2172// Try to create 16-bit GP relative load instruction.2173for (unsigned i = 0; i < MCID.getNumOperands(); i++) {2174const MCOperandInfo &OpInfo = MCID.operands()[i];2175if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||2176(OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {2177MCOperand &Op = Inst.getOperand(i);2178if (Op.isImm()) {2179int MemOffset = Op.getImm();2180MCOperand &DstReg = Inst.getOperand(0);2181MCOperand &BaseReg = Inst.getOperand(1);2182if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&2183getContext().getRegisterInfo()->getRegClass(2184Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&2185(BaseReg.getReg() == Mips::GP ||2186BaseReg.getReg() == Mips::GP_64)) {21872188TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,2189IDLoc, STI);2190return false;2191}2192}2193}2194} // for2195} // if load21962197// TODO: Handle this with the AsmOperandClass.PredicateMethod.21982199MCOperand Opnd;2200int Imm;22012202switch (Opcode) {2203default:2204break;2205case Mips::ADDIUSP_MM:2206Opnd = Inst.getOperand(0);2207if (!Opnd.isImm())2208return Error(IDLoc, "expected immediate operand kind");2209Imm = Opnd.getImm();2210if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||2211Imm % 4 != 0)2212return Error(IDLoc, "immediate operand value out of range");2213break;2214case Mips::SLL16_MM:2215case Mips::SRL16_MM:2216Opnd = Inst.getOperand(2);2217if (!Opnd.isImm())2218return Error(IDLoc, "expected immediate operand kind");2219Imm = Opnd.getImm();2220if (Imm < 1 || Imm > 8)2221return Error(IDLoc, "immediate operand value out of range");2222break;2223case Mips::LI16_MM:2224Opnd = Inst.getOperand(1);2225if (!Opnd.isImm())2226return Error(IDLoc, "expected immediate operand kind");2227Imm = Opnd.getImm();2228if (Imm < -1 || Imm > 126)2229return Error(IDLoc, "immediate operand value out of range");2230break;2231case Mips::ADDIUR2_MM:2232Opnd = Inst.getOperand(2);2233if (!Opnd.isImm())2234return Error(IDLoc, "expected immediate operand kind");2235Imm = Opnd.getImm();2236if (!(Imm == 1 || Imm == -1 ||2237((Imm % 4 == 0) && Imm < 28 && Imm > 0)))2238return Error(IDLoc, "immediate operand value out of range");2239break;2240case Mips::ANDI16_MM:2241Opnd = Inst.getOperand(2);2242if (!Opnd.isImm())2243return Error(IDLoc, "expected immediate operand kind");2244Imm = Opnd.getImm();2245if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||2246Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||2247Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))2248return Error(IDLoc, "immediate operand value out of range");2249break;2250case Mips::LBU16_MM:2251Opnd = Inst.getOperand(2);2252if (!Opnd.isImm())2253return Error(IDLoc, "expected immediate operand kind");2254Imm = Opnd.getImm();2255if (Imm < -1 || Imm > 14)2256return Error(IDLoc, "immediate operand value out of range");2257break;2258case Mips::SB16_MM:2259case Mips::SB16_MMR6:2260Opnd = Inst.getOperand(2);2261if (!Opnd.isImm())2262return Error(IDLoc, "expected immediate operand kind");2263Imm = Opnd.getImm();2264if (Imm < 0 || Imm > 15)2265return Error(IDLoc, "immediate operand value out of range");2266break;2267case Mips::LHU16_MM:2268case Mips::SH16_MM:2269case Mips::SH16_MMR6:2270Opnd = Inst.getOperand(2);2271if (!Opnd.isImm())2272return Error(IDLoc, "expected immediate operand kind");2273Imm = Opnd.getImm();2274if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))2275return Error(IDLoc, "immediate operand value out of range");2276break;2277case Mips::LW16_MM:2278case Mips::SW16_MM:2279case Mips::SW16_MMR6:2280Opnd = Inst.getOperand(2);2281if (!Opnd.isImm())2282return Error(IDLoc, "expected immediate operand kind");2283Imm = Opnd.getImm();2284if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))2285return Error(IDLoc, "immediate operand value out of range");2286break;2287case Mips::ADDIUPC_MM:2288Opnd = Inst.getOperand(1);2289if (!Opnd.isImm())2290return Error(IDLoc, "expected immediate operand kind");2291Imm = Opnd.getImm();2292if ((Imm % 4 != 0) || !isInt<25>(Imm))2293return Error(IDLoc, "immediate operand value out of range");2294break;2295case Mips::LWP_MM:2296case Mips::SWP_MM:2297if (Inst.getOperand(0).getReg() == Mips::RA)2298return Error(IDLoc, "invalid operand for instruction");2299break;2300case Mips::MOVEP_MM:2301case Mips::MOVEP_MMR6: {2302unsigned R0 = Inst.getOperand(0).getReg();2303unsigned R1 = Inst.getOperand(1).getReg();2304bool RegPair = ((R0 == Mips::A1 && R1 == Mips::A2) ||2305(R0 == Mips::A1 && R1 == Mips::A3) ||2306(R0 == Mips::A2 && R1 == Mips::A3) ||2307(R0 == Mips::A0 && R1 == Mips::S5) ||2308(R0 == Mips::A0 && R1 == Mips::S6) ||2309(R0 == Mips::A0 && R1 == Mips::A1) ||2310(R0 == Mips::A0 && R1 == Mips::A2) ||2311(R0 == Mips::A0 && R1 == Mips::A3));2312if (!RegPair)2313return Error(IDLoc, "invalid operand for instruction");2314break;2315}2316}2317}23182319bool FillDelaySlot =2320MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();23212322// Get previous instruction`s forbidden slot attribute and2323// whether set reorder.2324bool PrevForbiddenSlotAttr = CurForbiddenSlotAttr;23252326// Flag represents we set reorder after nop.2327bool SetReorderAfterNop = false;23282329// If previous instruction has forbidden slot and .set reorder2330// is active and current instruction is CTI.2331// Then emit a NOP after it.2332if (PrevForbiddenSlotAttr && !SafeInForbiddenSlot(MCID)) {2333TOut.emitEmptyDelaySlot(false, IDLoc, STI);2334// When 'FillDelaySlot' is true, the existing logic will add2335// noreorder before instruction and reorder after it. So there2336// need exclude this case avoiding two '.set reorder'.2337// The format of the first case is:2338// .set noreorder2339// bnezc2340// nop2341// .set reorder2342if (AssemblerOptions.back()->isReorder() && !FillDelaySlot) {2343SetReorderAfterNop = true;2344TOut.emitDirectiveSetReorder();2345}2346}23472348// Save current instruction`s forbidden slot and whether set reorder.2349// This is the judgment condition for whether to add nop.2350// We would add a couple of '.set noreorder' and '.set reorder' to2351// wrap the current instruction and the next instruction.2352CurForbiddenSlotAttr =2353hasForbiddenSlot(MCID) && AssemblerOptions.back()->isReorder();23542355if (FillDelaySlot || CurForbiddenSlotAttr)2356TOut.emitDirectiveSetNoReorder();23572358MacroExpanderResultTy ExpandResult =2359tryExpandInstruction(Inst, IDLoc, Out, STI);2360switch (ExpandResult) {2361case MER_NotAMacro:2362Out.emitInstruction(Inst, *STI);2363break;2364case MER_Success:2365break;2366case MER_Fail:2367return true;2368}23692370// When current instruction was not CTI, recover reorder state.2371// The format of the second case is:2372// .set noreoder2373// bnezc2374// add2375// .set reorder2376if (PrevForbiddenSlotAttr && !SetReorderAfterNop && !FillDelaySlot &&2377AssemblerOptions.back()->isReorder()) {2378TOut.emitDirectiveSetReorder();2379}23802381// We know we emitted an instruction on the MER_NotAMacro or MER_Success path.2382// If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.2383if (inMicroMipsMode()) {2384TOut.setUsesMicroMips();2385TOut.updateABIInfo(*this);2386}23872388// If this instruction has a delay slot and .set reorder is active,2389// emit a NOP after it.2390// The format of the third case is:2391// .set noreorder2392// bnezc2393// nop2394// .set noreorder2395// j2396// nop2397// .set reorder2398if (FillDelaySlot) {2399TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst), IDLoc, STI);2400TOut.emitDirectiveSetReorder();2401}24022403if ((Opcode == Mips::JalOneReg || Opcode == Mips::JalTwoReg ||2404ExpandedJalSym) &&2405isPicAndNotNxxAbi()) {2406if (IsCpRestoreSet) {2407// We need a NOP between the JALR and the LW:2408// If .set reorder has been used, we've already emitted a NOP.2409// If .set noreorder has been used, we need to emit a NOP at this point.2410if (!AssemblerOptions.back()->isReorder())2411TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst), IDLoc,2412STI);24132414// Load the $gp from the stack.2415TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);2416} else2417Warning(IDLoc, "no .cprestore used in PIC mode");2418}24192420return false;2421}24222423void MipsAsmParser::onEndOfFile() {2424MipsTargetStreamer &TOut = getTargetStreamer();2425SMLoc IDLoc = SMLoc();2426// If has pending forbidden slot, fill nop and recover reorder.2427if (CurForbiddenSlotAttr) {2428TOut.emitEmptyDelaySlot(false, IDLoc, STI);2429if (AssemblerOptions.back()->isReorder())2430TOut.emitDirectiveSetReorder();2431}2432}24332434MipsAsmParser::MacroExpanderResultTy2435MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,2436const MCSubtargetInfo *STI) {2437switch (Inst.getOpcode()) {2438default:2439return MER_NotAMacro;2440case Mips::LoadImm32:2441return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;2442case Mips::LoadImm64:2443return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;2444case Mips::LoadAddrImm32:2445case Mips::LoadAddrImm64:2446assert(Inst.getOperand(0).isReg() && "expected register operand kind");2447assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&2448"expected immediate operand kind");24492450return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,2451Inst.getOperand(1),2452Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,2453Out, STI)2454? MER_Fail2455: MER_Success;2456case Mips::LoadAddrReg32:2457case Mips::LoadAddrReg64:2458assert(Inst.getOperand(0).isReg() && "expected register operand kind");2459assert(Inst.getOperand(1).isReg() && "expected register operand kind");2460assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&2461"expected immediate operand kind");24622463return expandLoadAddress(Inst.getOperand(0).getReg(),2464Inst.getOperand(1).getReg(), Inst.getOperand(2),2465Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,2466Out, STI)2467? MER_Fail2468: MER_Success;2469case Mips::B_MM_Pseudo:2470case Mips::B_MMR6_Pseudo:2471return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail2472: MER_Success;2473case Mips::SWM_MM:2474case Mips::LWM_MM:2475return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail2476: MER_Success;2477case Mips::JalOneReg:2478case Mips::JalTwoReg:2479return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2480case Mips::BneImm:2481case Mips::BeqImm:2482case Mips::BEQLImmMacro:2483case Mips::BNELImmMacro:2484return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2485case Mips::BLT:2486case Mips::BLE:2487case Mips::BGE:2488case Mips::BGT:2489case Mips::BLTU:2490case Mips::BLEU:2491case Mips::BGEU:2492case Mips::BGTU:2493case Mips::BLTL:2494case Mips::BLEL:2495case Mips::BGEL:2496case Mips::BGTL:2497case Mips::BLTUL:2498case Mips::BLEUL:2499case Mips::BGEUL:2500case Mips::BGTUL:2501case Mips::BLTImmMacro:2502case Mips::BLEImmMacro:2503case Mips::BGEImmMacro:2504case Mips::BGTImmMacro:2505case Mips::BLTUImmMacro:2506case Mips::BLEUImmMacro:2507case Mips::BGEUImmMacro:2508case Mips::BGTUImmMacro:2509case Mips::BLTLImmMacro:2510case Mips::BLELImmMacro:2511case Mips::BGELImmMacro:2512case Mips::BGTLImmMacro:2513case Mips::BLTULImmMacro:2514case Mips::BLEULImmMacro:2515case Mips::BGEULImmMacro:2516case Mips::BGTULImmMacro:2517return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2518case Mips::SDivMacro:2519case Mips::SDivIMacro:2520case Mips::SRemMacro:2521case Mips::SRemIMacro:2522return expandDivRem(Inst, IDLoc, Out, STI, false, true) ? MER_Fail2523: MER_Success;2524case Mips::DSDivMacro:2525case Mips::DSDivIMacro:2526case Mips::DSRemMacro:2527case Mips::DSRemIMacro:2528return expandDivRem(Inst, IDLoc, Out, STI, true, true) ? MER_Fail2529: MER_Success;2530case Mips::UDivMacro:2531case Mips::UDivIMacro:2532case Mips::URemMacro:2533case Mips::URemIMacro:2534return expandDivRem(Inst, IDLoc, Out, STI, false, false) ? MER_Fail2535: MER_Success;2536case Mips::DUDivMacro:2537case Mips::DUDivIMacro:2538case Mips::DURemMacro:2539case Mips::DURemIMacro:2540return expandDivRem(Inst, IDLoc, Out, STI, true, false) ? MER_Fail2541: MER_Success;2542case Mips::PseudoTRUNC_W_S:2543return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail2544: MER_Success;2545case Mips::PseudoTRUNC_W_D32:2546return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail2547: MER_Success;2548case Mips::PseudoTRUNC_W_D:2549return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail2550: MER_Success;25512552case Mips::LoadImmSingleGPR:2553return expandLoadSingleImmToGPR(Inst, IDLoc, Out, STI) ? MER_Fail2554: MER_Success;2555case Mips::LoadImmSingleFGR:2556return expandLoadSingleImmToFPR(Inst, IDLoc, Out, STI) ? MER_Fail2557: MER_Success;2558case Mips::LoadImmDoubleGPR:2559return expandLoadDoubleImmToGPR(Inst, IDLoc, Out, STI) ? MER_Fail2560: MER_Success;2561case Mips::LoadImmDoubleFGR:2562return expandLoadDoubleImmToFPR(Inst, true, IDLoc, Out, STI) ? MER_Fail2563: MER_Success;2564case Mips::LoadImmDoubleFGR_32:2565return expandLoadDoubleImmToFPR(Inst, false, IDLoc, Out, STI) ? MER_Fail2566: MER_Success;25672568case Mips::Ulh:2569return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;2570case Mips::Ulhu:2571return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;2572case Mips::Ush:2573return expandUsh(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2574case Mips::Ulw:2575case Mips::Usw:2576return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2577case Mips::NORImm:2578case Mips::NORImm64:2579return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2580case Mips::SGE:2581case Mips::SGEU:2582return expandSge(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2583case Mips::SGEImm:2584case Mips::SGEUImm:2585case Mips::SGEImm64:2586case Mips::SGEUImm64:2587return expandSgeImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2588case Mips::SGTImm:2589case Mips::SGTUImm:2590case Mips::SGTImm64:2591case Mips::SGTUImm64:2592return expandSgtImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2593case Mips::SLE:2594case Mips::SLEU:2595return expandSle(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2596case Mips::SLEImm:2597case Mips::SLEUImm:2598case Mips::SLEImm64:2599case Mips::SLEUImm64:2600return expandSleImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2601case Mips::SLTImm64:2602if (isInt<16>(Inst.getOperand(2).getImm())) {2603Inst.setOpcode(Mips::SLTi64);2604return MER_NotAMacro;2605}2606return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2607case Mips::SLTUImm64:2608if (isInt<16>(Inst.getOperand(2).getImm())) {2609Inst.setOpcode(Mips::SLTiu64);2610return MER_NotAMacro;2611}2612return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2613case Mips::ADDi: case Mips::ADDi_MM:2614case Mips::ADDiu: case Mips::ADDiu_MM:2615case Mips::SLTi: case Mips::SLTi_MM:2616case Mips::SLTiu: case Mips::SLTiu_MM:2617if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&2618Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {2619int64_t ImmValue = Inst.getOperand(2).getImm();2620if (isInt<16>(ImmValue))2621return MER_NotAMacro;2622return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail2623: MER_Success;2624}2625return MER_NotAMacro;2626case Mips::ANDi: case Mips::ANDi_MM: case Mips::ANDi64:2627case Mips::ORi: case Mips::ORi_MM: case Mips::ORi64:2628case Mips::XORi: case Mips::XORi_MM: case Mips::XORi64:2629if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&2630Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {2631int64_t ImmValue = Inst.getOperand(2).getImm();2632if (isUInt<16>(ImmValue))2633return MER_NotAMacro;2634return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail2635: MER_Success;2636}2637return MER_NotAMacro;2638case Mips::ROL:2639case Mips::ROR:2640return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2641case Mips::ROLImm:2642case Mips::RORImm:2643return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2644case Mips::DROL:2645case Mips::DROR:2646return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2647case Mips::DROLImm:2648case Mips::DRORImm:2649return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2650case Mips::ABSMacro:2651return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2652case Mips::MULImmMacro:2653case Mips::DMULImmMacro:2654return expandMulImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2655case Mips::MULOMacro:2656case Mips::DMULOMacro:2657return expandMulO(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2658case Mips::MULOUMacro:2659case Mips::DMULOUMacro:2660return expandMulOU(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2661case Mips::DMULMacro:2662return expandDMULMacro(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2663case Mips::LDMacro:2664case Mips::SDMacro:2665return expandLoadStoreDMacro(Inst, IDLoc, Out, STI,2666Inst.getOpcode() == Mips::LDMacro)2667? MER_Fail2668: MER_Success;2669case Mips::SDC1_M1:2670return expandStoreDM1Macro(Inst, IDLoc, Out, STI)2671? MER_Fail2672: MER_Success;2673case Mips::SEQMacro:2674return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2675case Mips::SEQIMacro:2676return expandSeqI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2677case Mips::SNEMacro:2678return expandSne(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2679case Mips::SNEIMacro:2680return expandSneI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2681case Mips::MFTC0: case Mips::MTTC0:2682case Mips::MFTGPR: case Mips::MTTGPR:2683case Mips::MFTLO: case Mips::MTTLO:2684case Mips::MFTHI: case Mips::MTTHI:2685case Mips::MFTACX: case Mips::MTTACX:2686case Mips::MFTDSP: case Mips::MTTDSP:2687case Mips::MFTC1: case Mips::MTTC1:2688case Mips::MFTHC1: case Mips::MTTHC1:2689case Mips::CFTC1: case Mips::CTTC1:2690return expandMXTRAlias(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2691case Mips::SaaAddr:2692case Mips::SaadAddr:2693return expandSaaAddr(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2694}2695}26962697bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,2698MCStreamer &Out,2699const MCSubtargetInfo *STI) {2700MipsTargetStreamer &TOut = getTargetStreamer();27012702// Create a JALR instruction which is going to replace the pseudo-JAL.2703MCInst JalrInst;2704JalrInst.setLoc(IDLoc);2705const MCOperand FirstRegOp = Inst.getOperand(0);2706const unsigned Opcode = Inst.getOpcode();27072708if (Opcode == Mips::JalOneReg) {2709// jal $rs => jalr $rs2710if (IsCpRestoreSet && inMicroMipsMode()) {2711JalrInst.setOpcode(Mips::JALRS16_MM);2712JalrInst.addOperand(FirstRegOp);2713} else if (inMicroMipsMode()) {2714JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);2715JalrInst.addOperand(FirstRegOp);2716} else {2717JalrInst.setOpcode(Mips::JALR);2718JalrInst.addOperand(MCOperand::createReg(Mips::RA));2719JalrInst.addOperand(FirstRegOp);2720}2721} else if (Opcode == Mips::JalTwoReg) {2722// jal $rd, $rs => jalr $rd, $rs2723if (IsCpRestoreSet && inMicroMipsMode())2724JalrInst.setOpcode(Mips::JALRS_MM);2725else2726JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);2727JalrInst.addOperand(FirstRegOp);2728const MCOperand SecondRegOp = Inst.getOperand(1);2729JalrInst.addOperand(SecondRegOp);2730}2731Out.emitInstruction(JalrInst, *STI);27322733// If .set reorder is active and branch instruction has a delay slot,2734// emit a NOP after it.2735const MCInstrDesc &MCID = MII.get(JalrInst.getOpcode());2736if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())2737TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst), IDLoc,2738STI);27392740return false;2741}27422743/// Can the value be represented by a unsigned N-bit value and a shift left?2744template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {2745return x && isUInt<N>(x >> llvm::countr_zero(x));2746}27472748/// Load (or add) an immediate into a register.2749///2750/// @param ImmValue The immediate to load.2751/// @param DstReg The register that will hold the immediate.2752/// @param SrcReg A register to add to the immediate or Mips::NoRegister2753/// for a simple initialization.2754/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?2755/// @param IsAddress True if the immediate represents an address. False if it2756/// is an integer.2757/// @param IDLoc Location of the immediate in the source file.2758bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,2759unsigned SrcReg, bool Is32BitImm,2760bool IsAddress, SMLoc IDLoc, MCStreamer &Out,2761const MCSubtargetInfo *STI) {2762MipsTargetStreamer &TOut = getTargetStreamer();27632764if (!Is32BitImm && !isGP64bit()) {2765Error(IDLoc, "instruction requires a 64-bit architecture");2766return true;2767}27682769if (Is32BitImm) {2770if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {2771// Sign extend up to 64-bit so that the predicates match the hardware2772// behaviour. In particular, isInt<16>(0xffff8000) and similar should be2773// true.2774ImmValue = SignExtend64<32>(ImmValue);2775} else {2776Error(IDLoc, "instruction requires a 32-bit immediate");2777return true;2778}2779}27802781unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();2782unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;27832784bool UseSrcReg = false;2785if (SrcReg != Mips::NoRegister)2786UseSrcReg = true;27872788unsigned TmpReg = DstReg;2789if (UseSrcReg &&2790getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {2791// At this point we need AT to perform the expansions and we exit if it is2792// not available.2793unsigned ATReg = getATReg(IDLoc);2794if (!ATReg)2795return true;2796TmpReg = ATReg;2797}27982799if (isInt<16>(ImmValue)) {2800if (!UseSrcReg)2801SrcReg = ZeroReg;28022803// This doesn't quite follow the usual ABI expectations for N32 but matches2804// traditional assembler behaviour. N32 would normally use addiu for both2805// integers and addresses.2806if (IsAddress && !Is32BitImm) {2807TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);2808return false;2809}28102811TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);2812return false;2813}28142815if (isUInt<16>(ImmValue)) {2816unsigned TmpReg = DstReg;2817if (SrcReg == DstReg) {2818TmpReg = getATReg(IDLoc);2819if (!TmpReg)2820return true;2821}28222823TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);2824if (UseSrcReg)2825TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);2826return false;2827}28282829if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {2830warnIfNoMacro(IDLoc);28312832uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;2833uint16_t Bits15To0 = ImmValue & 0xffff;2834if (!Is32BitImm && !isInt<32>(ImmValue)) {2835// Traditional behaviour seems to special case this particular value. It's2836// not clear why other masks are handled differently.2837if (ImmValue == 0xffffffff) {2838TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);2839TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);2840if (UseSrcReg)2841TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);2842return false;2843}28442845// Expand to an ORi instead of a LUi to avoid sign-extending into the2846// upper 32 bits.2847TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);2848TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);2849if (Bits15To0)2850TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);2851if (UseSrcReg)2852TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);2853return false;2854}28552856TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);2857if (Bits15To0)2858TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);2859if (UseSrcReg)2860TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);2861return false;2862}28632864if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {2865if (Is32BitImm) {2866Error(IDLoc, "instruction requires a 32-bit immediate");2867return true;2868}28692870// We've processed ImmValue satisfying isUInt<16> above, so ImmValue must be2871// at least 17-bit wide here.2872unsigned BitWidth = llvm::bit_width((uint64_t)ImmValue);2873assert(BitWidth >= 17 && "ImmValue must be at least 17-bit wide");28742875// Traditionally, these immediates are shifted as little as possible and as2876// such we align the most significant bit to bit 15 of our temporary.2877unsigned ShiftAmount = BitWidth - 16;2878uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;2879TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);2880TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);28812882if (UseSrcReg)2883TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);28842885return false;2886}28872888warnIfNoMacro(IDLoc);28892890// The remaining case is packed with a sequence of dsll and ori with zeros2891// being omitted and any neighbouring dsll's being coalesced.2892// The highest 32-bit's are equivalent to a 32-bit immediate load.28932894// Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.2895if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,2896IDLoc, Out, STI))2897return false;28982899// Shift and accumulate into the register. If a 16-bit chunk is zero, then2900// skip it and defer the shift to the next chunk.2901unsigned ShiftCarriedForwards = 16;2902for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {2903uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;29042905if (ImmChunk != 0) {2906TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);2907TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);2908ShiftCarriedForwards = 0;2909}29102911ShiftCarriedForwards += 16;2912}2913ShiftCarriedForwards -= 16;29142915// Finish any remaining shifts left by trailing zeros.2916if (ShiftCarriedForwards)2917TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);29182919if (UseSrcReg)2920TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);29212922return false;2923}29242925bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,2926MCStreamer &Out, const MCSubtargetInfo *STI) {2927const MCOperand &ImmOp = Inst.getOperand(1);2928assert(ImmOp.isImm() && "expected immediate operand kind");2929const MCOperand &DstRegOp = Inst.getOperand(0);2930assert(DstRegOp.isReg() && "expected register operand kind");29312932if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,2933Is32BitImm, false, IDLoc, Out, STI))2934return true;29352936return false;2937}29382939bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,2940const MCOperand &Offset,2941bool Is32BitAddress, SMLoc IDLoc,2942MCStreamer &Out,2943const MCSubtargetInfo *STI) {2944// la can't produce a usable address when addresses are 64-bit.2945if (Is32BitAddress && ABI.ArePtrs64bit()) {2946Warning(IDLoc, "la used to load 64-bit address");2947// Continue as if we had 'dla' instead.2948Is32BitAddress = false;2949}29502951// dla requires 64-bit addresses.2952if (!Is32BitAddress && !hasMips3()) {2953Error(IDLoc, "instruction requires a 64-bit architecture");2954return true;2955}29562957if (!Offset.isImm())2958return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,2959Is32BitAddress, IDLoc, Out, STI);29602961if (!ABI.ArePtrs64bit()) {2962// Continue as if we had 'la' whether we had 'la' or 'dla'.2963Is32BitAddress = true;2964}29652966return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,2967IDLoc, Out, STI);2968}29692970bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,2971unsigned DstReg, unsigned SrcReg,2972bool Is32BitSym, SMLoc IDLoc,2973MCStreamer &Out,2974const MCSubtargetInfo *STI) {2975MipsTargetStreamer &TOut = getTargetStreamer();2976bool UseSrcReg = SrcReg != Mips::NoRegister && SrcReg != Mips::ZERO &&2977SrcReg != Mips::ZERO_64;2978warnIfNoMacro(IDLoc);29792980if (inPicMode()) {2981MCValue Res;2982if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {2983Error(IDLoc, "expected relocatable expression");2984return true;2985}2986if (Res.getSymB() != nullptr) {2987Error(IDLoc, "expected relocatable expression with only one symbol");2988return true;2989}29902991bool IsPtr64 = ABI.ArePtrs64bit();2992bool IsLocalSym =2993Res.getSymA()->getSymbol().isInSection() ||2994Res.getSymA()->getSymbol().isTemporary() ||2995(Res.getSymA()->getSymbol().isELF() &&2996cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==2997ELF::STB_LOCAL);2998// For O32, "$"-prefixed symbols are recognized as temporary while2999// .L-prefixed symbols are not (PrivateGlobalPrefix is "$"). Recognize ".L"3000// manually.3001if (ABI.IsO32() && Res.getSymA()->getSymbol().getName().starts_with(".L"))3002IsLocalSym = true;3003bool UseXGOT = STI->hasFeature(Mips::FeatureXGOT) && !IsLocalSym;30043005// The case where the result register is $25 is somewhat special. If the3006// symbol in the final relocation is external and not modified with a3007// constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT163008// or R_MIPS_CALL16 instead of R_MIPS_GOT_DISP in 64-bit case.3009if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&3010Res.getConstant() == 0 && !IsLocalSym) {3011if (UseXGOT) {3012const MCExpr *CallHiExpr = MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16,3013SymExpr, getContext());3014const MCExpr *CallLoExpr = MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16,3015SymExpr, getContext());3016TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(CallHiExpr), IDLoc,3017STI);3018TOut.emitRRR(IsPtr64 ? Mips::DADDu : Mips::ADDu, DstReg, DstReg, GPReg,3019IDLoc, STI);3020TOut.emitRRX(IsPtr64 ? Mips::LD : Mips::LW, DstReg, DstReg,3021MCOperand::createExpr(CallLoExpr), IDLoc, STI);3022} else {3023const MCExpr *CallExpr =3024MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());3025TOut.emitRRX(IsPtr64 ? Mips::LD : Mips::LW, DstReg, GPReg,3026MCOperand::createExpr(CallExpr), IDLoc, STI);3027}3028return false;3029}30303031unsigned TmpReg = DstReg;3032if (UseSrcReg &&3033getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,3034SrcReg)) {3035// If $rs is the same as $rd, we need to use AT.3036// If it is not available we exit.3037unsigned ATReg = getATReg(IDLoc);3038if (!ATReg)3039return true;3040TmpReg = ATReg;3041}30423043// FIXME: In case of N32 / N64 ABI and emabled XGOT, local addresses3044// loaded using R_MIPS_GOT_PAGE / R_MIPS_GOT_OFST pair of relocations.3045// FIXME: Implement XGOT for microMIPS.3046if (UseXGOT) {3047// Loading address from XGOT3048// External GOT: lui $tmp, %got_hi(symbol)($gp)3049// addu $tmp, $tmp, $gp3050// lw $tmp, %got_lo(symbol)($tmp)3051// >addiu $tmp, $tmp, offset3052// >addiu $rd, $tmp, $rs3053// The addiu's marked with a '>' may be omitted if they are redundant. If3054// this happens then the last instruction must use $rd as the result3055// register.3056const MCExpr *CallHiExpr =3057MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, SymExpr, getContext());3058const MCExpr *CallLoExpr = MipsMCExpr::create(3059MipsMCExpr::MEK_GOT_LO16, Res.getSymA(), getContext());30603061TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(CallHiExpr), IDLoc,3062STI);3063TOut.emitRRR(IsPtr64 ? Mips::DADDu : Mips::ADDu, TmpReg, TmpReg, GPReg,3064IDLoc, STI);3065TOut.emitRRX(IsPtr64 ? Mips::LD : Mips::LW, TmpReg, TmpReg,3066MCOperand::createExpr(CallLoExpr), IDLoc, STI);30673068if (Res.getConstant() != 0)3069TOut.emitRRX(IsPtr64 ? Mips::DADDiu : Mips::ADDiu, TmpReg, TmpReg,3070MCOperand::createExpr(MCConstantExpr::create(3071Res.getConstant(), getContext())),3072IDLoc, STI);30733074if (UseSrcReg)3075TOut.emitRRR(IsPtr64 ? Mips::DADDu : Mips::ADDu, DstReg, TmpReg, SrcReg,3076IDLoc, STI);3077return false;3078}30793080const MipsMCExpr *GotExpr = nullptr;3081const MCExpr *LoExpr = nullptr;3082if (ABI.IsN32() || ABI.IsN64()) {3083// The remaining cases are:3084// Small offset: ld $tmp, %got_disp(symbol)($gp)3085// >daddiu $tmp, $tmp, offset3086// >daddu $rd, $tmp, $rs3087// The daddiu's marked with a '>' may be omitted if they are redundant. If3088// this happens then the last instruction must use $rd as the result3089// register.3090GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, Res.getSymA(),3091getContext());3092if (Res.getConstant() != 0) {3093// Symbols fully resolve with just the %got_disp(symbol) but we3094// must still account for any offset to the symbol for3095// expressions like symbol+8.3096LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());30973098// FIXME: Offsets greater than 16 bits are not yet implemented.3099// FIXME: The correct range is a 32-bit sign-extended number.3100if (Res.getConstant() < -0x8000 || Res.getConstant() > 0x7fff) {3101Error(IDLoc, "macro instruction uses large offset, which is not "3102"currently supported");3103return true;3104}3105}3106} else {3107// The remaining cases are:3108// External GOT: lw $tmp, %got(symbol)($gp)3109// >addiu $tmp, $tmp, offset3110// >addiu $rd, $tmp, $rs3111// Local GOT: lw $tmp, %got(symbol+offset)($gp)3112// addiu $tmp, $tmp, %lo(symbol+offset)($gp)3113// >addiu $rd, $tmp, $rs3114// The addiu's marked with a '>' may be omitted if they are redundant. If3115// this happens then the last instruction must use $rd as the result3116// register.3117if (IsLocalSym) {3118GotExpr =3119MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());3120LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());3121} else {3122// External symbols fully resolve the symbol with just the %got(symbol)3123// but we must still account for any offset to the symbol for3124// expressions like symbol+8.3125GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT, Res.getSymA(),3126getContext());3127if (Res.getConstant() != 0)3128LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());3129}3130}31313132TOut.emitRRX(IsPtr64 ? Mips::LD : Mips::LW, TmpReg, GPReg,3133MCOperand::createExpr(GotExpr), IDLoc, STI);31343135if (LoExpr)3136TOut.emitRRX(IsPtr64 ? Mips::DADDiu : Mips::ADDiu, TmpReg, TmpReg,3137MCOperand::createExpr(LoExpr), IDLoc, STI);31383139if (UseSrcReg)3140TOut.emitRRR(IsPtr64 ? Mips::DADDu : Mips::ADDu, DstReg, TmpReg, SrcReg,3141IDLoc, STI);31423143return false;3144}31453146const MipsMCExpr *HiExpr =3147MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());3148const MipsMCExpr *LoExpr =3149MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());31503151// This is the 64-bit symbol address expansion.3152if (ABI.ArePtrs64bit() && isGP64bit()) {3153// We need AT for the 64-bit expansion in the cases where the optional3154// source register is the destination register and for the superscalar3155// scheduled form.3156//3157// If it is not available we exit if the destination is the same as the3158// source register.31593160const MipsMCExpr *HighestExpr =3161MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());3162const MipsMCExpr *HigherExpr =3163MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());31643165bool RdRegIsRsReg =3166UseSrcReg &&3167getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg);31683169if (canUseATReg() && UseSrcReg && RdRegIsRsReg) {3170unsigned ATReg = getATReg(IDLoc);31713172// If $rs is the same as $rd:3173// (d)la $rd, sym($rd) => lui $at, %highest(sym)3174// daddiu $at, $at, %higher(sym)3175// dsll $at, $at, 163176// daddiu $at, $at, %hi(sym)3177// dsll $at, $at, 163178// daddiu $at, $at, %lo(sym)3179// daddu $rd, $at, $rd3180TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,3181STI);3182TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,3183MCOperand::createExpr(HigherExpr), IDLoc, STI);3184TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);3185TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),3186IDLoc, STI);3187TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);3188TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),3189IDLoc, STI);3190TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);31913192return false;3193} else if (canUseATReg() && !RdRegIsRsReg && DstReg != getATReg(IDLoc)) {3194unsigned ATReg = getATReg(IDLoc);31953196// If the $rs is different from $rd or if $rs isn't specified and we3197// have $at available:3198// (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)3199// lui $at, %hi(sym)3200// daddiu $rd, $rd, %higher(sym)3201// daddiu $at, $at, %lo(sym)3202// dsll32 $rd, $rd, 03203// daddu $rd, $rd, $at3204// (daddu $rd, $rd, $rs)3205//3206// Which is preferred for superscalar issue.3207TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,3208STI);3209TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);3210TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,3211MCOperand::createExpr(HigherExpr), IDLoc, STI);3212TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),3213IDLoc, STI);3214TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);3215TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);3216if (UseSrcReg)3217TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);32183219return false;3220} else if ((!canUseATReg() && !RdRegIsRsReg) ||3221(canUseATReg() && DstReg == getATReg(IDLoc))) {3222// Otherwise, synthesize the address in the destination register3223// serially:3224// (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)3225// daddiu $rd, $rd, %higher(sym)3226// dsll $rd, $rd, 163227// daddiu $rd, $rd, %hi(sym)3228// dsll $rd, $rd, 163229// daddiu $rd, $rd, %lo(sym)3230TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,3231STI);3232TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,3233MCOperand::createExpr(HigherExpr), IDLoc, STI);3234TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);3235TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,3236MCOperand::createExpr(HiExpr), IDLoc, STI);3237TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);3238TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,3239MCOperand::createExpr(LoExpr), IDLoc, STI);3240if (UseSrcReg)3241TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);32423243return false;3244} else {3245// We have a case where SrcReg == DstReg and we don't have $at3246// available. We can't expand this case, so error out appropriately.3247assert(SrcReg == DstReg && !canUseATReg() &&3248"Could have expanded dla but didn't?");3249reportParseError(IDLoc,3250"pseudo-instruction requires $at, which is not available");3251return true;3252}3253}32543255// And now, the 32-bit symbol address expansion:3256// If $rs is the same as $rd:3257// (d)la $rd, sym($rd) => lui $at, %hi(sym)3258// ori $at, $at, %lo(sym)3259// addu $rd, $at, $rd3260// Otherwise, if the $rs is different from $rd or if $rs isn't specified:3261// (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)3262// ori $rd, $rd, %lo(sym)3263// (addu $rd, $rd, $rs)3264unsigned TmpReg = DstReg;3265if (UseSrcReg &&3266getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {3267// If $rs is the same as $rd, we need to use AT.3268// If it is not available we exit.3269unsigned ATReg = getATReg(IDLoc);3270if (!ATReg)3271return true;3272TmpReg = ATReg;3273}32743275TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);3276TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),3277IDLoc, STI);32783279if (UseSrcReg)3280TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);3281else3282assert(3283getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));32843285return false;3286}32873288// Each double-precision register DO-D15 overlaps with two of the single3289// precision registers F0-F31. As an example, all of the following hold true:3290// D0 + 1 == F1, F1 + 1 == D1, F1 + 1 == F2, depending on the context.3291static unsigned nextReg(unsigned Reg) {3292if (MipsMCRegisterClasses[Mips::FGR32RegClassID].contains(Reg))3293return Reg == (unsigned)Mips::F31 ? (unsigned)Mips::F0 : Reg + 1;3294switch (Reg) {3295default: llvm_unreachable("Unknown register in assembly macro expansion!");3296case Mips::ZERO: return Mips::AT;3297case Mips::AT: return Mips::V0;3298case Mips::V0: return Mips::V1;3299case Mips::V1: return Mips::A0;3300case Mips::A0: return Mips::A1;3301case Mips::A1: return Mips::A2;3302case Mips::A2: return Mips::A3;3303case Mips::A3: return Mips::T0;3304case Mips::T0: return Mips::T1;3305case Mips::T1: return Mips::T2;3306case Mips::T2: return Mips::T3;3307case Mips::T3: return Mips::T4;3308case Mips::T4: return Mips::T5;3309case Mips::T5: return Mips::T6;3310case Mips::T6: return Mips::T7;3311case Mips::T7: return Mips::S0;3312case Mips::S0: return Mips::S1;3313case Mips::S1: return Mips::S2;3314case Mips::S2: return Mips::S3;3315case Mips::S3: return Mips::S4;3316case Mips::S4: return Mips::S5;3317case Mips::S5: return Mips::S6;3318case Mips::S6: return Mips::S7;3319case Mips::S7: return Mips::T8;3320case Mips::T8: return Mips::T9;3321case Mips::T9: return Mips::K0;3322case Mips::K0: return Mips::K1;3323case Mips::K1: return Mips::GP;3324case Mips::GP: return Mips::SP;3325case Mips::SP: return Mips::FP;3326case Mips::FP: return Mips::RA;3327case Mips::RA: return Mips::ZERO;3328case Mips::D0: return Mips::F1;3329case Mips::D1: return Mips::F3;3330case Mips::D2: return Mips::F5;3331case Mips::D3: return Mips::F7;3332case Mips::D4: return Mips::F9;3333case Mips::D5: return Mips::F11;3334case Mips::D6: return Mips::F13;3335case Mips::D7: return Mips::F15;3336case Mips::D8: return Mips::F17;3337case Mips::D9: return Mips::F19;3338case Mips::D10: return Mips::F21;3339case Mips::D11: return Mips::F23;3340case Mips::D12: return Mips::F25;3341case Mips::D13: return Mips::F27;3342case Mips::D14: return Mips::F29;3343case Mips::D15: return Mips::F31;3344}3345}33463347// FIXME: This method is too general. In principle we should compute the number3348// of instructions required to synthesize the immediate inline compared to3349// synthesizing the address inline and relying on non .text sections.3350// For static O32 and N32 this may yield a small benefit, for static N64 this is3351// likely to yield a much larger benefit as we have to synthesize a 64bit3352// address to load a 64 bit value.3353bool MipsAsmParser::emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc,3354MCSymbol *Sym) {3355unsigned ATReg = getATReg(IDLoc);3356if (!ATReg)3357return true;33583359if(IsPicEnabled) {3360const MCExpr *GotSym =3361MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());3362const MipsMCExpr *GotExpr =3363MipsMCExpr::create(MipsMCExpr::MEK_GOT, GotSym, getContext());33643365if(isABI_O32() || isABI_N32()) {3366TOut.emitRRX(Mips::LW, ATReg, GPReg, MCOperand::createExpr(GotExpr),3367IDLoc, STI);3368} else { //isABI_N64()3369TOut.emitRRX(Mips::LD, ATReg, GPReg, MCOperand::createExpr(GotExpr),3370IDLoc, STI);3371}3372} else { //!IsPicEnabled3373const MCExpr *HiSym =3374MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());3375const MipsMCExpr *HiExpr =3376MipsMCExpr::create(MipsMCExpr::MEK_HI, HiSym, getContext());33773378// FIXME: This is technically correct but gives a different result to gas,3379// but gas is incomplete there (it has a fixme noting it doesn't work with3380// 64-bit addresses).3381// FIXME: With -msym32 option, the address expansion for N64 should probably3382// use the O32 / N32 case. It's safe to use the 64 address expansion as the3383// symbol's value is considered sign extended.3384if(isABI_O32() || isABI_N32()) {3385TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);3386} else { //isABI_N64()3387const MCExpr *HighestSym =3388MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());3389const MipsMCExpr *HighestExpr =3390MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, HighestSym, getContext());3391const MCExpr *HigherSym =3392MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());3393const MipsMCExpr *HigherExpr =3394MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, HigherSym, getContext());33953396TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,3397STI);3398TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,3399MCOperand::createExpr(HigherExpr), IDLoc, STI);3400TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);3401TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),3402IDLoc, STI);3403TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);3404}3405}3406return false;3407}34083409static uint64_t convertIntToDoubleImm(uint64_t ImmOp64) {3410// If ImmOp64 is AsmToken::Integer type (all bits set to zero in the3411// exponent field), convert it to double (e.g. 1 to 1.0)3412if ((Hi_32(ImmOp64) & 0x7ff00000) == 0) {3413APFloat RealVal(APFloat::IEEEdouble(), ImmOp64);3414ImmOp64 = RealVal.bitcastToAPInt().getZExtValue();3415}3416return ImmOp64;3417}34183419static uint32_t covertDoubleImmToSingleImm(uint64_t ImmOp64) {3420// Conversion of a double in an uint64_t to a float in a uint32_t,3421// retaining the bit pattern of a float.3422double DoubleImm = llvm::bit_cast<double>(ImmOp64);3423float TmpFloat = static_cast<float>(DoubleImm);3424return llvm::bit_cast<uint32_t>(TmpFloat);3425}34263427bool MipsAsmParser::expandLoadSingleImmToGPR(MCInst &Inst, SMLoc IDLoc,3428MCStreamer &Out,3429const MCSubtargetInfo *STI) {3430assert(Inst.getNumOperands() == 2 && "Invalid operand count");3431assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&3432"Invalid instruction operand.");34333434unsigned FirstReg = Inst.getOperand(0).getReg();3435uint64_t ImmOp64 = Inst.getOperand(1).getImm();34363437uint32_t ImmOp32 = covertDoubleImmToSingleImm(convertIntToDoubleImm(ImmOp64));34383439return loadImmediate(ImmOp32, FirstReg, Mips::NoRegister, true, false, IDLoc,3440Out, STI);3441}34423443bool MipsAsmParser::expandLoadSingleImmToFPR(MCInst &Inst, SMLoc IDLoc,3444MCStreamer &Out,3445const MCSubtargetInfo *STI) {3446MipsTargetStreamer &TOut = getTargetStreamer();3447assert(Inst.getNumOperands() == 2 && "Invalid operand count");3448assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&3449"Invalid instruction operand.");34503451unsigned FirstReg = Inst.getOperand(0).getReg();3452uint64_t ImmOp64 = Inst.getOperand(1).getImm();34533454ImmOp64 = convertIntToDoubleImm(ImmOp64);34553456uint32_t ImmOp32 = covertDoubleImmToSingleImm(ImmOp64);34573458unsigned TmpReg = Mips::ZERO;3459if (ImmOp32 != 0) {3460TmpReg = getATReg(IDLoc);3461if (!TmpReg)3462return true;3463}34643465if (Lo_32(ImmOp64) == 0) {3466if (TmpReg != Mips::ZERO && loadImmediate(ImmOp32, TmpReg, Mips::NoRegister,3467true, false, IDLoc, Out, STI))3468return true;3469TOut.emitRR(Mips::MTC1, FirstReg, TmpReg, IDLoc, STI);3470return false;3471}34723473MCSection *CS = getStreamer().getCurrentSectionOnly();3474// FIXME: Enhance this expansion to use the .lit4 & .lit8 sections3475// where appropriate.3476MCSection *ReadOnlySection =3477getContext().getELFSection(".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);34783479MCSymbol *Sym = getContext().createTempSymbol();3480const MCExpr *LoSym =3481MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());3482const MipsMCExpr *LoExpr =3483MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());34843485getStreamer().switchSection(ReadOnlySection);3486getStreamer().emitLabel(Sym, IDLoc);3487getStreamer().emitInt32(ImmOp32);3488getStreamer().switchSection(CS);34893490if (emitPartialAddress(TOut, IDLoc, Sym))3491return true;3492TOut.emitRRX(Mips::LWC1, FirstReg, TmpReg, MCOperand::createExpr(LoExpr),3493IDLoc, STI);3494return false;3495}34963497bool MipsAsmParser::expandLoadDoubleImmToGPR(MCInst &Inst, SMLoc IDLoc,3498MCStreamer &Out,3499const MCSubtargetInfo *STI) {3500MipsTargetStreamer &TOut = getTargetStreamer();3501assert(Inst.getNumOperands() == 2 && "Invalid operand count");3502assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&3503"Invalid instruction operand.");35043505unsigned FirstReg = Inst.getOperand(0).getReg();3506uint64_t ImmOp64 = Inst.getOperand(1).getImm();35073508ImmOp64 = convertIntToDoubleImm(ImmOp64);35093510if (Lo_32(ImmOp64) == 0) {3511if (isGP64bit()) {3512if (loadImmediate(ImmOp64, FirstReg, Mips::NoRegister, false, false,3513IDLoc, Out, STI))3514return true;3515} else {3516if (loadImmediate(Hi_32(ImmOp64), FirstReg, Mips::NoRegister, true, false,3517IDLoc, Out, STI))3518return true;35193520if (loadImmediate(0, nextReg(FirstReg), Mips::NoRegister, true, false,3521IDLoc, Out, STI))3522return true;3523}3524return false;3525}35263527MCSection *CS = getStreamer().getCurrentSectionOnly();3528MCSection *ReadOnlySection =3529getContext().getELFSection(".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);35303531MCSymbol *Sym = getContext().createTempSymbol();3532const MCExpr *LoSym =3533MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());3534const MipsMCExpr *LoExpr =3535MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());35363537getStreamer().switchSection(ReadOnlySection);3538getStreamer().emitLabel(Sym, IDLoc);3539getStreamer().emitValueToAlignment(Align(8));3540getStreamer().emitIntValue(ImmOp64, 8);3541getStreamer().switchSection(CS);35423543unsigned TmpReg = getATReg(IDLoc);3544if (!TmpReg)3545return true;35463547if (emitPartialAddress(TOut, IDLoc, Sym))3548return true;35493550TOut.emitRRX(isABI_N64() ? Mips::DADDiu : Mips::ADDiu, TmpReg, TmpReg,3551MCOperand::createExpr(LoExpr), IDLoc, STI);35523553if (isGP64bit())3554TOut.emitRRI(Mips::LD, FirstReg, TmpReg, 0, IDLoc, STI);3555else {3556TOut.emitRRI(Mips::LW, FirstReg, TmpReg, 0, IDLoc, STI);3557TOut.emitRRI(Mips::LW, nextReg(FirstReg), TmpReg, 4, IDLoc, STI);3558}3559return false;3560}35613562bool MipsAsmParser::expandLoadDoubleImmToFPR(MCInst &Inst, bool Is64FPU,3563SMLoc IDLoc, MCStreamer &Out,3564const MCSubtargetInfo *STI) {3565MipsTargetStreamer &TOut = getTargetStreamer();3566assert(Inst.getNumOperands() == 2 && "Invalid operand count");3567assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&3568"Invalid instruction operand.");35693570unsigned FirstReg = Inst.getOperand(0).getReg();3571uint64_t ImmOp64 = Inst.getOperand(1).getImm();35723573ImmOp64 = convertIntToDoubleImm(ImmOp64);35743575unsigned TmpReg = Mips::ZERO;3576if (ImmOp64 != 0) {3577TmpReg = getATReg(IDLoc);3578if (!TmpReg)3579return true;3580}35813582if ((Lo_32(ImmOp64) == 0) &&3583!((Hi_32(ImmOp64) & 0xffff0000) && (Hi_32(ImmOp64) & 0x0000ffff))) {3584if (isGP64bit()) {3585if (TmpReg != Mips::ZERO &&3586loadImmediate(ImmOp64, TmpReg, Mips::NoRegister, false, false, IDLoc,3587Out, STI))3588return true;3589TOut.emitRR(Mips::DMTC1, FirstReg, TmpReg, IDLoc, STI);3590return false;3591}35923593if (TmpReg != Mips::ZERO &&3594loadImmediate(Hi_32(ImmOp64), TmpReg, Mips::NoRegister, true, false,3595IDLoc, Out, STI))3596return true;35973598if (hasMips32r2()) {3599TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);3600TOut.emitRRR(Mips::MTHC1_D32, FirstReg, FirstReg, TmpReg, IDLoc, STI);3601} else {3602TOut.emitRR(Mips::MTC1, nextReg(FirstReg), TmpReg, IDLoc, STI);3603TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);3604}3605return false;3606}36073608MCSection *CS = getStreamer().getCurrentSectionOnly();3609// FIXME: Enhance this expansion to use the .lit4 & .lit8 sections3610// where appropriate.3611MCSection *ReadOnlySection =3612getContext().getELFSection(".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);36133614MCSymbol *Sym = getContext().createTempSymbol();3615const MCExpr *LoSym =3616MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());3617const MipsMCExpr *LoExpr =3618MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());36193620getStreamer().switchSection(ReadOnlySection);3621getStreamer().emitLabel(Sym, IDLoc);3622getStreamer().emitValueToAlignment(Align(8));3623getStreamer().emitIntValue(ImmOp64, 8);3624getStreamer().switchSection(CS);36253626if (emitPartialAddress(TOut, IDLoc, Sym))3627return true;36283629TOut.emitRRX(Is64FPU ? Mips::LDC164 : Mips::LDC1, FirstReg, TmpReg,3630MCOperand::createExpr(LoExpr), IDLoc, STI);36313632return false;3633}36343635bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,3636MCStreamer &Out,3637const MCSubtargetInfo *STI) {3638MipsTargetStreamer &TOut = getTargetStreamer();36393640assert(MII.get(Inst.getOpcode()).getNumOperands() == 1 &&3641"unexpected number of operands");36423643MCOperand Offset = Inst.getOperand(0);3644if (Offset.isExpr()) {3645Inst.clear();3646Inst.setOpcode(Mips::BEQ_MM);3647Inst.addOperand(MCOperand::createReg(Mips::ZERO));3648Inst.addOperand(MCOperand::createReg(Mips::ZERO));3649Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));3650} else {3651assert(Offset.isImm() && "expected immediate operand kind");3652if (isInt<11>(Offset.getImm())) {3653// If offset fits into 11 bits then this instruction becomes microMIPS3654// 16-bit unconditional branch instruction.3655if (inMicroMipsMode())3656Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);3657} else {3658if (!isInt<17>(Offset.getImm()))3659return Error(IDLoc, "branch target out of range");3660if (offsetToAlignment(Offset.getImm(), Align(2)))3661return Error(IDLoc, "branch to misaligned address");3662Inst.clear();3663Inst.setOpcode(Mips::BEQ_MM);3664Inst.addOperand(MCOperand::createReg(Mips::ZERO));3665Inst.addOperand(MCOperand::createReg(Mips::ZERO));3666Inst.addOperand(MCOperand::createImm(Offset.getImm()));3667}3668}3669Out.emitInstruction(Inst, *STI);36703671// If .set reorder is active and branch instruction has a delay slot,3672// emit a NOP after it.3673const MCInstrDesc &MCID = MII.get(Inst.getOpcode());3674if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())3675TOut.emitEmptyDelaySlot(true, IDLoc, STI);36763677return false;3678}36793680bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,3681const MCSubtargetInfo *STI) {3682MipsTargetStreamer &TOut = getTargetStreamer();3683const MCOperand &DstRegOp = Inst.getOperand(0);3684assert(DstRegOp.isReg() && "expected register operand kind");36853686const MCOperand &ImmOp = Inst.getOperand(1);3687assert(ImmOp.isImm() && "expected immediate operand kind");36883689const MCOperand &MemOffsetOp = Inst.getOperand(2);3690assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&3691"expected immediate or expression operand");36923693bool IsLikely = false;36943695unsigned OpCode = 0;3696switch(Inst.getOpcode()) {3697case Mips::BneImm:3698OpCode = Mips::BNE;3699break;3700case Mips::BeqImm:3701OpCode = Mips::BEQ;3702break;3703case Mips::BEQLImmMacro:3704OpCode = Mips::BEQL;3705IsLikely = true;3706break;3707case Mips::BNELImmMacro:3708OpCode = Mips::BNEL;3709IsLikely = true;3710break;3711default:3712llvm_unreachable("Unknown immediate branch pseudo-instruction.");3713break;3714}37153716int64_t ImmValue = ImmOp.getImm();3717if (ImmValue == 0) {3718if (IsLikely) {3719TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO,3720MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);3721TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);3722} else3723TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,3724STI);3725} else {3726warnIfNoMacro(IDLoc);37273728unsigned ATReg = getATReg(IDLoc);3729if (!ATReg)3730return true;37313732if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,3733IDLoc, Out, STI))3734return true;37353736if (IsLikely) {3737TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg,3738MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);3739TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);3740} else3741TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);3742}3743return false;3744}37453746void MipsAsmParser::expandMem16Inst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,3747const MCSubtargetInfo *STI, bool IsLoad) {3748unsigned NumOp = Inst.getNumOperands();3749assert((NumOp == 3 || NumOp == 4) && "unexpected operands number");3750unsigned StartOp = NumOp == 3 ? 0 : 1;37513752const MCOperand &DstRegOp = Inst.getOperand(StartOp);3753assert(DstRegOp.isReg() && "expected register operand kind");3754const MCOperand &BaseRegOp = Inst.getOperand(StartOp + 1);3755assert(BaseRegOp.isReg() && "expected register operand kind");3756const MCOperand &OffsetOp = Inst.getOperand(StartOp + 2);37573758MipsTargetStreamer &TOut = getTargetStreamer();3759unsigned OpCode = Inst.getOpcode();3760unsigned DstReg = DstRegOp.getReg();3761unsigned BaseReg = BaseRegOp.getReg();3762unsigned TmpReg = DstReg;37633764const MCInstrDesc &Desc = MII.get(OpCode);3765int16_t DstRegClass = Desc.operands()[StartOp].RegClass;3766unsigned DstRegClassID =3767getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();3768bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||3769(DstRegClassID == Mips::GPR64RegClassID);37703771if (!IsLoad || !IsGPR || (BaseReg == DstReg)) {3772// At this point we need AT to perform the expansions3773// and we exit if it is not available.3774TmpReg = getATReg(IDLoc);3775if (!TmpReg)3776return;3777}37783779auto emitInstWithOffset = [&](const MCOperand &Off) {3780if (NumOp == 3)3781TOut.emitRRX(OpCode, DstReg, TmpReg, Off, IDLoc, STI);3782else3783TOut.emitRRRX(OpCode, DstReg, DstReg, TmpReg, Off, IDLoc, STI);3784};37853786if (OffsetOp.isImm()) {3787int64_t LoOffset = OffsetOp.getImm() & 0xffff;3788int64_t HiOffset = OffsetOp.getImm() & ~0xffff;37893790// If msb of LoOffset is 1(negative number) we must increment3791// HiOffset to account for the sign-extension of the low part.3792if (LoOffset & 0x8000)3793HiOffset += 0x10000;37943795bool IsLargeOffset = HiOffset != 0;37963797if (IsLargeOffset) {3798bool Is32BitImm = isInt<32>(OffsetOp.getImm());3799if (loadImmediate(HiOffset, TmpReg, Mips::NoRegister, Is32BitImm, true,3800IDLoc, Out, STI))3801return;3802}38033804if (BaseReg != Mips::ZERO && BaseReg != Mips::ZERO_64)3805TOut.emitRRR(ABI.ArePtrs64bit() ? Mips::DADDu : Mips::ADDu, TmpReg,3806TmpReg, BaseReg, IDLoc, STI);3807emitInstWithOffset(MCOperand::createImm(int16_t(LoOffset)));3808return;3809}38103811if (OffsetOp.isExpr()) {3812if (inPicMode()) {3813// FIXME:3814// c) Check that immediates of R_MIPS_GOT16/R_MIPS_LO16 relocations3815// do not exceed 16-bit.3816// d) Use R_MIPS_GOT_PAGE/R_MIPS_GOT_OFST relocations instead3817// of R_MIPS_GOT_DISP in appropriate cases to reduce number3818// of GOT entries.3819MCValue Res;3820if (!OffsetOp.getExpr()->evaluateAsRelocatable(Res, nullptr, nullptr)) {3821Error(IDLoc, "expected relocatable expression");3822return;3823}3824if (Res.getSymB() != nullptr) {3825Error(IDLoc, "expected relocatable expression with only one symbol");3826return;3827}38283829loadAndAddSymbolAddress(Res.getSymA(), TmpReg, BaseReg,3830!ABI.ArePtrs64bit(), IDLoc, Out, STI);3831emitInstWithOffset(MCOperand::createImm(int16_t(Res.getConstant())));3832} else {3833// FIXME: Implement 64-bit case.3834// 1) lw $8, sym => lui $8, %hi(sym)3835// lw $8, %lo(sym)($8)3836// 2) sw $8, sym => lui $at, %hi(sym)3837// sw $8, %lo(sym)($at)3838const MCExpr *OffExpr = OffsetOp.getExpr();3839MCOperand LoOperand = MCOperand::createExpr(3840MipsMCExpr::create(MipsMCExpr::MEK_LO, OffExpr, getContext()));3841MCOperand HiOperand = MCOperand::createExpr(3842MipsMCExpr::create(MipsMCExpr::MEK_HI, OffExpr, getContext()));38433844if (ABI.IsN64()) {3845MCOperand HighestOperand = MCOperand::createExpr(3846MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, OffExpr, getContext()));3847MCOperand HigherOperand = MCOperand::createExpr(3848MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, OffExpr, getContext()));38493850TOut.emitRX(Mips::LUi, TmpReg, HighestOperand, IDLoc, STI);3851TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, HigherOperand, IDLoc, STI);3852TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);3853TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, HiOperand, IDLoc, STI);3854TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);3855if (BaseReg != Mips::ZERO && BaseReg != Mips::ZERO_64)3856TOut.emitRRR(Mips::DADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI);3857emitInstWithOffset(LoOperand);3858} else {3859// Generate the base address in TmpReg.3860TOut.emitRX(Mips::LUi, TmpReg, HiOperand, IDLoc, STI);3861if (BaseReg != Mips::ZERO)3862TOut.emitRRR(Mips::ADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI);3863// Emit the load or store with the adjusted base and offset.3864emitInstWithOffset(LoOperand);3865}3866}3867return;3868}38693870llvm_unreachable("unexpected operand type");3871}38723873void MipsAsmParser::expandMem9Inst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,3874const MCSubtargetInfo *STI, bool IsLoad) {3875unsigned NumOp = Inst.getNumOperands();3876assert((NumOp == 3 || NumOp == 4) && "unexpected operands number");3877unsigned StartOp = NumOp == 3 ? 0 : 1;38783879const MCOperand &DstRegOp = Inst.getOperand(StartOp);3880assert(DstRegOp.isReg() && "expected register operand kind");3881const MCOperand &BaseRegOp = Inst.getOperand(StartOp + 1);3882assert(BaseRegOp.isReg() && "expected register operand kind");3883const MCOperand &OffsetOp = Inst.getOperand(StartOp + 2);38843885MipsTargetStreamer &TOut = getTargetStreamer();3886unsigned OpCode = Inst.getOpcode();3887unsigned DstReg = DstRegOp.getReg();3888unsigned BaseReg = BaseRegOp.getReg();3889unsigned TmpReg = DstReg;38903891const MCInstrDesc &Desc = MII.get(OpCode);3892int16_t DstRegClass = Desc.operands()[StartOp].RegClass;3893unsigned DstRegClassID =3894getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();3895bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||3896(DstRegClassID == Mips::GPR64RegClassID);38973898if (!IsLoad || !IsGPR || (BaseReg == DstReg)) {3899// At this point we need AT to perform the expansions3900// and we exit if it is not available.3901TmpReg = getATReg(IDLoc);3902if (!TmpReg)3903return;3904}39053906auto emitInst = [&]() {3907if (NumOp == 3)3908TOut.emitRRX(OpCode, DstReg, TmpReg, MCOperand::createImm(0), IDLoc, STI);3909else3910TOut.emitRRRX(OpCode, DstReg, DstReg, TmpReg, MCOperand::createImm(0),3911IDLoc, STI);3912};39133914if (OffsetOp.isImm()) {3915loadImmediate(OffsetOp.getImm(), TmpReg, BaseReg, !ABI.ArePtrs64bit(), true,3916IDLoc, Out, STI);3917emitInst();3918return;3919}39203921if (OffsetOp.isExpr()) {3922loadAndAddSymbolAddress(OffsetOp.getExpr(), TmpReg, BaseReg,3923!ABI.ArePtrs64bit(), IDLoc, Out, STI);3924emitInst();3925return;3926}39273928llvm_unreachable("unexpected operand type");3929}39303931bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,3932MCStreamer &Out,3933const MCSubtargetInfo *STI) {3934unsigned OpNum = Inst.getNumOperands();3935unsigned Opcode = Inst.getOpcode();3936unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;39373938assert(Inst.getOperand(OpNum - 1).isImm() &&3939Inst.getOperand(OpNum - 2).isReg() &&3940Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");39413942if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&3943Inst.getOperand(OpNum - 1).getImm() >= 0 &&3944(Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||3945Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&3946(Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||3947Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {3948// It can be implemented as SWM16 or LWM16 instruction.3949if (inMicroMipsMode() && hasMips32r6())3950NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;3951else3952NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;3953}39543955Inst.setOpcode(NewOpcode);3956Out.emitInstruction(Inst, *STI);3957return false;3958}39593960bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,3961MCStreamer &Out,3962const MCSubtargetInfo *STI) {3963MipsTargetStreamer &TOut = getTargetStreamer();3964bool EmittedNoMacroWarning = false;3965unsigned PseudoOpcode = Inst.getOpcode();3966unsigned SrcReg = Inst.getOperand(0).getReg();3967const MCOperand &TrgOp = Inst.getOperand(1);3968const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();39693970unsigned ZeroSrcOpcode, ZeroTrgOpcode;3971bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;39723973unsigned TrgReg;3974if (TrgOp.isReg())3975TrgReg = TrgOp.getReg();3976else if (TrgOp.isImm()) {3977warnIfNoMacro(IDLoc);3978EmittedNoMacroWarning = true;39793980TrgReg = getATReg(IDLoc);3981if (!TrgReg)3982return true;39833984switch(PseudoOpcode) {3985default:3986llvm_unreachable("unknown opcode for branch pseudo-instruction");3987case Mips::BLTImmMacro:3988PseudoOpcode = Mips::BLT;3989break;3990case Mips::BLEImmMacro:3991PseudoOpcode = Mips::BLE;3992break;3993case Mips::BGEImmMacro:3994PseudoOpcode = Mips::BGE;3995break;3996case Mips::BGTImmMacro:3997PseudoOpcode = Mips::BGT;3998break;3999case Mips::BLTUImmMacro:4000PseudoOpcode = Mips::BLTU;4001break;4002case Mips::BLEUImmMacro:4003PseudoOpcode = Mips::BLEU;4004break;4005case Mips::BGEUImmMacro:4006PseudoOpcode = Mips::BGEU;4007break;4008case Mips::BGTUImmMacro:4009PseudoOpcode = Mips::BGTU;4010break;4011case Mips::BLTLImmMacro:4012PseudoOpcode = Mips::BLTL;4013break;4014case Mips::BLELImmMacro:4015PseudoOpcode = Mips::BLEL;4016break;4017case Mips::BGELImmMacro:4018PseudoOpcode = Mips::BGEL;4019break;4020case Mips::BGTLImmMacro:4021PseudoOpcode = Mips::BGTL;4022break;4023case Mips::BLTULImmMacro:4024PseudoOpcode = Mips::BLTUL;4025break;4026case Mips::BLEULImmMacro:4027PseudoOpcode = Mips::BLEUL;4028break;4029case Mips::BGEULImmMacro:4030PseudoOpcode = Mips::BGEUL;4031break;4032case Mips::BGTULImmMacro:4033PseudoOpcode = Mips::BGTUL;4034break;4035}40364037if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),4038false, IDLoc, Out, STI))4039return true;4040}40414042switch (PseudoOpcode) {4043case Mips::BLT:4044case Mips::BLTU:4045case Mips::BLTL:4046case Mips::BLTUL:4047AcceptsEquality = false;4048ReverseOrderSLT = false;4049IsUnsigned =4050((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));4051IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));4052ZeroSrcOpcode = Mips::BGTZ;4053ZeroTrgOpcode = Mips::BLTZ;4054break;4055case Mips::BLE:4056case Mips::BLEU:4057case Mips::BLEL:4058case Mips::BLEUL:4059AcceptsEquality = true;4060ReverseOrderSLT = true;4061IsUnsigned =4062((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));4063IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));4064ZeroSrcOpcode = Mips::BGEZ;4065ZeroTrgOpcode = Mips::BLEZ;4066break;4067case Mips::BGE:4068case Mips::BGEU:4069case Mips::BGEL:4070case Mips::BGEUL:4071AcceptsEquality = true;4072ReverseOrderSLT = false;4073IsUnsigned =4074((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));4075IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));4076ZeroSrcOpcode = Mips::BLEZ;4077ZeroTrgOpcode = Mips::BGEZ;4078break;4079case Mips::BGT:4080case Mips::BGTU:4081case Mips::BGTL:4082case Mips::BGTUL:4083AcceptsEquality = false;4084ReverseOrderSLT = true;4085IsUnsigned =4086((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));4087IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));4088ZeroSrcOpcode = Mips::BLTZ;4089ZeroTrgOpcode = Mips::BGTZ;4090break;4091default:4092llvm_unreachable("unknown opcode for branch pseudo-instruction");4093}40944095bool IsTrgRegZero = (TrgReg == Mips::ZERO);4096bool IsSrcRegZero = (SrcReg == Mips::ZERO);4097if (IsSrcRegZero && IsTrgRegZero) {4098// FIXME: All of these Opcode-specific if's are needed for compatibility4099// with GAS' behaviour. However, they may not generate the most efficient4100// code in some circumstances.4101if (PseudoOpcode == Mips::BLT) {4102TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),4103IDLoc, STI);4104return false;4105}4106if (PseudoOpcode == Mips::BLE) {4107TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),4108IDLoc, STI);4109Warning(IDLoc, "branch is always taken");4110return false;4111}4112if (PseudoOpcode == Mips::BGE) {4113TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),4114IDLoc, STI);4115Warning(IDLoc, "branch is always taken");4116return false;4117}4118if (PseudoOpcode == Mips::BGT) {4119TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),4120IDLoc, STI);4121return false;4122}4123if (PseudoOpcode == Mips::BGTU) {4124TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,4125MCOperand::createExpr(OffsetExpr), IDLoc, STI);4126return false;4127}4128if (AcceptsEquality) {4129// If both registers are $0 and the pseudo-branch accepts equality, it4130// will always be taken, so we emit an unconditional branch.4131TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,4132MCOperand::createExpr(OffsetExpr), IDLoc, STI);4133Warning(IDLoc, "branch is always taken");4134return false;4135}4136// If both registers are $0 and the pseudo-branch does not accept4137// equality, it will never be taken, so we don't have to emit anything.4138return false;4139}4140if (IsSrcRegZero || IsTrgRegZero) {4141if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||4142(IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {4143// If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or4144// if the $rt is $0 and the pseudo-branch is BLTU (x < 0),4145// the pseudo-branch will never be taken, so we don't emit anything.4146// This only applies to unsigned pseudo-branches.4147return false;4148}4149if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||4150(IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {4151// If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or4152// if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),4153// the pseudo-branch will always be taken, so we emit an unconditional4154// branch.4155// This only applies to unsigned pseudo-branches.4156TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,4157MCOperand::createExpr(OffsetExpr), IDLoc, STI);4158Warning(IDLoc, "branch is always taken");4159return false;4160}4161if (IsUnsigned) {4162// If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or4163// if the $rt is $0 and the pseudo-branch is BGTU (x > 0),4164// the pseudo-branch will be taken only when the non-zero register is4165// different from 0, so we emit a BNEZ.4166//4167// If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or4168// if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),4169// the pseudo-branch will be taken only when the non-zero register is4170// equal to 0, so we emit a BEQZ.4171//4172// Because only BLEU and BGEU branch on equality, we can use the4173// AcceptsEquality variable to decide when to emit the BEQZ.4174TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,4175IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,4176MCOperand::createExpr(OffsetExpr), IDLoc, STI);4177return false;4178}4179// If we have a signed pseudo-branch and one of the registers is $0,4180// we can use an appropriate compare-to-zero branch. We select which one4181// to use in the switch statement above.4182TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,4183IsSrcRegZero ? TrgReg : SrcReg,4184MCOperand::createExpr(OffsetExpr), IDLoc, STI);4185return false;4186}41874188// If neither the SrcReg nor the TrgReg are $0, we need AT to perform the4189// expansions. If it is not available, we return.4190unsigned ATRegNum = getATReg(IDLoc);4191if (!ATRegNum)4192return true;41934194if (!EmittedNoMacroWarning)4195warnIfNoMacro(IDLoc);41964197// SLT fits well with 2 of our 4 pseudo-branches:4198// BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and4199// BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".4200// If the result of the SLT is 1, we branch, and if it's 0, we don't.4201// This is accomplished by using a BNEZ with the result of the SLT.4202//4203// The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT4204// and BLE with BGT), so we change the BNEZ into a BEQZ.4205// Because only BGE and BLE branch on equality, we can use the4206// AcceptsEquality variable to decide when to emit the BEQZ.4207// Note that the order of the SLT arguments doesn't change between4208// opposites.4209//4210// The same applies to the unsigned variants, except that SLTu is used4211// instead of SLT.4212TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,4213ReverseOrderSLT ? TrgReg : SrcReg,4214ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);42154216TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)4217: (AcceptsEquality ? Mips::BEQ : Mips::BNE),4218ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,4219STI);4220return false;4221}42224223// Expand a integer division macro.4224//4225// Notably we don't have to emit a warning when encountering $rt as the $zero4226// register, or 0 as an immediate. processInstruction() has already done that.4227//4228// The destination register can only be $zero when expanding (S)DivIMacro or4229// D(S)DivMacro.42304231bool MipsAsmParser::expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,4232const MCSubtargetInfo *STI,4233const bool IsMips64, const bool Signed) {4234MipsTargetStreamer &TOut = getTargetStreamer();42354236warnIfNoMacro(IDLoc);42374238const MCOperand &RdRegOp = Inst.getOperand(0);4239assert(RdRegOp.isReg() && "expected register operand kind");4240unsigned RdReg = RdRegOp.getReg();42414242const MCOperand &RsRegOp = Inst.getOperand(1);4243assert(RsRegOp.isReg() && "expected register operand kind");4244unsigned RsReg = RsRegOp.getReg();42454246unsigned RtReg;4247int64_t ImmValue;42484249const MCOperand &RtOp = Inst.getOperand(2);4250assert((RtOp.isReg() || RtOp.isImm()) &&4251"expected register or immediate operand kind");4252if (RtOp.isReg())4253RtReg = RtOp.getReg();4254else4255ImmValue = RtOp.getImm();42564257unsigned DivOp;4258unsigned ZeroReg;4259unsigned SubOp;42604261if (IsMips64) {4262DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;4263ZeroReg = Mips::ZERO_64;4264SubOp = Mips::DSUB;4265} else {4266DivOp = Signed ? Mips::SDIV : Mips::UDIV;4267ZeroReg = Mips::ZERO;4268SubOp = Mips::SUB;4269}42704271bool UseTraps = useTraps();42724273unsigned Opcode = Inst.getOpcode();4274bool isDiv = Opcode == Mips::SDivMacro || Opcode == Mips::SDivIMacro ||4275Opcode == Mips::UDivMacro || Opcode == Mips::UDivIMacro ||4276Opcode == Mips::DSDivMacro || Opcode == Mips::DSDivIMacro ||4277Opcode == Mips::DUDivMacro || Opcode == Mips::DUDivIMacro;42784279bool isRem = Opcode == Mips::SRemMacro || Opcode == Mips::SRemIMacro ||4280Opcode == Mips::URemMacro || Opcode == Mips::URemIMacro ||4281Opcode == Mips::DSRemMacro || Opcode == Mips::DSRemIMacro ||4282Opcode == Mips::DURemMacro || Opcode == Mips::DURemIMacro;42834284if (RtOp.isImm()) {4285unsigned ATReg = getATReg(IDLoc);4286if (!ATReg)4287return true;42884289if (ImmValue == 0) {4290if (UseTraps)4291TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);4292else4293TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);4294return false;4295}42964297if (isRem && (ImmValue == 1 || (Signed && (ImmValue == -1)))) {4298TOut.emitRRR(Mips::OR, RdReg, ZeroReg, ZeroReg, IDLoc, STI);4299return false;4300} else if (isDiv && ImmValue == 1) {4301TOut.emitRRR(Mips::OR, RdReg, RsReg, Mips::ZERO, IDLoc, STI);4302return false;4303} else if (isDiv && Signed && ImmValue == -1) {4304TOut.emitRRR(SubOp, RdReg, ZeroReg, RsReg, IDLoc, STI);4305return false;4306} else {4307if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue),4308false, Inst.getLoc(), Out, STI))4309return true;4310TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI);4311TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);4312return false;4313}4314return true;4315}43164317// If the macro expansion of (d)div(u) or (d)rem(u) would always trap or4318// break, insert the trap/break and exit. This gives a different result to4319// GAS. GAS has an inconsistency/missed optimization in that not all cases4320// are handled equivalently. As the observed behaviour is the same, we're ok.4321if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {4322if (UseTraps) {4323TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);4324return false;4325}4326TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);4327return false;4328}43294330// (d)rem(u) $0, $X, $Y is a special case. Like div $zero, $X, $Y, it does4331// not expand to macro sequence.4332if (isRem && (RdReg == Mips::ZERO || RdReg == Mips::ZERO_64)) {4333TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);4334return false;4335}43364337// Temporary label for first branch traget4338MCContext &Context = TOut.getStreamer().getContext();4339MCSymbol *BrTarget;4340MCOperand LabelOp;43414342if (UseTraps) {4343TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);4344} else {4345// Branch to the li instruction.4346BrTarget = Context.createTempSymbol();4347LabelOp = MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));4348TOut.emitRRX(Mips::BNE, RtReg, ZeroReg, LabelOp, IDLoc, STI);4349}43504351TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);43524353if (!UseTraps)4354TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);43554356if (!Signed) {4357if (!UseTraps)4358TOut.getStreamer().emitLabel(BrTarget);43594360TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);4361return false;4362}43634364unsigned ATReg = getATReg(IDLoc);4365if (!ATReg)4366return true;43674368if (!UseTraps)4369TOut.getStreamer().emitLabel(BrTarget);43704371TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);43724373// Temporary label for the second branch target.4374MCSymbol *BrTargetEnd = Context.createTempSymbol();4375MCOperand LabelOpEnd =4376MCOperand::createExpr(MCSymbolRefExpr::create(BrTargetEnd, Context));43774378// Branch to the mflo instruction.4379TOut.emitRRX(Mips::BNE, RtReg, ATReg, LabelOpEnd, IDLoc, STI);43804381if (IsMips64) {4382TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);4383TOut.emitDSLL(ATReg, ATReg, 63, IDLoc, STI);4384} else {4385TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);4386}43874388if (UseTraps)4389TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);4390else {4391// Branch to the mflo instruction.4392TOut.emitRRX(Mips::BNE, RsReg, ATReg, LabelOpEnd, IDLoc, STI);4393TOut.emitNop(IDLoc, STI);4394TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);4395}43964397TOut.getStreamer().emitLabel(BrTargetEnd);4398TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);4399return false;4400}44014402bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,4403SMLoc IDLoc, MCStreamer &Out,4404const MCSubtargetInfo *STI) {4405MipsTargetStreamer &TOut = getTargetStreamer();44064407assert(Inst.getNumOperands() == 3 && "Invalid operand count");4408assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&4409Inst.getOperand(2).isReg() && "Invalid instruction operand.");44104411unsigned FirstReg = Inst.getOperand(0).getReg();4412unsigned SecondReg = Inst.getOperand(1).getReg();4413unsigned ThirdReg = Inst.getOperand(2).getReg();44144415if (hasMips1() && !hasMips2()) {4416unsigned ATReg = getATReg(IDLoc);4417if (!ATReg)4418return true;4419TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);4420TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);4421TOut.emitNop(IDLoc, STI);4422TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);4423TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);4424TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);4425TOut.emitNop(IDLoc, STI);4426TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)4427: Mips::CVT_W_S,4428FirstReg, SecondReg, IDLoc, STI);4429TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);4430TOut.emitNop(IDLoc, STI);4431return false;4432}44334434TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)4435: Mips::TRUNC_W_S,4436FirstReg, SecondReg, IDLoc, STI);44374438return false;4439}44404441bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,4442MCStreamer &Out, const MCSubtargetInfo *STI) {4443if (hasMips32r6() || hasMips64r6()) {4444return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");4445}44464447const MCOperand &DstRegOp = Inst.getOperand(0);4448assert(DstRegOp.isReg() && "expected register operand kind");4449const MCOperand &SrcRegOp = Inst.getOperand(1);4450assert(SrcRegOp.isReg() && "expected register operand kind");4451const MCOperand &OffsetImmOp = Inst.getOperand(2);4452assert(OffsetImmOp.isImm() && "expected immediate operand kind");44534454MipsTargetStreamer &TOut = getTargetStreamer();4455unsigned DstReg = DstRegOp.getReg();4456unsigned SrcReg = SrcRegOp.getReg();4457int64_t OffsetValue = OffsetImmOp.getImm();44584459// NOTE: We always need AT for ULHU, as it is always used as the source4460// register for one of the LBu's.4461warnIfNoMacro(IDLoc);4462unsigned ATReg = getATReg(IDLoc);4463if (!ATReg)4464return true;44654466bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));4467if (IsLargeOffset) {4468if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,4469IDLoc, Out, STI))4470return true;4471}44724473int64_t FirstOffset = IsLargeOffset ? 0 : OffsetValue;4474int64_t SecondOffset = IsLargeOffset ? 1 : (OffsetValue + 1);4475if (isLittle())4476std::swap(FirstOffset, SecondOffset);44774478unsigned FirstLbuDstReg = IsLargeOffset ? DstReg : ATReg;4479unsigned SecondLbuDstReg = IsLargeOffset ? ATReg : DstReg;44804481unsigned LbuSrcReg = IsLargeOffset ? ATReg : SrcReg;4482unsigned SllReg = IsLargeOffset ? DstReg : ATReg;44834484TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,4485FirstOffset, IDLoc, STI);4486TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondOffset, IDLoc, STI);4487TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);4488TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);44894490return false;4491}44924493bool MipsAsmParser::expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,4494const MCSubtargetInfo *STI) {4495if (hasMips32r6() || hasMips64r6()) {4496return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");4497}44984499const MCOperand &DstRegOp = Inst.getOperand(0);4500assert(DstRegOp.isReg() && "expected register operand kind");4501const MCOperand &SrcRegOp = Inst.getOperand(1);4502assert(SrcRegOp.isReg() && "expected register operand kind");4503const MCOperand &OffsetImmOp = Inst.getOperand(2);4504assert(OffsetImmOp.isImm() && "expected immediate operand kind");45054506MipsTargetStreamer &TOut = getTargetStreamer();4507unsigned DstReg = DstRegOp.getReg();4508unsigned SrcReg = SrcRegOp.getReg();4509int64_t OffsetValue = OffsetImmOp.getImm();45104511warnIfNoMacro(IDLoc);4512unsigned ATReg = getATReg(IDLoc);4513if (!ATReg)4514return true;45154516bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));4517if (IsLargeOffset) {4518if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,4519IDLoc, Out, STI))4520return true;4521}45224523int64_t FirstOffset = IsLargeOffset ? 1 : (OffsetValue + 1);4524int64_t SecondOffset = IsLargeOffset ? 0 : OffsetValue;4525if (isLittle())4526std::swap(FirstOffset, SecondOffset);45274528if (IsLargeOffset) {4529TOut.emitRRI(Mips::SB, DstReg, ATReg, FirstOffset, IDLoc, STI);4530TOut.emitRRI(Mips::SRL, DstReg, DstReg, 8, IDLoc, STI);4531TOut.emitRRI(Mips::SB, DstReg, ATReg, SecondOffset, IDLoc, STI);4532TOut.emitRRI(Mips::LBu, ATReg, ATReg, 0, IDLoc, STI);4533TOut.emitRRI(Mips::SLL, DstReg, DstReg, 8, IDLoc, STI);4534TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);4535} else {4536TOut.emitRRI(Mips::SB, DstReg, SrcReg, FirstOffset, IDLoc, STI);4537TOut.emitRRI(Mips::SRL, ATReg, DstReg, 8, IDLoc, STI);4538TOut.emitRRI(Mips::SB, ATReg, SrcReg, SecondOffset, IDLoc, STI);4539}45404541return false;4542}45434544bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,4545const MCSubtargetInfo *STI) {4546if (hasMips32r6() || hasMips64r6()) {4547return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");4548}45494550const MCOperand &DstRegOp = Inst.getOperand(0);4551assert(DstRegOp.isReg() && "expected register operand kind");4552const MCOperand &SrcRegOp = Inst.getOperand(1);4553assert(SrcRegOp.isReg() && "expected register operand kind");4554const MCOperand &OffsetImmOp = Inst.getOperand(2);4555assert(OffsetImmOp.isImm() && "expected immediate operand kind");45564557MipsTargetStreamer &TOut = getTargetStreamer();4558unsigned DstReg = DstRegOp.getReg();4559unsigned SrcReg = SrcRegOp.getReg();4560int64_t OffsetValue = OffsetImmOp.getImm();45614562// Compute left/right load/store offsets.4563bool IsLargeOffset = !(isInt<16>(OffsetValue + 3) && isInt<16>(OffsetValue));4564int64_t LxlOffset = IsLargeOffset ? 0 : OffsetValue;4565int64_t LxrOffset = IsLargeOffset ? 3 : (OffsetValue + 3);4566if (isLittle())4567std::swap(LxlOffset, LxrOffset);45684569bool IsLoadInst = (Inst.getOpcode() == Mips::Ulw);4570bool DoMove = IsLoadInst && (SrcReg == DstReg) && !IsLargeOffset;4571unsigned TmpReg = SrcReg;4572if (IsLargeOffset || DoMove) {4573warnIfNoMacro(IDLoc);4574TmpReg = getATReg(IDLoc);4575if (!TmpReg)4576return true;4577}45784579if (IsLargeOffset) {4580if (loadImmediate(OffsetValue, TmpReg, SrcReg, !ABI.ArePtrs64bit(), true,4581IDLoc, Out, STI))4582return true;4583}45844585if (DoMove)4586std::swap(DstReg, TmpReg);45874588unsigned XWL = IsLoadInst ? Mips::LWL : Mips::SWL;4589unsigned XWR = IsLoadInst ? Mips::LWR : Mips::SWR;4590TOut.emitRRI(XWL, DstReg, TmpReg, LxlOffset, IDLoc, STI);4591TOut.emitRRI(XWR, DstReg, TmpReg, LxrOffset, IDLoc, STI);45924593if (DoMove)4594TOut.emitRRR(Mips::OR, TmpReg, DstReg, Mips::ZERO, IDLoc, STI);45954596return false;4597}45984599bool MipsAsmParser::expandSge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,4600const MCSubtargetInfo *STI) {4601MipsTargetStreamer &TOut = getTargetStreamer();46024603assert(Inst.getNumOperands() == 3 && "Invalid operand count");4604assert(Inst.getOperand(0).isReg() &&4605Inst.getOperand(1).isReg() &&4606Inst.getOperand(2).isReg() && "Invalid instruction operand.");46074608unsigned DstReg = Inst.getOperand(0).getReg();4609unsigned SrcReg = Inst.getOperand(1).getReg();4610unsigned OpReg = Inst.getOperand(2).getReg();4611unsigned OpCode;46124613warnIfNoMacro(IDLoc);46144615switch (Inst.getOpcode()) {4616case Mips::SGE:4617OpCode = Mips::SLT;4618break;4619case Mips::SGEU:4620OpCode = Mips::SLTu;4621break;4622default:4623llvm_unreachable("unexpected 'sge' opcode");4624}46254626// $SrcReg >= $OpReg is equal to (not ($SrcReg < $OpReg))4627TOut.emitRRR(OpCode, DstReg, SrcReg, OpReg, IDLoc, STI);4628TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI);46294630return false;4631}46324633bool MipsAsmParser::expandSgeImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,4634const MCSubtargetInfo *STI) {4635MipsTargetStreamer &TOut = getTargetStreamer();46364637assert(Inst.getNumOperands() == 3 && "Invalid operand count");4638assert(Inst.getOperand(0).isReg() &&4639Inst.getOperand(1).isReg() &&4640Inst.getOperand(2).isImm() && "Invalid instruction operand.");46414642unsigned DstReg = Inst.getOperand(0).getReg();4643unsigned SrcReg = Inst.getOperand(1).getReg();4644int64_t ImmValue = Inst.getOperand(2).getImm();4645unsigned OpRegCode, OpImmCode;46464647warnIfNoMacro(IDLoc);46484649switch (Inst.getOpcode()) {4650case Mips::SGEImm:4651case Mips::SGEImm64:4652OpRegCode = Mips::SLT;4653OpImmCode = Mips::SLTi;4654break;4655case Mips::SGEUImm:4656case Mips::SGEUImm64:4657OpRegCode = Mips::SLTu;4658OpImmCode = Mips::SLTiu;4659break;4660default:4661llvm_unreachable("unexpected 'sge' opcode with immediate");4662}46634664// $SrcReg >= Imm is equal to (not ($SrcReg < Imm))4665if (isInt<16>(ImmValue)) {4666// Use immediate version of STL.4667TOut.emitRRI(OpImmCode, DstReg, SrcReg, ImmValue, IDLoc, STI);4668TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI);4669} else {4670unsigned ImmReg = DstReg;4671if (DstReg == SrcReg) {4672unsigned ATReg = getATReg(Inst.getLoc());4673if (!ATReg)4674return true;4675ImmReg = ATReg;4676}46774678if (loadImmediate(ImmValue, ImmReg, Mips::NoRegister, isInt<32>(ImmValue),4679false, IDLoc, Out, STI))4680return true;46814682TOut.emitRRR(OpRegCode, DstReg, SrcReg, ImmReg, IDLoc, STI);4683TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI);4684}46854686return false;4687}46884689bool MipsAsmParser::expandSgtImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,4690const MCSubtargetInfo *STI) {4691MipsTargetStreamer &TOut = getTargetStreamer();46924693assert(Inst.getNumOperands() == 3 && "Invalid operand count");4694assert(Inst.getOperand(0).isReg() &&4695Inst.getOperand(1).isReg() &&4696Inst.getOperand(2).isImm() && "Invalid instruction operand.");46974698unsigned DstReg = Inst.getOperand(0).getReg();4699unsigned SrcReg = Inst.getOperand(1).getReg();4700unsigned ImmReg = DstReg;4701int64_t ImmValue = Inst.getOperand(2).getImm();4702unsigned OpCode;47034704warnIfNoMacro(IDLoc);47054706switch (Inst.getOpcode()) {4707case Mips::SGTImm:4708case Mips::SGTImm64:4709OpCode = Mips::SLT;4710break;4711case Mips::SGTUImm:4712case Mips::SGTUImm64:4713OpCode = Mips::SLTu;4714break;4715default:4716llvm_unreachable("unexpected 'sgt' opcode with immediate");4717}47184719if (DstReg == SrcReg) {4720unsigned ATReg = getATReg(Inst.getLoc());4721if (!ATReg)4722return true;4723ImmReg = ATReg;4724}47254726if (loadImmediate(ImmValue, ImmReg, Mips::NoRegister, isInt<32>(ImmValue),4727false, IDLoc, Out, STI))4728return true;47294730// $SrcReg > $ImmReg is equal to $ImmReg < $SrcReg4731TOut.emitRRR(OpCode, DstReg, ImmReg, SrcReg, IDLoc, STI);47324733return false;4734}47354736bool MipsAsmParser::expandSle(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,4737const MCSubtargetInfo *STI) {4738MipsTargetStreamer &TOut = getTargetStreamer();47394740assert(Inst.getNumOperands() == 3 && "Invalid operand count");4741assert(Inst.getOperand(0).isReg() &&4742Inst.getOperand(1).isReg() &&4743Inst.getOperand(2).isReg() && "Invalid instruction operand.");47444745unsigned DstReg = Inst.getOperand(0).getReg();4746unsigned SrcReg = Inst.getOperand(1).getReg();4747unsigned OpReg = Inst.getOperand(2).getReg();4748unsigned OpCode;47494750warnIfNoMacro(IDLoc);47514752switch (Inst.getOpcode()) {4753case Mips::SLE:4754OpCode = Mips::SLT;4755break;4756case Mips::SLEU:4757OpCode = Mips::SLTu;4758break;4759default:4760llvm_unreachable("unexpected 'sge' opcode");4761}47624763// $SrcReg <= $OpReg is equal to (not ($OpReg < $SrcReg))4764TOut.emitRRR(OpCode, DstReg, OpReg, SrcReg, IDLoc, STI);4765TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI);47664767return false;4768}47694770bool MipsAsmParser::expandSleImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,4771const MCSubtargetInfo *STI) {4772MipsTargetStreamer &TOut = getTargetStreamer();47734774assert(Inst.getNumOperands() == 3 && "Invalid operand count");4775assert(Inst.getOperand(0).isReg() &&4776Inst.getOperand(1).isReg() &&4777Inst.getOperand(2).isImm() && "Invalid instruction operand.");47784779unsigned DstReg = Inst.getOperand(0).getReg();4780unsigned SrcReg = Inst.getOperand(1).getReg();4781int64_t ImmValue = Inst.getOperand(2).getImm();4782unsigned OpRegCode;47834784warnIfNoMacro(IDLoc);47854786switch (Inst.getOpcode()) {4787case Mips::SLEImm:4788case Mips::SLEImm64:4789OpRegCode = Mips::SLT;4790break;4791case Mips::SLEUImm:4792case Mips::SLEUImm64:4793OpRegCode = Mips::SLTu;4794break;4795default:4796llvm_unreachable("unexpected 'sge' opcode with immediate");4797}47984799// $SrcReg <= Imm is equal to (not (Imm < $SrcReg))4800unsigned ImmReg = DstReg;4801if (DstReg == SrcReg) {4802unsigned ATReg = getATReg(Inst.getLoc());4803if (!ATReg)4804return true;4805ImmReg = ATReg;4806}48074808if (loadImmediate(ImmValue, ImmReg, Mips::NoRegister, isInt<32>(ImmValue),4809false, IDLoc, Out, STI))4810return true;48114812TOut.emitRRR(OpRegCode, DstReg, ImmReg, SrcReg, IDLoc, STI);4813TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI);48144815return false;4816}48174818bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,4819MCStreamer &Out,4820const MCSubtargetInfo *STI) {4821MipsTargetStreamer &TOut = getTargetStreamer();48224823assert(Inst.getNumOperands() == 3 && "Invalid operand count");4824assert(Inst.getOperand(0).isReg() &&4825Inst.getOperand(1).isReg() &&4826Inst.getOperand(2).isImm() && "Invalid instruction operand.");48274828unsigned ATReg = Mips::NoRegister;4829unsigned FinalDstReg = Mips::NoRegister;4830unsigned DstReg = Inst.getOperand(0).getReg();4831unsigned SrcReg = Inst.getOperand(1).getReg();4832int64_t ImmValue = Inst.getOperand(2).getImm();48334834bool Is32Bit = isInt<32>(ImmValue) || (!isGP64bit() && isUInt<32>(ImmValue));48354836unsigned FinalOpcode = Inst.getOpcode();48374838if (DstReg == SrcReg) {4839ATReg = getATReg(Inst.getLoc());4840if (!ATReg)4841return true;4842FinalDstReg = DstReg;4843DstReg = ATReg;4844}48454846if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false,4847Inst.getLoc(), Out, STI)) {4848switch (FinalOpcode) {4849default:4850llvm_unreachable("unimplemented expansion");4851case Mips::ADDi:4852FinalOpcode = Mips::ADD;4853break;4854case Mips::ADDiu:4855FinalOpcode = Mips::ADDu;4856break;4857case Mips::ANDi:4858FinalOpcode = Mips::AND;4859break;4860case Mips::NORImm:4861FinalOpcode = Mips::NOR;4862break;4863case Mips::ORi:4864FinalOpcode = Mips::OR;4865break;4866case Mips::SLTi:4867FinalOpcode = Mips::SLT;4868break;4869case Mips::SLTiu:4870FinalOpcode = Mips::SLTu;4871break;4872case Mips::XORi:4873FinalOpcode = Mips::XOR;4874break;4875case Mips::ADDi_MM:4876FinalOpcode = Mips::ADD_MM;4877break;4878case Mips::ADDiu_MM:4879FinalOpcode = Mips::ADDu_MM;4880break;4881case Mips::ANDi_MM:4882FinalOpcode = Mips::AND_MM;4883break;4884case Mips::ORi_MM:4885FinalOpcode = Mips::OR_MM;4886break;4887case Mips::SLTi_MM:4888FinalOpcode = Mips::SLT_MM;4889break;4890case Mips::SLTiu_MM:4891FinalOpcode = Mips::SLTu_MM;4892break;4893case Mips::XORi_MM:4894FinalOpcode = Mips::XOR_MM;4895break;4896case Mips::ANDi64:4897FinalOpcode = Mips::AND64;4898break;4899case Mips::NORImm64:4900FinalOpcode = Mips::NOR64;4901break;4902case Mips::ORi64:4903FinalOpcode = Mips::OR64;4904break;4905case Mips::SLTImm64:4906FinalOpcode = Mips::SLT64;4907break;4908case Mips::SLTUImm64:4909FinalOpcode = Mips::SLTu64;4910break;4911case Mips::XORi64:4912FinalOpcode = Mips::XOR64;4913break;4914}49154916if (FinalDstReg == Mips::NoRegister)4917TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);4918else4919TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);4920return false;4921}4922return true;4923}49244925bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,4926const MCSubtargetInfo *STI) {4927MipsTargetStreamer &TOut = getTargetStreamer();4928unsigned ATReg = Mips::NoRegister;4929unsigned DReg = Inst.getOperand(0).getReg();4930unsigned SReg = Inst.getOperand(1).getReg();4931unsigned TReg = Inst.getOperand(2).getReg();4932unsigned TmpReg = DReg;49334934unsigned FirstShift = Mips::NOP;4935unsigned SecondShift = Mips::NOP;49364937if (hasMips32r2()) {4938if (DReg == SReg) {4939TmpReg = getATReg(Inst.getLoc());4940if (!TmpReg)4941return true;4942}49434944if (Inst.getOpcode() == Mips::ROL) {4945TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);4946TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);4947return false;4948}49494950if (Inst.getOpcode() == Mips::ROR) {4951TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);4952return false;4953}49544955return true;4956}49574958if (hasMips32()) {4959switch (Inst.getOpcode()) {4960default:4961llvm_unreachable("unexpected instruction opcode");4962case Mips::ROL:4963FirstShift = Mips::SRLV;4964SecondShift = Mips::SLLV;4965break;4966case Mips::ROR:4967FirstShift = Mips::SLLV;4968SecondShift = Mips::SRLV;4969break;4970}49714972ATReg = getATReg(Inst.getLoc());4973if (!ATReg)4974return true;49754976TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);4977TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);4978TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);4979TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);49804981return false;4982}49834984return true;4985}49864987bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,4988MCStreamer &Out,4989const MCSubtargetInfo *STI) {4990MipsTargetStreamer &TOut = getTargetStreamer();4991unsigned ATReg = Mips::NoRegister;4992unsigned DReg = Inst.getOperand(0).getReg();4993unsigned SReg = Inst.getOperand(1).getReg();4994int64_t ImmValue = Inst.getOperand(2).getImm();49954996unsigned FirstShift = Mips::NOP;4997unsigned SecondShift = Mips::NOP;49984999if (hasMips32r2()) {5000if (Inst.getOpcode() == Mips::ROLImm) {5001uint64_t MaxShift = 32;5002uint64_t ShiftValue = ImmValue;5003if (ImmValue != 0)5004ShiftValue = MaxShift - ImmValue;5005TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);5006return false;5007}50085009if (Inst.getOpcode() == Mips::RORImm) {5010TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);5011return false;5012}50135014return true;5015}50165017if (hasMips32()) {5018if (ImmValue == 0) {5019TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);5020return false;5021}50225023switch (Inst.getOpcode()) {5024default:5025llvm_unreachable("unexpected instruction opcode");5026case Mips::ROLImm:5027FirstShift = Mips::SLL;5028SecondShift = Mips::SRL;5029break;5030case Mips::RORImm:5031FirstShift = Mips::SRL;5032SecondShift = Mips::SLL;5033break;5034}50355036ATReg = getATReg(Inst.getLoc());5037if (!ATReg)5038return true;50395040TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);5041TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);5042TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);50435044return false;5045}50465047return true;5048}50495050bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,5051const MCSubtargetInfo *STI) {5052MipsTargetStreamer &TOut = getTargetStreamer();5053unsigned ATReg = Mips::NoRegister;5054unsigned DReg = Inst.getOperand(0).getReg();5055unsigned SReg = Inst.getOperand(1).getReg();5056unsigned TReg = Inst.getOperand(2).getReg();5057unsigned TmpReg = DReg;50585059unsigned FirstShift = Mips::NOP;5060unsigned SecondShift = Mips::NOP;50615062if (hasMips64r2()) {5063if (TmpReg == SReg) {5064TmpReg = getATReg(Inst.getLoc());5065if (!TmpReg)5066return true;5067}50685069if (Inst.getOpcode() == Mips::DROL) {5070TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);5071TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);5072return false;5073}50745075if (Inst.getOpcode() == Mips::DROR) {5076TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);5077return false;5078}50795080return true;5081}50825083if (hasMips64()) {5084switch (Inst.getOpcode()) {5085default:5086llvm_unreachable("unexpected instruction opcode");5087case Mips::DROL:5088FirstShift = Mips::DSRLV;5089SecondShift = Mips::DSLLV;5090break;5091case Mips::DROR:5092FirstShift = Mips::DSLLV;5093SecondShift = Mips::DSRLV;5094break;5095}50965097ATReg = getATReg(Inst.getLoc());5098if (!ATReg)5099return true;51005101TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);5102TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);5103TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);5104TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);51055106return false;5107}51085109return true;5110}51115112bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,5113MCStreamer &Out,5114const MCSubtargetInfo *STI) {5115MipsTargetStreamer &TOut = getTargetStreamer();5116unsigned ATReg = Mips::NoRegister;5117unsigned DReg = Inst.getOperand(0).getReg();5118unsigned SReg = Inst.getOperand(1).getReg();5119int64_t ImmValue = Inst.getOperand(2).getImm() % 64;51205121unsigned FirstShift = Mips::NOP;5122unsigned SecondShift = Mips::NOP;51235124MCInst TmpInst;51255126if (hasMips64r2()) {5127unsigned FinalOpcode = Mips::NOP;5128if (ImmValue == 0)5129FinalOpcode = Mips::DROTR;5130else if (ImmValue % 32 == 0)5131FinalOpcode = Mips::DROTR32;5132else if ((ImmValue >= 1) && (ImmValue <= 32)) {5133if (Inst.getOpcode() == Mips::DROLImm)5134FinalOpcode = Mips::DROTR32;5135else5136FinalOpcode = Mips::DROTR;5137} else if (ImmValue >= 33) {5138if (Inst.getOpcode() == Mips::DROLImm)5139FinalOpcode = Mips::DROTR;5140else5141FinalOpcode = Mips::DROTR32;5142}51435144uint64_t ShiftValue = ImmValue % 32;5145if (Inst.getOpcode() == Mips::DROLImm)5146ShiftValue = (32 - ImmValue % 32) % 32;51475148TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);51495150return false;5151}51525153if (hasMips64()) {5154if (ImmValue == 0) {5155TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);5156return false;5157}51585159switch (Inst.getOpcode()) {5160default:5161llvm_unreachable("unexpected instruction opcode");5162case Mips::DROLImm:5163if ((ImmValue >= 1) && (ImmValue <= 31)) {5164FirstShift = Mips::DSLL;5165SecondShift = Mips::DSRL32;5166}5167if (ImmValue == 32) {5168FirstShift = Mips::DSLL32;5169SecondShift = Mips::DSRL32;5170}5171if ((ImmValue >= 33) && (ImmValue <= 63)) {5172FirstShift = Mips::DSLL32;5173SecondShift = Mips::DSRL;5174}5175break;5176case Mips::DRORImm:5177if ((ImmValue >= 1) && (ImmValue <= 31)) {5178FirstShift = Mips::DSRL;5179SecondShift = Mips::DSLL32;5180}5181if (ImmValue == 32) {5182FirstShift = Mips::DSRL32;5183SecondShift = Mips::DSLL32;5184}5185if ((ImmValue >= 33) && (ImmValue <= 63)) {5186FirstShift = Mips::DSRL32;5187SecondShift = Mips::DSLL;5188}5189break;5190}51915192ATReg = getATReg(Inst.getLoc());5193if (!ATReg)5194return true;51955196TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);5197TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,5198Inst.getLoc(), STI);5199TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);52005201return false;5202}52035204return true;5205}52065207bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,5208const MCSubtargetInfo *STI) {5209MipsTargetStreamer &TOut = getTargetStreamer();5210unsigned FirstRegOp = Inst.getOperand(0).getReg();5211unsigned SecondRegOp = Inst.getOperand(1).getReg();52125213TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);5214if (FirstRegOp != SecondRegOp)5215TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);5216else5217TOut.emitEmptyDelaySlot(false, IDLoc, STI);5218TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);52195220return false;5221}52225223bool MipsAsmParser::expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,5224const MCSubtargetInfo *STI) {5225MipsTargetStreamer &TOut = getTargetStreamer();5226unsigned ATReg = Mips::NoRegister;5227unsigned DstReg = Inst.getOperand(0).getReg();5228unsigned SrcReg = Inst.getOperand(1).getReg();5229int32_t ImmValue = Inst.getOperand(2).getImm();52305231ATReg = getATReg(IDLoc);5232if (!ATReg)5233return true;52345235loadImmediate(ImmValue, ATReg, Mips::NoRegister, true, false, IDLoc, Out,5236STI);52375238TOut.emitRR(Inst.getOpcode() == Mips::MULImmMacro ? Mips::MULT : Mips::DMULT,5239SrcReg, ATReg, IDLoc, STI);52405241TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);52425243return false;5244}52455246bool MipsAsmParser::expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,5247const MCSubtargetInfo *STI) {5248MipsTargetStreamer &TOut = getTargetStreamer();5249unsigned ATReg = Mips::NoRegister;5250unsigned DstReg = Inst.getOperand(0).getReg();5251unsigned SrcReg = Inst.getOperand(1).getReg();5252unsigned TmpReg = Inst.getOperand(2).getReg();52535254ATReg = getATReg(Inst.getLoc());5255if (!ATReg)5256return true;52575258TOut.emitRR(Inst.getOpcode() == Mips::MULOMacro ? Mips::MULT : Mips::DMULT,5259SrcReg, TmpReg, IDLoc, STI);52605261TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);52625263TOut.emitRRI(Inst.getOpcode() == Mips::MULOMacro ? Mips::SRA : Mips::DSRA32,5264DstReg, DstReg, 0x1F, IDLoc, STI);52655266TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);52675268if (useTraps()) {5269TOut.emitRRI(Mips::TNE, DstReg, ATReg, 6, IDLoc, STI);5270} else {5271MCContext & Context = TOut.getStreamer().getContext();5272MCSymbol * BrTarget = Context.createTempSymbol();5273MCOperand LabelOp =5274MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));52755276TOut.emitRRX(Mips::BEQ, DstReg, ATReg, LabelOp, IDLoc, STI);5277if (AssemblerOptions.back()->isReorder())5278TOut.emitNop(IDLoc, STI);5279TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);52805281TOut.getStreamer().emitLabel(BrTarget);5282}5283TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);52845285return false;5286}52875288bool MipsAsmParser::expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,5289const MCSubtargetInfo *STI) {5290MipsTargetStreamer &TOut = getTargetStreamer();5291unsigned ATReg = Mips::NoRegister;5292unsigned DstReg = Inst.getOperand(0).getReg();5293unsigned SrcReg = Inst.getOperand(1).getReg();5294unsigned TmpReg = Inst.getOperand(2).getReg();52955296ATReg = getATReg(IDLoc);5297if (!ATReg)5298return true;52995300TOut.emitRR(Inst.getOpcode() == Mips::MULOUMacro ? Mips::MULTu : Mips::DMULTu,5301SrcReg, TmpReg, IDLoc, STI);53025303TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);5304TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);5305if (useTraps()) {5306TOut.emitRRI(Mips::TNE, ATReg, Mips::ZERO, 6, IDLoc, STI);5307} else {5308MCContext & Context = TOut.getStreamer().getContext();5309MCSymbol * BrTarget = Context.createTempSymbol();5310MCOperand LabelOp =5311MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));53125313TOut.emitRRX(Mips::BEQ, ATReg, Mips::ZERO, LabelOp, IDLoc, STI);5314if (AssemblerOptions.back()->isReorder())5315TOut.emitNop(IDLoc, STI);5316TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);53175318TOut.getStreamer().emitLabel(BrTarget);5319}53205321return false;5322}53235324bool MipsAsmParser::expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,5325const MCSubtargetInfo *STI) {5326MipsTargetStreamer &TOut = getTargetStreamer();5327unsigned DstReg = Inst.getOperand(0).getReg();5328unsigned SrcReg = Inst.getOperand(1).getReg();5329unsigned TmpReg = Inst.getOperand(2).getReg();53305331TOut.emitRR(Mips::DMULTu, SrcReg, TmpReg, IDLoc, STI);5332TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);53335334return false;5335}53365337// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);5338// lw $<reg+1>>, offset+4($reg2)'5339// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);5340// sw $<reg+1>>, offset+4($reg2)'5341// for O32.5342bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc,5343MCStreamer &Out,5344const MCSubtargetInfo *STI,5345bool IsLoad) {5346if (!isABI_O32())5347return true;53485349warnIfNoMacro(IDLoc);53505351MipsTargetStreamer &TOut = getTargetStreamer();5352unsigned Opcode = IsLoad ? Mips::LW : Mips::SW;5353unsigned FirstReg = Inst.getOperand(0).getReg();5354unsigned SecondReg = nextReg(FirstReg);5355unsigned BaseReg = Inst.getOperand(1).getReg();5356if (!SecondReg)5357return true;53585359warnIfRegIndexIsAT(FirstReg, IDLoc);53605361assert(Inst.getOperand(2).isImm() &&5362"Offset for load macro is not immediate!");53635364MCOperand &FirstOffset = Inst.getOperand(2);5365signed NextOffset = FirstOffset.getImm() + 4;5366MCOperand SecondOffset = MCOperand::createImm(NextOffset);53675368if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))5369return true;53705371// For loads, clobber the base register with the second load instead of the5372// first if the BaseReg == FirstReg.5373if (FirstReg != BaseReg || !IsLoad) {5374TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);5375TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);5376} else {5377TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);5378TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);5379}53805381return false;5382}538353845385// Expand 's.d $<reg> offset($reg2)' to 'swc1 $<reg+1>, offset($reg2);5386// swc1 $<reg>, offset+4($reg2)'5387// or if little endian to 'swc1 $<reg>, offset($reg2);5388// swc1 $<reg+1>, offset+4($reg2)'5389// for Mips1.5390bool MipsAsmParser::expandStoreDM1Macro(MCInst &Inst, SMLoc IDLoc,5391MCStreamer &Out,5392const MCSubtargetInfo *STI) {5393if (!isABI_O32())5394return true;53955396warnIfNoMacro(IDLoc);53975398MipsTargetStreamer &TOut = getTargetStreamer();5399unsigned Opcode = Mips::SWC1;5400unsigned FirstReg = Inst.getOperand(0).getReg();5401unsigned SecondReg = nextReg(FirstReg);5402unsigned BaseReg = Inst.getOperand(1).getReg();5403if (!SecondReg)5404return true;54055406warnIfRegIndexIsAT(FirstReg, IDLoc);54075408assert(Inst.getOperand(2).isImm() &&5409"Offset for macro is not immediate!");54105411MCOperand &FirstOffset = Inst.getOperand(2);5412signed NextOffset = FirstOffset.getImm() + 4;5413MCOperand SecondOffset = MCOperand::createImm(NextOffset);54145415if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))5416return true;54175418if (!IsLittleEndian)5419std::swap(FirstReg, SecondReg);54205421TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);5422TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);54235424return false;5425}54265427bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,5428const MCSubtargetInfo *STI) {5429MipsTargetStreamer &TOut = getTargetStreamer();54305431assert(Inst.getNumOperands() == 3 && "Invalid operand count");5432assert(Inst.getOperand(0).isReg() &&5433Inst.getOperand(1).isReg() &&5434Inst.getOperand(2).isReg() && "Invalid instruction operand.");54355436unsigned DstReg = Inst.getOperand(0).getReg();5437unsigned SrcReg = Inst.getOperand(1).getReg();5438unsigned OpReg = Inst.getOperand(2).getReg();54395440warnIfNoMacro(IDLoc);54415442if (SrcReg != Mips::ZERO && OpReg != Mips::ZERO) {5443TOut.emitRRR(Mips::XOR, DstReg, SrcReg, OpReg, IDLoc, STI);5444TOut.emitRRI(Mips::SLTiu, DstReg, DstReg, 1, IDLoc, STI);5445return false;5446}54475448unsigned Reg = SrcReg == Mips::ZERO ? OpReg : SrcReg;5449TOut.emitRRI(Mips::SLTiu, DstReg, Reg, 1, IDLoc, STI);5450return false;5451}54525453bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,5454const MCSubtargetInfo *STI) {5455MipsTargetStreamer &TOut = getTargetStreamer();54565457assert(Inst.getNumOperands() == 3 && "Invalid operand count");5458assert(Inst.getOperand(0).isReg() &&5459Inst.getOperand(1).isReg() &&5460Inst.getOperand(2).isImm() && "Invalid instruction operand.");54615462unsigned DstReg = Inst.getOperand(0).getReg();5463unsigned SrcReg = Inst.getOperand(1).getReg();5464int64_t Imm = Inst.getOperand(2).getImm();54655466warnIfNoMacro(IDLoc);54675468if (Imm == 0) {5469TOut.emitRRI(Mips::SLTiu, DstReg, SrcReg, 1, IDLoc, STI);5470return false;5471}54725473if (SrcReg == Mips::ZERO) {5474Warning(IDLoc, "comparison is always false");5475TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu,5476DstReg, SrcReg, SrcReg, IDLoc, STI);5477return false;5478}54795480unsigned Opc;5481if (Imm > -0x8000 && Imm < 0) {5482Imm = -Imm;5483Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;5484} else {5485Opc = Mips::XORi;5486}54875488if (!isUInt<16>(Imm)) {5489unsigned ATReg = getATReg(IDLoc);5490if (!ATReg)5491return true;54925493if (loadImmediate(Imm, ATReg, Mips::NoRegister, true, isGP64bit(), IDLoc,5494Out, STI))5495return true;54965497TOut.emitRRR(Mips::XOR, DstReg, SrcReg, ATReg, IDLoc, STI);5498TOut.emitRRI(Mips::SLTiu, DstReg, DstReg, 1, IDLoc, STI);5499return false;5500}55015502TOut.emitRRI(Opc, DstReg, SrcReg, Imm, IDLoc, STI);5503TOut.emitRRI(Mips::SLTiu, DstReg, DstReg, 1, IDLoc, STI);5504return false;5505}55065507bool MipsAsmParser::expandSne(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,5508const MCSubtargetInfo *STI) {55095510MipsTargetStreamer &TOut = getTargetStreamer();55115512assert(Inst.getNumOperands() == 3 && "Invalid operand count");5513assert(Inst.getOperand(0).isReg() &&5514Inst.getOperand(1).isReg() &&5515Inst.getOperand(2).isReg() && "Invalid instruction operand.");55165517unsigned DstReg = Inst.getOperand(0).getReg();5518unsigned SrcReg = Inst.getOperand(1).getReg();5519unsigned OpReg = Inst.getOperand(2).getReg();55205521warnIfNoMacro(IDLoc);55225523if (SrcReg != Mips::ZERO && OpReg != Mips::ZERO) {5524TOut.emitRRR(Mips::XOR, DstReg, SrcReg, OpReg, IDLoc, STI);5525TOut.emitRRR(Mips::SLTu, DstReg, Mips::ZERO, DstReg, IDLoc, STI);5526return false;5527}55285529unsigned Reg = SrcReg == Mips::ZERO ? OpReg : SrcReg;5530TOut.emitRRR(Mips::SLTu, DstReg, Mips::ZERO, Reg, IDLoc, STI);5531return false;5532}55335534bool MipsAsmParser::expandSneI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,5535const MCSubtargetInfo *STI) {5536MipsTargetStreamer &TOut = getTargetStreamer();55375538assert(Inst.getNumOperands() == 3 && "Invalid operand count");5539assert(Inst.getOperand(0).isReg() &&5540Inst.getOperand(1).isReg() &&5541Inst.getOperand(2).isImm() && "Invalid instruction operand.");55425543unsigned DstReg = Inst.getOperand(0).getReg();5544unsigned SrcReg = Inst.getOperand(1).getReg();5545int64_t ImmValue = Inst.getOperand(2).getImm();55465547warnIfNoMacro(IDLoc);55485549if (ImmValue == 0) {5550TOut.emitRRR(Mips::SLTu, DstReg, Mips::ZERO, SrcReg, IDLoc, STI);5551return false;5552}55535554if (SrcReg == Mips::ZERO) {5555Warning(IDLoc, "comparison is always true");5556if (loadImmediate(1, DstReg, Mips::NoRegister, true, false, IDLoc, Out,5557STI))5558return true;5559return false;5560}55615562unsigned Opc;5563if (ImmValue > -0x8000 && ImmValue < 0) {5564ImmValue = -ImmValue;5565Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;5566} else {5567Opc = Mips::XORi;5568}55695570if (isUInt<16>(ImmValue)) {5571TOut.emitRRI(Opc, DstReg, SrcReg, ImmValue, IDLoc, STI);5572TOut.emitRRR(Mips::SLTu, DstReg, Mips::ZERO, DstReg, IDLoc, STI);5573return false;5574}55755576unsigned ATReg = getATReg(IDLoc);5577if (!ATReg)5578return true;55795580if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue),5581false, IDLoc, Out, STI))5582return true;55835584TOut.emitRRR(Mips::XOR, DstReg, SrcReg, ATReg, IDLoc, STI);5585TOut.emitRRR(Mips::SLTu, DstReg, Mips::ZERO, DstReg, IDLoc, STI);5586return false;5587}55885589// Map the DSP accumulator and control register to the corresponding gpr5590// operand. Unlike the other alias, the m(f|t)t(lo|hi|acx) instructions5591// do not map the DSP registers contigously to gpr registers.5592static unsigned getRegisterForMxtrDSP(MCInst &Inst, bool IsMFDSP) {5593switch (Inst.getOpcode()) {5594case Mips::MFTLO:5595case Mips::MTTLO:5596switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {5597case Mips::AC0:5598return Mips::ZERO;5599case Mips::AC1:5600return Mips::A0;5601case Mips::AC2:5602return Mips::T0;5603case Mips::AC3:5604return Mips::T4;5605default:5606llvm_unreachable("Unknown register for 'mttr' alias!");5607}5608case Mips::MFTHI:5609case Mips::MTTHI:5610switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {5611case Mips::AC0:5612return Mips::AT;5613case Mips::AC1:5614return Mips::A1;5615case Mips::AC2:5616return Mips::T1;5617case Mips::AC3:5618return Mips::T5;5619default:5620llvm_unreachable("Unknown register for 'mttr' alias!");5621}5622case Mips::MFTACX:5623case Mips::MTTACX:5624switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {5625case Mips::AC0:5626return Mips::V0;5627case Mips::AC1:5628return Mips::A2;5629case Mips::AC2:5630return Mips::T2;5631case Mips::AC3:5632return Mips::T6;5633default:5634llvm_unreachable("Unknown register for 'mttr' alias!");5635}5636case Mips::MFTDSP:5637case Mips::MTTDSP:5638return Mips::S0;5639default:5640llvm_unreachable("Unknown instruction for 'mttr' dsp alias!");5641}5642}56435644// Map the floating point register operand to the corresponding register5645// operand.5646static unsigned getRegisterForMxtrFP(MCInst &Inst, bool IsMFTC1) {5647switch (Inst.getOperand(IsMFTC1 ? 1 : 0).getReg()) {5648case Mips::F0: return Mips::ZERO;5649case Mips::F1: return Mips::AT;5650case Mips::F2: return Mips::V0;5651case Mips::F3: return Mips::V1;5652case Mips::F4: return Mips::A0;5653case Mips::F5: return Mips::A1;5654case Mips::F6: return Mips::A2;5655case Mips::F7: return Mips::A3;5656case Mips::F8: return Mips::T0;5657case Mips::F9: return Mips::T1;5658case Mips::F10: return Mips::T2;5659case Mips::F11: return Mips::T3;5660case Mips::F12: return Mips::T4;5661case Mips::F13: return Mips::T5;5662case Mips::F14: return Mips::T6;5663case Mips::F15: return Mips::T7;5664case Mips::F16: return Mips::S0;5665case Mips::F17: return Mips::S1;5666case Mips::F18: return Mips::S2;5667case Mips::F19: return Mips::S3;5668case Mips::F20: return Mips::S4;5669case Mips::F21: return Mips::S5;5670case Mips::F22: return Mips::S6;5671case Mips::F23: return Mips::S7;5672case Mips::F24: return Mips::T8;5673case Mips::F25: return Mips::T9;5674case Mips::F26: return Mips::K0;5675case Mips::F27: return Mips::K1;5676case Mips::F28: return Mips::GP;5677case Mips::F29: return Mips::SP;5678case Mips::F30: return Mips::FP;5679case Mips::F31: return Mips::RA;5680default: llvm_unreachable("Unknown register for mttc1 alias!");5681}5682}56835684// Map the coprocessor operand the corresponding gpr register operand.5685static unsigned getRegisterForMxtrC0(MCInst &Inst, bool IsMFTC0) {5686switch (Inst.getOperand(IsMFTC0 ? 1 : 0).getReg()) {5687case Mips::COP00: return Mips::ZERO;5688case Mips::COP01: return Mips::AT;5689case Mips::COP02: return Mips::V0;5690case Mips::COP03: return Mips::V1;5691case Mips::COP04: return Mips::A0;5692case Mips::COP05: return Mips::A1;5693case Mips::COP06: return Mips::A2;5694case Mips::COP07: return Mips::A3;5695case Mips::COP08: return Mips::T0;5696case Mips::COP09: return Mips::T1;5697case Mips::COP010: return Mips::T2;5698case Mips::COP011: return Mips::T3;5699case Mips::COP012: return Mips::T4;5700case Mips::COP013: return Mips::T5;5701case Mips::COP014: return Mips::T6;5702case Mips::COP015: return Mips::T7;5703case Mips::COP016: return Mips::S0;5704case Mips::COP017: return Mips::S1;5705case Mips::COP018: return Mips::S2;5706case Mips::COP019: return Mips::S3;5707case Mips::COP020: return Mips::S4;5708case Mips::COP021: return Mips::S5;5709case Mips::COP022: return Mips::S6;5710case Mips::COP023: return Mips::S7;5711case Mips::COP024: return Mips::T8;5712case Mips::COP025: return Mips::T9;5713case Mips::COP026: return Mips::K0;5714case Mips::COP027: return Mips::K1;5715case Mips::COP028: return Mips::GP;5716case Mips::COP029: return Mips::SP;5717case Mips::COP030: return Mips::FP;5718case Mips::COP031: return Mips::RA;5719default: llvm_unreachable("Unknown register for mttc0 alias!");5720}5721}57225723/// Expand an alias of 'mftr' or 'mttr' into the full instruction, by producing5724/// an mftr or mttr with the correctly mapped gpr register, u, sel and h bits.5725bool MipsAsmParser::expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,5726const MCSubtargetInfo *STI) {5727MipsTargetStreamer &TOut = getTargetStreamer();5728unsigned rd = 0;5729unsigned u = 1;5730unsigned sel = 0;5731unsigned h = 0;5732bool IsMFTR = false;5733switch (Inst.getOpcode()) {5734case Mips::MFTC0:5735IsMFTR = true;5736[[fallthrough]];5737case Mips::MTTC0:5738u = 0;5739rd = getRegisterForMxtrC0(Inst, IsMFTR);5740sel = Inst.getOperand(2).getImm();5741break;5742case Mips::MFTGPR:5743IsMFTR = true;5744[[fallthrough]];5745case Mips::MTTGPR:5746rd = Inst.getOperand(IsMFTR ? 1 : 0).getReg();5747break;5748case Mips::MFTLO:5749case Mips::MFTHI:5750case Mips::MFTACX:5751case Mips::MFTDSP:5752IsMFTR = true;5753[[fallthrough]];5754case Mips::MTTLO:5755case Mips::MTTHI:5756case Mips::MTTACX:5757case Mips::MTTDSP:5758rd = getRegisterForMxtrDSP(Inst, IsMFTR);5759sel = 1;5760break;5761case Mips::MFTHC1:5762h = 1;5763[[fallthrough]];5764case Mips::MFTC1:5765IsMFTR = true;5766rd = getRegisterForMxtrFP(Inst, IsMFTR);5767sel = 2;5768break;5769case Mips::MTTHC1:5770h = 1;5771[[fallthrough]];5772case Mips::MTTC1:5773rd = getRegisterForMxtrFP(Inst, IsMFTR);5774sel = 2;5775break;5776case Mips::CFTC1:5777IsMFTR = true;5778[[fallthrough]];5779case Mips::CTTC1:5780rd = getRegisterForMxtrFP(Inst, IsMFTR);5781sel = 3;5782break;5783}5784unsigned Op0 = IsMFTR ? Inst.getOperand(0).getReg() : rd;5785unsigned Op1 =5786IsMFTR ? rd5787: (Inst.getOpcode() != Mips::MTTDSP ? Inst.getOperand(1).getReg()5788: Inst.getOperand(0).getReg());57895790TOut.emitRRIII(IsMFTR ? Mips::MFTR : Mips::MTTR, Op0, Op1, u, sel, h, IDLoc,5791STI);5792return false;5793}57945795bool MipsAsmParser::expandSaaAddr(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,5796const MCSubtargetInfo *STI) {5797assert(Inst.getNumOperands() == 3 && "expected three operands");5798assert(Inst.getOperand(0).isReg() && "expected register operand kind");5799assert(Inst.getOperand(1).isReg() && "expected register operand kind");58005801warnIfNoMacro(IDLoc);58025803MipsTargetStreamer &TOut = getTargetStreamer();5804unsigned Opcode = Inst.getOpcode() == Mips::SaaAddr ? Mips::SAA : Mips::SAAD;5805unsigned RtReg = Inst.getOperand(0).getReg();5806unsigned BaseReg = Inst.getOperand(1).getReg();5807const MCOperand &BaseOp = Inst.getOperand(2);58085809if (BaseOp.isImm()) {5810int64_t ImmValue = BaseOp.getImm();5811if (ImmValue == 0) {5812TOut.emitRR(Opcode, RtReg, BaseReg, IDLoc, STI);5813return false;5814}5815}58165817unsigned ATReg = getATReg(IDLoc);5818if (!ATReg)5819return true;58205821if (expandLoadAddress(ATReg, BaseReg, BaseOp, !isGP64bit(), IDLoc, Out, STI))5822return true;58235824TOut.emitRR(Opcode, RtReg, ATReg, IDLoc, STI);5825return false;5826}58275828unsigned5829MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,5830const OperandVector &Operands) {5831switch (Inst.getOpcode()) {5832default:5833return Match_Success;5834case Mips::DATI:5835case Mips::DAHI:5836if (static_cast<MipsOperand &>(*Operands[1])5837.isValidForTie(static_cast<MipsOperand &>(*Operands[2])))5838return Match_Success;5839return Match_RequiresSameSrcAndDst;5840}5841}58425843unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {5844switch (Inst.getOpcode()) {5845// As described by the MIPSR6 spec, daui must not use the zero operand for5846// its source operand.5847case Mips::DAUI:5848if (Inst.getOperand(1).getReg() == Mips::ZERO ||5849Inst.getOperand(1).getReg() == Mips::ZERO_64)5850return Match_RequiresNoZeroRegister;5851return Match_Success;5852// As described by the Mips32r2 spec, the registers Rd and Rs for5853// jalr.hb must be different.5854// It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction5855// and registers Rd and Base for microMIPS lwp instruction5856case Mips::JALR_HB:5857case Mips::JALR_HB64:5858case Mips::JALRC_HB_MMR6:5859case Mips::JALRC_MMR6:5860if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())5861return Match_RequiresDifferentSrcAndDst;5862return Match_Success;5863case Mips::LWP_MM:5864if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())5865return Match_RequiresDifferentSrcAndDst;5866return Match_Success;5867case Mips::SYNC:5868if (Inst.getOperand(0).getImm() != 0 && !hasMips32())5869return Match_NonZeroOperandForSync;5870return Match_Success;5871case Mips::MFC0:5872case Mips::MTC0:5873case Mips::MTC2:5874case Mips::MFC2:5875if (Inst.getOperand(2).getImm() != 0 && !hasMips32())5876return Match_NonZeroOperandForMTCX;5877return Match_Success;5878// As described the MIPSR6 spec, the compact branches that compare registers5879// must:5880// a) Not use the zero register.5881// b) Not use the same register twice.5882// c) rs < rt for bnec, beqc.5883// NB: For this case, the encoding will swap the operands as their5884// ordering doesn't matter. GAS performs this transformation too.5885// Hence, that constraint does not have to be enforced.5886//5887// The compact branches that branch iff the signed addition of two registers5888// would overflow must have rs >= rt. That can be handled like beqc/bnec with5889// operand swapping. They do not have restriction of using the zero register.5890case Mips::BLEZC: case Mips::BLEZC_MMR6:5891case Mips::BGEZC: case Mips::BGEZC_MMR6:5892case Mips::BGTZC: case Mips::BGTZC_MMR6:5893case Mips::BLTZC: case Mips::BLTZC_MMR6:5894case Mips::BEQZC: case Mips::BEQZC_MMR6:5895case Mips::BNEZC: case Mips::BNEZC_MMR6:5896case Mips::BLEZC64:5897case Mips::BGEZC64:5898case Mips::BGTZC64:5899case Mips::BLTZC64:5900case Mips::BEQZC64:5901case Mips::BNEZC64:5902if (Inst.getOperand(0).getReg() == Mips::ZERO ||5903Inst.getOperand(0).getReg() == Mips::ZERO_64)5904return Match_RequiresNoZeroRegister;5905return Match_Success;5906case Mips::BGEC: case Mips::BGEC_MMR6:5907case Mips::BLTC: case Mips::BLTC_MMR6:5908case Mips::BGEUC: case Mips::BGEUC_MMR6:5909case Mips::BLTUC: case Mips::BLTUC_MMR6:5910case Mips::BEQC: case Mips::BEQC_MMR6:5911case Mips::BNEC: case Mips::BNEC_MMR6:5912case Mips::BGEC64:5913case Mips::BLTC64:5914case Mips::BGEUC64:5915case Mips::BLTUC64:5916case Mips::BEQC64:5917case Mips::BNEC64:5918if (Inst.getOperand(0).getReg() == Mips::ZERO ||5919Inst.getOperand(0).getReg() == Mips::ZERO_64)5920return Match_RequiresNoZeroRegister;5921if (Inst.getOperand(1).getReg() == Mips::ZERO ||5922Inst.getOperand(1).getReg() == Mips::ZERO_64)5923return Match_RequiresNoZeroRegister;5924if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())5925return Match_RequiresDifferentOperands;5926return Match_Success;5927case Mips::DINS: {5928assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&5929"Operands must be immediates for dins!");5930const signed Pos = Inst.getOperand(2).getImm();5931const signed Size = Inst.getOperand(3).getImm();5932if ((0 > (Pos + Size)) || ((Pos + Size) > 32))5933return Match_RequiresPosSizeRange0_32;5934return Match_Success;5935}5936case Mips::DINSM:5937case Mips::DINSU: {5938assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&5939"Operands must be immediates for dinsm/dinsu!");5940const signed Pos = Inst.getOperand(2).getImm();5941const signed Size = Inst.getOperand(3).getImm();5942if ((32 >= (Pos + Size)) || ((Pos + Size) > 64))5943return Match_RequiresPosSizeRange33_64;5944return Match_Success;5945}5946case Mips::DEXT: {5947assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&5948"Operands must be immediates for DEXTM!");5949const signed Pos = Inst.getOperand(2).getImm();5950const signed Size = Inst.getOperand(3).getImm();5951if ((1 > (Pos + Size)) || ((Pos + Size) > 63))5952return Match_RequiresPosSizeUImm6;5953return Match_Success;5954}5955case Mips::DEXTM:5956case Mips::DEXTU: {5957assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&5958"Operands must be immediates for dextm/dextu!");5959const signed Pos = Inst.getOperand(2).getImm();5960const signed Size = Inst.getOperand(3).getImm();5961if ((32 > (Pos + Size)) || ((Pos + Size) > 64))5962return Match_RequiresPosSizeRange33_64;5963return Match_Success;5964}5965case Mips::CRC32B: case Mips::CRC32CB:5966case Mips::CRC32H: case Mips::CRC32CH:5967case Mips::CRC32W: case Mips::CRC32CW:5968case Mips::CRC32D: case Mips::CRC32CD:5969if (Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg())5970return Match_RequiresSameSrcAndDst;5971return Match_Success;5972}59735974uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags;5975if ((TSFlags & MipsII::HasFCCRegOperand) &&5976(Inst.getOperand(0).getReg() != Mips::FCC0) && !hasEightFccRegisters())5977return Match_NoFCCRegisterForCurrentISA;59785979return Match_Success;59805981}59825983static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,5984uint64_t ErrorInfo) {5985if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {5986SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();5987if (ErrorLoc == SMLoc())5988return Loc;5989return ErrorLoc;5990}5991return Loc;5992}59935994bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,5995OperandVector &Operands,5996MCStreamer &Out,5997uint64_t &ErrorInfo,5998bool MatchingInlineAsm) {5999MCInst Inst;6000unsigned MatchResult =6001MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);60026003switch (MatchResult) {6004case Match_Success:6005if (processInstruction(Inst, IDLoc, Out, STI))6006return true;6007return false;6008case Match_MissingFeature:6009Error(IDLoc, "instruction requires a CPU feature not currently enabled");6010return true;6011case Match_InvalidTiedOperand:6012Error(IDLoc, "operand must match destination register");6013return true;6014case Match_InvalidOperand: {6015SMLoc ErrorLoc = IDLoc;6016if (ErrorInfo != ~0ULL) {6017if (ErrorInfo >= Operands.size())6018return Error(IDLoc, "too few operands for instruction");60196020ErrorLoc = Operands[ErrorInfo]->getStartLoc();6021if (ErrorLoc == SMLoc())6022ErrorLoc = IDLoc;6023}60246025return Error(ErrorLoc, "invalid operand for instruction");6026}6027case Match_NonZeroOperandForSync:6028return Error(IDLoc,6029"s-type must be zero or unspecified for pre-MIPS32 ISAs");6030case Match_NonZeroOperandForMTCX:6031return Error(IDLoc, "selector must be zero for pre-MIPS32 ISAs");6032case Match_MnemonicFail:6033return Error(IDLoc, "invalid instruction");6034case Match_RequiresDifferentSrcAndDst:6035return Error(IDLoc, "source and destination must be different");6036case Match_RequiresDifferentOperands:6037return Error(IDLoc, "registers must be different");6038case Match_RequiresNoZeroRegister:6039return Error(IDLoc, "invalid operand ($zero) for instruction");6040case Match_RequiresSameSrcAndDst:6041return Error(IDLoc, "source and destination must match");6042case Match_NoFCCRegisterForCurrentISA:6043return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6044"non-zero fcc register doesn't exist in current ISA level");6045case Match_Immz:6046return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");6047case Match_UImm1_0:6048return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6049"expected 1-bit unsigned immediate");6050case Match_UImm2_0:6051return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6052"expected 2-bit unsigned immediate");6053case Match_UImm2_1:6054return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6055"expected immediate in range 1 .. 4");6056case Match_UImm3_0:6057return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6058"expected 3-bit unsigned immediate");6059case Match_UImm4_0:6060return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6061"expected 4-bit unsigned immediate");6062case Match_SImm4_0:6063return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6064"expected 4-bit signed immediate");6065case Match_UImm5_0:6066return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6067"expected 5-bit unsigned immediate");6068case Match_SImm5_0:6069return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6070"expected 5-bit signed immediate");6071case Match_UImm5_1:6072return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6073"expected immediate in range 1 .. 32");6074case Match_UImm5_32:6075return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6076"expected immediate in range 32 .. 63");6077case Match_UImm5_33:6078return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6079"expected immediate in range 33 .. 64");6080case Match_UImm5_0_Report_UImm6:6081// This is used on UImm5 operands that have a corresponding UImm5_326082// operand to avoid confusing the user.6083return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6084"expected 6-bit unsigned immediate");6085case Match_UImm5_Lsl2:6086return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6087"expected both 7-bit unsigned immediate and multiple of 4");6088case Match_UImmRange2_64:6089return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6090"expected immediate in range 2 .. 64");6091case Match_UImm6_0:6092return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6093"expected 6-bit unsigned immediate");6094case Match_UImm6_Lsl2:6095return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6096"expected both 8-bit unsigned immediate and multiple of 4");6097case Match_SImm6_0:6098return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6099"expected 6-bit signed immediate");6100case Match_UImm7_0:6101return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6102"expected 7-bit unsigned immediate");6103case Match_UImm7_N1:6104return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6105"expected immediate in range -1 .. 126");6106case Match_SImm7_Lsl2:6107return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6108"expected both 9-bit signed immediate and multiple of 4");6109case Match_UImm8_0:6110return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6111"expected 8-bit unsigned immediate");6112case Match_UImm10_0:6113return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6114"expected 10-bit unsigned immediate");6115case Match_SImm10_0:6116return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6117"expected 10-bit signed immediate");6118case Match_SImm11_0:6119return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6120"expected 11-bit signed immediate");6121case Match_UImm16:6122case Match_UImm16_Relaxed:6123case Match_UImm16_AltRelaxed:6124return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6125"expected 16-bit unsigned immediate");6126case Match_SImm16:6127case Match_SImm16_Relaxed:6128return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6129"expected 16-bit signed immediate");6130case Match_SImm19_Lsl2:6131return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6132"expected both 19-bit signed immediate and multiple of 4");6133case Match_UImm20_0:6134return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6135"expected 20-bit unsigned immediate");6136case Match_UImm26_0:6137return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6138"expected 26-bit unsigned immediate");6139case Match_SImm32:6140case Match_SImm32_Relaxed:6141return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6142"expected 32-bit signed immediate");6143case Match_UImm32_Coerced:6144return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6145"expected 32-bit immediate");6146case Match_MemSImm9:6147return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6148"expected memory with 9-bit signed offset");6149case Match_MemSImm10:6150return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6151"expected memory with 10-bit signed offset");6152case Match_MemSImm10Lsl1:6153return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6154"expected memory with 11-bit signed offset and multiple of 2");6155case Match_MemSImm10Lsl2:6156return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6157"expected memory with 12-bit signed offset and multiple of 4");6158case Match_MemSImm10Lsl3:6159return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6160"expected memory with 13-bit signed offset and multiple of 8");6161case Match_MemSImm11:6162return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6163"expected memory with 11-bit signed offset");6164case Match_MemSImm12:6165return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6166"expected memory with 12-bit signed offset");6167case Match_MemSImm16:6168return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6169"expected memory with 16-bit signed offset");6170case Match_MemSImmPtr:6171return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6172"expected memory with 32-bit signed offset");6173case Match_RequiresPosSizeRange0_32: {6174SMLoc ErrorStart = Operands[3]->getStartLoc();6175SMLoc ErrorEnd = Operands[4]->getEndLoc();6176return Error(ErrorStart, "size plus position are not in the range 0 .. 32",6177SMRange(ErrorStart, ErrorEnd));6178}6179case Match_RequiresPosSizeUImm6: {6180SMLoc ErrorStart = Operands[3]->getStartLoc();6181SMLoc ErrorEnd = Operands[4]->getEndLoc();6182return Error(ErrorStart, "size plus position are not in the range 1 .. 63",6183SMRange(ErrorStart, ErrorEnd));6184}6185case Match_RequiresPosSizeRange33_64: {6186SMLoc ErrorStart = Operands[3]->getStartLoc();6187SMLoc ErrorEnd = Operands[4]->getEndLoc();6188return Error(ErrorStart, "size plus position are not in the range 33 .. 64",6189SMRange(ErrorStart, ErrorEnd));6190}6191}61926193llvm_unreachable("Implement any new match types added!");6194}61956196void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {6197if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)6198Warning(Loc, "used $at (currently $" + Twine(RegIndex) +6199") without \".set noat\"");6200}62016202void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {6203if (!AssemblerOptions.back()->isMacro())6204Warning(Loc, "macro instruction expanded into multiple instructions");6205}62066207void MipsAsmParser::ConvertXWPOperands(MCInst &Inst,6208const OperandVector &Operands) {6209assert(6210(Inst.getOpcode() == Mips::LWP_MM || Inst.getOpcode() == Mips::SWP_MM) &&6211"Unexpected instruction!");6212((MipsOperand &)*Operands[1]).addGPR32ZeroAsmRegOperands(Inst, 1);6213int NextReg = nextReg(((MipsOperand &)*Operands[1]).getGPR32Reg());6214Inst.addOperand(MCOperand::createReg(NextReg));6215((MipsOperand &)*Operands[2]).addMemOperands(Inst, 2);6216}62176218void6219MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,6220SMRange Range, bool ShowColors) {6221getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,6222Range, SMFixIt(Range, FixMsg),6223ShowColors);6224}62256226int MipsAsmParser::matchCPURegisterName(StringRef Name) {6227int CC;62286229CC = StringSwitch<unsigned>(Name)6230.Case("zero", 0)6231.Cases("at", "AT", 1)6232.Case("a0", 4)6233.Case("a1", 5)6234.Case("a2", 6)6235.Case("a3", 7)6236.Case("v0", 2)6237.Case("v1", 3)6238.Case("s0", 16)6239.Case("s1", 17)6240.Case("s2", 18)6241.Case("s3", 19)6242.Case("s4", 20)6243.Case("s5", 21)6244.Case("s6", 22)6245.Case("s7", 23)6246.Case("k0", 26)6247.Case("k1", 27)6248.Case("gp", 28)6249.Case("sp", 29)6250.Case("fp", 30)6251.Case("s8", 30)6252.Case("ra", 31)6253.Case("t0", 8)6254.Case("t1", 9)6255.Case("t2", 10)6256.Case("t3", 11)6257.Case("t4", 12)6258.Case("t5", 13)6259.Case("t6", 14)6260.Case("t7", 15)6261.Case("t8", 24)6262.Case("t9", 25)6263.Default(-1);62646265if (!(isABI_N32() || isABI_N64()))6266return CC;62676268if (12 <= CC && CC <= 15) {6269// Name is one of t4-t76270AsmToken RegTok = getLexer().peekTok();6271SMRange RegRange = RegTok.getLocRange();62726273StringRef FixedName = StringSwitch<StringRef>(Name)6274.Case("t4", "t0")6275.Case("t5", "t1")6276.Case("t6", "t2")6277.Case("t7", "t3")6278.Default("");6279assert(FixedName != "" && "Register name is not one of t4-t7.");62806281printWarningWithFixIt("register names $t4-$t7 are only available in O32.",6282"Did you mean $" + FixedName + "?", RegRange);6283}62846285// Although SGI documentation just cuts out t0-t3 for n32/n64,6286// GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t76287// We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.6288if (8 <= CC && CC <= 11)6289CC += 4;62906291if (CC == -1)6292CC = StringSwitch<unsigned>(Name)6293.Case("a4", 8)6294.Case("a5", 9)6295.Case("a6", 10)6296.Case("a7", 11)6297.Case("kt0", 26)6298.Case("kt1", 27)6299.Default(-1);63006301return CC;6302}63036304int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {6305int CC;63066307CC = StringSwitch<unsigned>(Name)6308.Case("hwr_cpunum", 0)6309.Case("hwr_synci_step", 1)6310.Case("hwr_cc", 2)6311.Case("hwr_ccres", 3)6312.Case("hwr_ulr", 29)6313.Default(-1);63146315return CC;6316}63176318int MipsAsmParser::matchFPURegisterName(StringRef Name) {6319if (Name[0] == 'f') {6320StringRef NumString = Name.substr(1);6321unsigned IntVal;6322if (NumString.getAsInteger(10, IntVal))6323return -1; // This is not an integer.6324if (IntVal > 31) // Maximum index for fpu register.6325return -1;6326return IntVal;6327}6328return -1;6329}63306331int MipsAsmParser::matchFCCRegisterName(StringRef Name) {6332if (Name.starts_with("fcc")) {6333StringRef NumString = Name.substr(3);6334unsigned IntVal;6335if (NumString.getAsInteger(10, IntVal))6336return -1; // This is not an integer.6337if (IntVal > 7) // There are only 8 fcc registers.6338return -1;6339return IntVal;6340}6341return -1;6342}63436344int MipsAsmParser::matchACRegisterName(StringRef Name) {6345if (Name.starts_with("ac")) {6346StringRef NumString = Name.substr(2);6347unsigned IntVal;6348if (NumString.getAsInteger(10, IntVal))6349return -1; // This is not an integer.6350if (IntVal > 3) // There are only 3 acc registers.6351return -1;6352return IntVal;6353}6354return -1;6355}63566357int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {6358unsigned IntVal;63596360if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))6361return -1;63626363if (IntVal > 31)6364return -1;63656366return IntVal;6367}63686369int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {6370int CC;63716372CC = StringSwitch<unsigned>(Name)6373.Case("msair", 0)6374.Case("msacsr", 1)6375.Case("msaaccess", 2)6376.Case("msasave", 3)6377.Case("msamodify", 4)6378.Case("msarequest", 5)6379.Case("msamap", 6)6380.Case("msaunmap", 7)6381.Default(-1);63826383return CC;6384}63856386bool MipsAsmParser::canUseATReg() {6387return AssemblerOptions.back()->getATRegIndex() != 0;6388}63896390unsigned MipsAsmParser::getATReg(SMLoc Loc) {6391unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();6392if (ATIndex == 0) {6393reportParseError(Loc,6394"pseudo-instruction requires $at, which is not available");6395return 0;6396}6397unsigned AT = getReg(6398(isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);6399return AT;6400}64016402unsigned MipsAsmParser::getReg(int RC, int RegNo) {6403return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);6404}64056406bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {6407MCAsmParser &Parser = getParser();6408LLVM_DEBUG(dbgs() << "parseOperand\n");64096410// Check if the current operand has a custom associated parser, if so, try to6411// custom parse the operand, or fallback to the general approach.6412ParseStatus Res = MatchOperandParserImpl(Operands, Mnemonic);6413if (Res.isSuccess())6414return false;6415// If there wasn't a custom match, try the generic matcher below. Otherwise,6416// there was a match, but an error occurred, in which case, just return that6417// the operand parsing failed.6418if (Res.isFailure())6419return true;64206421LLVM_DEBUG(dbgs() << ".. Generic Parser\n");64226423switch (getLexer().getKind()) {6424case AsmToken::Dollar: {6425// Parse the register.6426SMLoc S = Parser.getTok().getLoc();64276428// Almost all registers have been parsed by custom parsers. There is only6429// one exception to this. $zero (and it's alias $0) will reach this point6430// for div, divu, and similar instructions because it is not an operand6431// to the instruction definition but an explicit register. Special case6432// this situation for now.6433if (!parseAnyRegister(Operands).isNoMatch())6434return false;64356436// Maybe it is a symbol reference.6437StringRef Identifier;6438if (Parser.parseIdentifier(Identifier))6439return true;64406441SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);6442MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);6443// Otherwise create a symbol reference.6444const MCExpr *SymRef =6445MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());64466447Operands.push_back(MipsOperand::CreateImm(SymRef, S, E, *this));6448return false;6449}6450default: {6451LLVM_DEBUG(dbgs() << ".. generic integer expression\n");64526453const MCExpr *Expr;6454SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.6455if (getParser().parseExpression(Expr))6456return true;64576458SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);64596460Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));6461return false;6462}6463} // switch(getLexer().getKind())6464return true;6465}64666467bool MipsAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,6468SMLoc &EndLoc) {6469return !tryParseRegister(Reg, StartLoc, EndLoc).isSuccess();6470}64716472ParseStatus MipsAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,6473SMLoc &EndLoc) {6474SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;6475ParseStatus Res = parseAnyRegister(Operands);6476if (Res.isSuccess()) {6477assert(Operands.size() == 1);6478MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());6479StartLoc = Operand.getStartLoc();6480EndLoc = Operand.getEndLoc();64816482// AFAIK, we only support numeric registers and named GPR's in CFI6483// directives.6484// Don't worry about eating tokens before failing. Using an unrecognised6485// register is a parse error.6486if (Operand.isGPRAsmReg()) {6487// Resolve to GPR32 or GPR64 appropriately.6488Reg = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();6489}64906491return (Reg == (unsigned)-1) ? ParseStatus::NoMatch : ParseStatus::Success;6492}64936494assert(Operands.size() == 0);6495return (Reg == (unsigned)-1) ? ParseStatus::NoMatch : ParseStatus::Success;6496}64976498bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {6499SMLoc S;65006501if (isParenExpr)6502return getParser().parseParenExprOfDepth(0, Res, S);6503return getParser().parseExpression(Res);6504}65056506ParseStatus MipsAsmParser::parseMemOperand(OperandVector &Operands) {6507MCAsmParser &Parser = getParser();6508LLVM_DEBUG(dbgs() << "parseMemOperand\n");6509const MCExpr *IdVal = nullptr;6510SMLoc S;6511bool isParenExpr = false;6512ParseStatus Res = ParseStatus::NoMatch;6513// First operand is the offset.6514S = Parser.getTok().getLoc();65156516if (getLexer().getKind() == AsmToken::LParen) {6517Parser.Lex();6518isParenExpr = true;6519}65206521if (getLexer().getKind() != AsmToken::Dollar) {6522if (parseMemOffset(IdVal, isParenExpr))6523return ParseStatus::Failure;65246525const AsmToken &Tok = Parser.getTok(); // Get the next token.6526if (Tok.isNot(AsmToken::LParen)) {6527MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);6528if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {6529SMLoc E =6530SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);6531Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));6532return ParseStatus::Success;6533}6534if (Tok.is(AsmToken::EndOfStatement)) {6535SMLoc E =6536SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);65376538// Zero register assumed, add a memory operand with ZERO as its base.6539// "Base" will be managed by k_Memory.6540auto Base = MipsOperand::createGPRReg(65410, "0", getContext().getRegisterInfo(), S, E, *this);6542Operands.push_back(6543MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));6544return ParseStatus::Success;6545}6546MCBinaryExpr::Opcode Opcode;6547// GAS and LLVM treat comparison operators different. GAS will generate -16548// or 0, while LLVM will generate 0 or 1. Since a comparsion operator is6549// highly unlikely to be found in a memory offset expression, we don't6550// handle them.6551switch (Tok.getKind()) {6552case AsmToken::Plus:6553Opcode = MCBinaryExpr::Add;6554Parser.Lex();6555break;6556case AsmToken::Minus:6557Opcode = MCBinaryExpr::Sub;6558Parser.Lex();6559break;6560case AsmToken::Star:6561Opcode = MCBinaryExpr::Mul;6562Parser.Lex();6563break;6564case AsmToken::Pipe:6565Opcode = MCBinaryExpr::Or;6566Parser.Lex();6567break;6568case AsmToken::Amp:6569Opcode = MCBinaryExpr::And;6570Parser.Lex();6571break;6572case AsmToken::LessLess:6573Opcode = MCBinaryExpr::Shl;6574Parser.Lex();6575break;6576case AsmToken::GreaterGreater:6577Opcode = MCBinaryExpr::LShr;6578Parser.Lex();6579break;6580case AsmToken::Caret:6581Opcode = MCBinaryExpr::Xor;6582Parser.Lex();6583break;6584case AsmToken::Slash:6585Opcode = MCBinaryExpr::Div;6586Parser.Lex();6587break;6588case AsmToken::Percent:6589Opcode = MCBinaryExpr::Mod;6590Parser.Lex();6591break;6592default:6593return Error(Parser.getTok().getLoc(), "'(' or expression expected");6594}6595const MCExpr * NextExpr;6596if (getParser().parseExpression(NextExpr))6597return ParseStatus::Failure;6598IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext());6599}66006601Parser.Lex(); // Eat the '(' token.6602}66036604Res = parseAnyRegister(Operands);6605if (!Res.isSuccess())6606return Res;66076608if (Parser.getTok().isNot(AsmToken::RParen))6609return Error(Parser.getTok().getLoc(), "')' expected");66106611SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);66126613Parser.Lex(); // Eat the ')' token.66146615if (!IdVal)6616IdVal = MCConstantExpr::create(0, getContext());66176618// Replace the register operand with the memory operand.6619std::unique_ptr<MipsOperand> op(6620static_cast<MipsOperand *>(Operands.back().release()));6621// Remove the register from the operands.6622// "op" will be managed by k_Memory.6623Operands.pop_back();6624// Add the memory operand.6625if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {6626int64_t Imm;6627if (IdVal->evaluateAsAbsolute(Imm))6628IdVal = MCConstantExpr::create(Imm, getContext());6629else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)6630IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),6631getContext());6632}66336634Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));6635return ParseStatus::Success;6636}66376638bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {6639MCAsmParser &Parser = getParser();6640MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());6641if (!Sym)6642return false;66436644SMLoc S = Parser.getTok().getLoc();6645if (Sym->isVariable()) {6646const MCExpr *Expr = Sym->getVariableValue();6647if (Expr->getKind() == MCExpr::SymbolRef) {6648const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);6649StringRef DefSymbol = Ref->getSymbol().getName();6650if (DefSymbol.starts_with("$")) {6651ParseStatus Res =6652matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);6653if (Res.isSuccess()) {6654Parser.Lex();6655return true;6656}6657if (Res.isFailure())6658llvm_unreachable("Should never fail");6659}6660}6661} else if (Sym->isUnset()) {6662// If symbol is unset, it might be created in the `parseSetAssignment`6663// routine as an alias for a numeric register name.6664// Lookup in the aliases list.6665auto Entry = RegisterSets.find(Sym->getName());6666if (Entry != RegisterSets.end()) {6667ParseStatus Res =6668matchAnyRegisterWithoutDollar(Operands, Entry->getValue(), S);6669if (Res.isSuccess()) {6670Parser.Lex();6671return true;6672}6673}6674}66756676return false;6677}66786679ParseStatus MipsAsmParser::matchAnyRegisterNameWithoutDollar(6680OperandVector &Operands, StringRef Identifier, SMLoc S) {6681int Index = matchCPURegisterName(Identifier);6682if (Index != -1) {6683Operands.push_back(MipsOperand::createGPRReg(6684Index, Identifier, getContext().getRegisterInfo(), S,6685getLexer().getLoc(), *this));6686return ParseStatus::Success;6687}66886689Index = matchHWRegsRegisterName(Identifier);6690if (Index != -1) {6691Operands.push_back(MipsOperand::createHWRegsReg(6692Index, Identifier, getContext().getRegisterInfo(), S,6693getLexer().getLoc(), *this));6694return ParseStatus::Success;6695}66966697Index = matchFPURegisterName(Identifier);6698if (Index != -1) {6699Operands.push_back(MipsOperand::createFGRReg(6700Index, Identifier, getContext().getRegisterInfo(), S,6701getLexer().getLoc(), *this));6702return ParseStatus::Success;6703}67046705Index = matchFCCRegisterName(Identifier);6706if (Index != -1) {6707Operands.push_back(MipsOperand::createFCCReg(6708Index, Identifier, getContext().getRegisterInfo(), S,6709getLexer().getLoc(), *this));6710return ParseStatus::Success;6711}67126713Index = matchACRegisterName(Identifier);6714if (Index != -1) {6715Operands.push_back(MipsOperand::createACCReg(6716Index, Identifier, getContext().getRegisterInfo(), S,6717getLexer().getLoc(), *this));6718return ParseStatus::Success;6719}67206721Index = matchMSA128RegisterName(Identifier);6722if (Index != -1) {6723Operands.push_back(MipsOperand::createMSA128Reg(6724Index, Identifier, getContext().getRegisterInfo(), S,6725getLexer().getLoc(), *this));6726return ParseStatus::Success;6727}67286729Index = matchMSA128CtrlRegisterName(Identifier);6730if (Index != -1) {6731Operands.push_back(MipsOperand::createMSACtrlReg(6732Index, Identifier, getContext().getRegisterInfo(), S,6733getLexer().getLoc(), *this));6734return ParseStatus::Success;6735}67366737return ParseStatus::NoMatch;6738}67396740ParseStatus6741MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands,6742const AsmToken &Token, SMLoc S) {6743if (Token.is(AsmToken::Identifier)) {6744LLVM_DEBUG(dbgs() << ".. identifier\n");6745StringRef Identifier = Token.getIdentifier();6746return matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);6747}6748if (Token.is(AsmToken::Integer)) {6749LLVM_DEBUG(dbgs() << ".. integer\n");6750int64_t RegNum = Token.getIntVal();6751if (RegNum < 0 || RegNum > 31) {6752// Show the error, but treat invalid register6753// number as a normal one to continue parsing6754// and catch other possible errors.6755Error(getLexer().getLoc(), "invalid register number");6756}6757Operands.push_back(MipsOperand::createNumericReg(6758RegNum, Token.getString(), getContext().getRegisterInfo(), S,6759Token.getLoc(), *this));6760return ParseStatus::Success;6761}67626763LLVM_DEBUG(dbgs() << Token.getKind() << "\n");67646765return ParseStatus::NoMatch;6766}67676768ParseStatus6769MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {6770auto Token = getLexer().peekTok(false);6771return matchAnyRegisterWithoutDollar(Operands, Token, S);6772}67736774ParseStatus MipsAsmParser::parseAnyRegister(OperandVector &Operands) {6775MCAsmParser &Parser = getParser();6776LLVM_DEBUG(dbgs() << "parseAnyRegister\n");67776778auto Token = Parser.getTok();67796780SMLoc S = Token.getLoc();67816782if (Token.isNot(AsmToken::Dollar)) {6783LLVM_DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");6784if (Token.is(AsmToken::Identifier)) {6785if (searchSymbolAlias(Operands))6786return ParseStatus::Success;6787}6788LLVM_DEBUG(dbgs() << ".. !symalias -> NoMatch\n");6789return ParseStatus::NoMatch;6790}6791LLVM_DEBUG(dbgs() << ".. $\n");67926793ParseStatus Res = matchAnyRegisterWithoutDollar(Operands, S);6794if (Res.isSuccess()) {6795Parser.Lex(); // $6796Parser.Lex(); // identifier6797}6798return Res;6799}68006801ParseStatus MipsAsmParser::parseJumpTarget(OperandVector &Operands) {6802MCAsmParser &Parser = getParser();6803LLVM_DEBUG(dbgs() << "parseJumpTarget\n");68046805SMLoc S = getLexer().getLoc();68066807// Registers are a valid target and have priority over symbols.6808ParseStatus Res = parseAnyRegister(Operands);6809if (!Res.isNoMatch())6810return Res;68116812// Integers and expressions are acceptable6813const MCExpr *Expr = nullptr;6814if (Parser.parseExpression(Expr)) {6815// We have no way of knowing if a symbol was consumed so we must ParseFail6816return ParseStatus::Failure;6817}6818Operands.push_back(6819MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));6820return ParseStatus::Success;6821}68226823ParseStatus MipsAsmParser::parseInvNum(OperandVector &Operands) {6824MCAsmParser &Parser = getParser();6825const MCExpr *IdVal;6826// If the first token is '$' we may have register operand. We have to reject6827// cases where it is not a register. Complicating the matter is that6828// register names are not reserved across all ABIs.6829// Peek past the dollar to see if it's a register name for this ABI.6830SMLoc S = Parser.getTok().getLoc();6831if (Parser.getTok().is(AsmToken::Dollar)) {6832return matchCPURegisterName(Parser.getLexer().peekTok().getString()) == -16833? ParseStatus::Failure6834: ParseStatus::NoMatch;6835}6836if (getParser().parseExpression(IdVal))6837return ParseStatus::Failure;6838const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);6839if (!MCE)6840return ParseStatus::NoMatch;6841int64_t Val = MCE->getValue();6842SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);6843Operands.push_back(MipsOperand::CreateImm(6844MCConstantExpr::create(0 - Val, getContext()), S, E, *this));6845return ParseStatus::Success;6846}68476848ParseStatus MipsAsmParser::parseRegisterList(OperandVector &Operands) {6849MCAsmParser &Parser = getParser();6850SmallVector<unsigned, 10> Regs;6851unsigned RegNo;6852unsigned PrevReg = Mips::NoRegister;6853bool RegRange = false;6854SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;68556856if (Parser.getTok().isNot(AsmToken::Dollar))6857return ParseStatus::Failure;68586859SMLoc S = Parser.getTok().getLoc();6860while (parseAnyRegister(TmpOperands).isSuccess()) {6861SMLoc E = getLexer().getLoc();6862MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());6863RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();6864if (RegRange) {6865// Remove last register operand because registers from register range6866// should be inserted first.6867if ((isGP64bit() && RegNo == Mips::RA_64) ||6868(!isGP64bit() && RegNo == Mips::RA)) {6869Regs.push_back(RegNo);6870} else {6871unsigned TmpReg = PrevReg + 1;6872while (TmpReg <= RegNo) {6873if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||6874(((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&6875isGP64bit()))6876return Error(E, "invalid register operand");68776878PrevReg = TmpReg;6879Regs.push_back(TmpReg++);6880}6881}68826883RegRange = false;6884} else {6885if ((PrevReg == Mips::NoRegister) &&6886((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||6887(!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA))))6888return Error(E, "$16 or $31 expected");6889if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||6890(RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&6891!isGP64bit()) ||6892((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||6893(RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&6894isGP64bit())))6895return Error(E, "invalid register operand");6896if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&6897((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||6898(RegNo != Mips::FP_64 && RegNo != Mips::RA_64 && isGP64bit())))6899return Error(E, "consecutive register numbers expected");69006901Regs.push_back(RegNo);6902}69036904if (Parser.getTok().is(AsmToken::Minus))6905RegRange = true;69066907if (!Parser.getTok().isNot(AsmToken::Minus) &&6908!Parser.getTok().isNot(AsmToken::Comma))6909return Error(E, "',' or '-' expected");69106911Lex(); // Consume comma or minus6912if (Parser.getTok().isNot(AsmToken::Dollar))6913break;69146915PrevReg = RegNo;6916}69176918SMLoc E = Parser.getTok().getLoc();6919Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));6920parseMemOperand(Operands);6921return ParseStatus::Success;6922}69236924/// Sometimes (i.e. load/stores) the operand may be followed immediately by6925/// either this.6926/// ::= '(', register, ')'6927/// handle it before we iterate so we don't get tripped up by the lack of6928/// a comma.6929bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {6930MCAsmParser &Parser = getParser();6931if (getLexer().is(AsmToken::LParen)) {6932Operands.push_back(6933MipsOperand::CreateToken("(", getLexer().getLoc(), *this));6934Parser.Lex();6935if (parseOperand(Operands, Name)) {6936SMLoc Loc = getLexer().getLoc();6937return Error(Loc, "unexpected token in argument list");6938}6939if (Parser.getTok().isNot(AsmToken::RParen)) {6940SMLoc Loc = getLexer().getLoc();6941return Error(Loc, "unexpected token, expected ')'");6942}6943Operands.push_back(6944MipsOperand::CreateToken(")", getLexer().getLoc(), *this));6945Parser.Lex();6946}6947return false;6948}69496950/// Sometimes (i.e. in MSA) the operand may be followed immediately by6951/// either one of these.6952/// ::= '[', register, ']'6953/// ::= '[', integer, ']'6954/// handle it before we iterate so we don't get tripped up by the lack of6955/// a comma.6956bool MipsAsmParser::parseBracketSuffix(StringRef Name,6957OperandVector &Operands) {6958MCAsmParser &Parser = getParser();6959if (getLexer().is(AsmToken::LBrac)) {6960Operands.push_back(6961MipsOperand::CreateToken("[", getLexer().getLoc(), *this));6962Parser.Lex();6963if (parseOperand(Operands, Name)) {6964SMLoc Loc = getLexer().getLoc();6965return Error(Loc, "unexpected token in argument list");6966}6967if (Parser.getTok().isNot(AsmToken::RBrac)) {6968SMLoc Loc = getLexer().getLoc();6969return Error(Loc, "unexpected token, expected ']'");6970}6971Operands.push_back(6972MipsOperand::CreateToken("]", getLexer().getLoc(), *this));6973Parser.Lex();6974}6975return false;6976}69776978static std::string MipsMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS,6979unsigned VariantID = 0);69806981bool MipsAsmParser::areEqualRegs(const MCParsedAsmOperand &Op1,6982const MCParsedAsmOperand &Op2) const {6983// This target-overriden function exists to maintain current behaviour for6984// e.g.6985// dahi $3, $3, 0x56786986// as tested in test/MC/Mips/mips64r6/valid.s.6987// FIXME: Should this test actually fail with an error? If so, then remove6988// this overloaded method.6989if (!Op1.isReg() || !Op2.isReg())6990return true;6991return Op1.getReg() == Op2.getReg();6992}69936994bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,6995SMLoc NameLoc, OperandVector &Operands) {6996MCAsmParser &Parser = getParser();6997LLVM_DEBUG(dbgs() << "ParseInstruction\n");69986999// We have reached first instruction, module directive are now forbidden.7000getTargetStreamer().forbidModuleDirective();70017002// Check if we have valid mnemonic7003if (!mnemonicIsValid(Name, 0)) {7004FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());7005std::string Suggestion = MipsMnemonicSpellCheck(Name, FBS);7006return Error(NameLoc, "unknown instruction" + Suggestion);7007}7008// First operand in MCInst is instruction mnemonic.7009Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));70107011// Read the remaining operands.7012if (getLexer().isNot(AsmToken::EndOfStatement)) {7013// Read the first operand.7014if (parseOperand(Operands, Name)) {7015SMLoc Loc = getLexer().getLoc();7016return Error(Loc, "unexpected token in argument list");7017}7018if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))7019return true;7020// AFAIK, parenthesis suffixes are never on the first operand70217022while (getLexer().is(AsmToken::Comma)) {7023Parser.Lex(); // Eat the comma.7024// Parse and remember the operand.7025if (parseOperand(Operands, Name)) {7026SMLoc Loc = getLexer().getLoc();7027return Error(Loc, "unexpected token in argument list");7028}7029// Parse bracket and parenthesis suffixes before we iterate7030if (getLexer().is(AsmToken::LBrac)) {7031if (parseBracketSuffix(Name, Operands))7032return true;7033} else if (getLexer().is(AsmToken::LParen) &&7034parseParenSuffix(Name, Operands))7035return true;7036}7037}7038if (getLexer().isNot(AsmToken::EndOfStatement)) {7039SMLoc Loc = getLexer().getLoc();7040return Error(Loc, "unexpected token in argument list");7041}7042Parser.Lex(); // Consume the EndOfStatement.7043return false;7044}70457046// FIXME: Given that these have the same name, these should both be7047// consistent on affecting the Parser.7048bool MipsAsmParser::reportParseError(const Twine &ErrorMsg) {7049SMLoc Loc = getLexer().getLoc();7050return Error(Loc, ErrorMsg);7051}70527053bool MipsAsmParser::reportParseError(SMLoc Loc, const Twine &ErrorMsg) {7054return Error(Loc, ErrorMsg);7055}70567057bool MipsAsmParser::parseSetNoAtDirective() {7058MCAsmParser &Parser = getParser();7059// Line should look like: ".set noat".70607061// Set the $at register to $0.7062AssemblerOptions.back()->setATRegIndex(0);70637064Parser.Lex(); // Eat "noat".70657066// If this is not the end of the statement, report an error.7067if (getLexer().isNot(AsmToken::EndOfStatement)) {7068reportParseError("unexpected token, expected end of statement");7069return false;7070}70717072getTargetStreamer().emitDirectiveSetNoAt();7073Parser.Lex(); // Consume the EndOfStatement.7074return false;7075}70767077bool MipsAsmParser::parseSetAtDirective() {7078// Line can be: ".set at", which sets $at to $17079// or ".set at=$reg", which sets $at to $reg.7080MCAsmParser &Parser = getParser();7081Parser.Lex(); // Eat "at".70827083if (getLexer().is(AsmToken::EndOfStatement)) {7084// No register was specified, so we set $at to $1.7085AssemblerOptions.back()->setATRegIndex(1);70867087getTargetStreamer().emitDirectiveSetAt();7088Parser.Lex(); // Consume the EndOfStatement.7089return false;7090}70917092if (getLexer().isNot(AsmToken::Equal)) {7093reportParseError("unexpected token, expected equals sign");7094return false;7095}7096Parser.Lex(); // Eat "=".70977098if (getLexer().isNot(AsmToken::Dollar)) {7099if (getLexer().is(AsmToken::EndOfStatement)) {7100reportParseError("no register specified");7101return false;7102} else {7103reportParseError("unexpected token, expected dollar sign '$'");7104return false;7105}7106}7107Parser.Lex(); // Eat "$".71087109// Find out what "reg" is.7110unsigned AtRegNo;7111const AsmToken &Reg = Parser.getTok();7112if (Reg.is(AsmToken::Identifier)) {7113AtRegNo = matchCPURegisterName(Reg.getIdentifier());7114} else if (Reg.is(AsmToken::Integer)) {7115AtRegNo = Reg.getIntVal();7116} else {7117reportParseError("unexpected token, expected identifier or integer");7118return false;7119}71207121// Check if $reg is a valid register. If it is, set $at to $reg.7122if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {7123reportParseError("invalid register");7124return false;7125}7126Parser.Lex(); // Eat "reg".71277128// If this is not the end of the statement, report an error.7129if (getLexer().isNot(AsmToken::EndOfStatement)) {7130reportParseError("unexpected token, expected end of statement");7131return false;7132}71337134getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);71357136Parser.Lex(); // Consume the EndOfStatement.7137return false;7138}71397140bool MipsAsmParser::parseSetReorderDirective() {7141MCAsmParser &Parser = getParser();7142Parser.Lex();7143// If this is not the end of the statement, report an error.7144if (getLexer().isNot(AsmToken::EndOfStatement)) {7145reportParseError("unexpected token, expected end of statement");7146return false;7147}7148AssemblerOptions.back()->setReorder();7149getTargetStreamer().emitDirectiveSetReorder();7150Parser.Lex(); // Consume the EndOfStatement.7151return false;7152}71537154bool MipsAsmParser::parseSetNoReorderDirective() {7155MCAsmParser &Parser = getParser();7156Parser.Lex();7157// If this is not the end of the statement, report an error.7158if (getLexer().isNot(AsmToken::EndOfStatement)) {7159reportParseError("unexpected token, expected end of statement");7160return false;7161}7162AssemblerOptions.back()->setNoReorder();7163getTargetStreamer().emitDirectiveSetNoReorder();7164Parser.Lex(); // Consume the EndOfStatement.7165return false;7166}71677168bool MipsAsmParser::parseSetMacroDirective() {7169MCAsmParser &Parser = getParser();7170Parser.Lex();7171// If this is not the end of the statement, report an error.7172if (getLexer().isNot(AsmToken::EndOfStatement)) {7173reportParseError("unexpected token, expected end of statement");7174return false;7175}7176AssemblerOptions.back()->setMacro();7177getTargetStreamer().emitDirectiveSetMacro();7178Parser.Lex(); // Consume the EndOfStatement.7179return false;7180}71817182bool MipsAsmParser::parseSetNoMacroDirective() {7183MCAsmParser &Parser = getParser();7184Parser.Lex();7185// If this is not the end of the statement, report an error.7186if (getLexer().isNot(AsmToken::EndOfStatement)) {7187reportParseError("unexpected token, expected end of statement");7188return false;7189}7190if (AssemblerOptions.back()->isReorder()) {7191reportParseError("`noreorder' must be set before `nomacro'");7192return false;7193}7194AssemblerOptions.back()->setNoMacro();7195getTargetStreamer().emitDirectiveSetNoMacro();7196Parser.Lex(); // Consume the EndOfStatement.7197return false;7198}71997200bool MipsAsmParser::parseSetMsaDirective() {7201MCAsmParser &Parser = getParser();7202Parser.Lex();72037204// If this is not the end of the statement, report an error.7205if (getLexer().isNot(AsmToken::EndOfStatement))7206return reportParseError("unexpected token, expected end of statement");72077208setFeatureBits(Mips::FeatureMSA, "msa");7209getTargetStreamer().emitDirectiveSetMsa();7210return false;7211}72127213bool MipsAsmParser::parseSetNoMsaDirective() {7214MCAsmParser &Parser = getParser();7215Parser.Lex();72167217// If this is not the end of the statement, report an error.7218if (getLexer().isNot(AsmToken::EndOfStatement))7219return reportParseError("unexpected token, expected end of statement");72207221clearFeatureBits(Mips::FeatureMSA, "msa");7222getTargetStreamer().emitDirectiveSetNoMsa();7223return false;7224}72257226bool MipsAsmParser::parseSetNoDspDirective() {7227MCAsmParser &Parser = getParser();7228Parser.Lex(); // Eat "nodsp".72297230// If this is not the end of the statement, report an error.7231if (getLexer().isNot(AsmToken::EndOfStatement)) {7232reportParseError("unexpected token, expected end of statement");7233return false;7234}72357236clearFeatureBits(Mips::FeatureDSP, "dsp");7237getTargetStreamer().emitDirectiveSetNoDsp();7238return false;7239}72407241bool MipsAsmParser::parseSetNoMips3DDirective() {7242MCAsmParser &Parser = getParser();7243Parser.Lex(); // Eat "nomips3d".72447245// If this is not the end of the statement, report an error.7246if (getLexer().isNot(AsmToken::EndOfStatement)) {7247reportParseError("unexpected token, expected end of statement");7248return false;7249}72507251clearFeatureBits(Mips::FeatureMips3D, "mips3d");7252getTargetStreamer().emitDirectiveSetNoMips3D();7253return false;7254}72557256bool MipsAsmParser::parseSetMips16Directive() {7257MCAsmParser &Parser = getParser();7258Parser.Lex(); // Eat "mips16".72597260// If this is not the end of the statement, report an error.7261if (getLexer().isNot(AsmToken::EndOfStatement)) {7262reportParseError("unexpected token, expected end of statement");7263return false;7264}72657266setFeatureBits(Mips::FeatureMips16, "mips16");7267getTargetStreamer().emitDirectiveSetMips16();7268Parser.Lex(); // Consume the EndOfStatement.7269return false;7270}72717272bool MipsAsmParser::parseSetNoMips16Directive() {7273MCAsmParser &Parser = getParser();7274Parser.Lex(); // Eat "nomips16".72757276// If this is not the end of the statement, report an error.7277if (getLexer().isNot(AsmToken::EndOfStatement)) {7278reportParseError("unexpected token, expected end of statement");7279return false;7280}72817282clearFeatureBits(Mips::FeatureMips16, "mips16");7283getTargetStreamer().emitDirectiveSetNoMips16();7284Parser.Lex(); // Consume the EndOfStatement.7285return false;7286}72877288bool MipsAsmParser::parseSetFpDirective() {7289MCAsmParser &Parser = getParser();7290MipsABIFlagsSection::FpABIKind FpAbiVal;7291// Line can be: .set fp=327292// .set fp=xx7293// .set fp=647294Parser.Lex(); // Eat fp token7295AsmToken Tok = Parser.getTok();7296if (Tok.isNot(AsmToken::Equal)) {7297reportParseError("unexpected token, expected equals sign '='");7298return false;7299}7300Parser.Lex(); // Eat '=' token.7301Tok = Parser.getTok();73027303if (!parseFpABIValue(FpAbiVal, ".set"))7304return false;73057306if (getLexer().isNot(AsmToken::EndOfStatement)) {7307reportParseError("unexpected token, expected end of statement");7308return false;7309}7310getTargetStreamer().emitDirectiveSetFp(FpAbiVal);7311Parser.Lex(); // Consume the EndOfStatement.7312return false;7313}73147315bool MipsAsmParser::parseSetOddSPRegDirective() {7316MCAsmParser &Parser = getParser();73177318Parser.Lex(); // Eat "oddspreg".7319if (getLexer().isNot(AsmToken::EndOfStatement)) {7320reportParseError("unexpected token, expected end of statement");7321return false;7322}73237324clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");7325getTargetStreamer().emitDirectiveSetOddSPReg();7326return false;7327}73287329bool MipsAsmParser::parseSetNoOddSPRegDirective() {7330MCAsmParser &Parser = getParser();73317332Parser.Lex(); // Eat "nooddspreg".7333if (getLexer().isNot(AsmToken::EndOfStatement)) {7334reportParseError("unexpected token, expected end of statement");7335return false;7336}73377338setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");7339getTargetStreamer().emitDirectiveSetNoOddSPReg();7340return false;7341}73427343bool MipsAsmParser::parseSetMtDirective() {7344MCAsmParser &Parser = getParser();7345Parser.Lex(); // Eat "mt".73467347// If this is not the end of the statement, report an error.7348if (getLexer().isNot(AsmToken::EndOfStatement)) {7349reportParseError("unexpected token, expected end of statement");7350return false;7351}73527353setFeatureBits(Mips::FeatureMT, "mt");7354getTargetStreamer().emitDirectiveSetMt();7355Parser.Lex(); // Consume the EndOfStatement.7356return false;7357}73587359bool MipsAsmParser::parseSetNoMtDirective() {7360MCAsmParser &Parser = getParser();7361Parser.Lex(); // Eat "nomt".73627363// If this is not the end of the statement, report an error.7364if (getLexer().isNot(AsmToken::EndOfStatement)) {7365reportParseError("unexpected token, expected end of statement");7366return false;7367}73687369clearFeatureBits(Mips::FeatureMT, "mt");73707371getTargetStreamer().emitDirectiveSetNoMt();7372Parser.Lex(); // Consume the EndOfStatement.7373return false;7374}73757376bool MipsAsmParser::parseSetNoCRCDirective() {7377MCAsmParser &Parser = getParser();7378Parser.Lex(); // Eat "nocrc".73797380// If this is not the end of the statement, report an error.7381if (getLexer().isNot(AsmToken::EndOfStatement)) {7382reportParseError("unexpected token, expected end of statement");7383return false;7384}73857386clearFeatureBits(Mips::FeatureCRC, "crc");73877388getTargetStreamer().emitDirectiveSetNoCRC();7389Parser.Lex(); // Consume the EndOfStatement.7390return false;7391}73927393bool MipsAsmParser::parseSetNoVirtDirective() {7394MCAsmParser &Parser = getParser();7395Parser.Lex(); // Eat "novirt".73967397// If this is not the end of the statement, report an error.7398if (getLexer().isNot(AsmToken::EndOfStatement)) {7399reportParseError("unexpected token, expected end of statement");7400return false;7401}74027403clearFeatureBits(Mips::FeatureVirt, "virt");74047405getTargetStreamer().emitDirectiveSetNoVirt();7406Parser.Lex(); // Consume the EndOfStatement.7407return false;7408}74097410bool MipsAsmParser::parseSetNoGINVDirective() {7411MCAsmParser &Parser = getParser();7412Parser.Lex(); // Eat "noginv".74137414// If this is not the end of the statement, report an error.7415if (getLexer().isNot(AsmToken::EndOfStatement)) {7416reportParseError("unexpected token, expected end of statement");7417return false;7418}74197420clearFeatureBits(Mips::FeatureGINV, "ginv");74217422getTargetStreamer().emitDirectiveSetNoGINV();7423Parser.Lex(); // Consume the EndOfStatement.7424return false;7425}74267427bool MipsAsmParser::parseSetPopDirective() {7428MCAsmParser &Parser = getParser();7429SMLoc Loc = getLexer().getLoc();74307431Parser.Lex();7432if (getLexer().isNot(AsmToken::EndOfStatement))7433return reportParseError("unexpected token, expected end of statement");74347435// Always keep an element on the options "stack" to prevent the user7436// from changing the initial options. This is how we remember them.7437if (AssemblerOptions.size() == 2)7438return reportParseError(Loc, ".set pop with no .set push");74397440MCSubtargetInfo &STI = copySTI();7441AssemblerOptions.pop_back();7442setAvailableFeatures(7443ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));7444STI.setFeatureBits(AssemblerOptions.back()->getFeatures());74457446getTargetStreamer().emitDirectiveSetPop();7447return false;7448}74497450bool MipsAsmParser::parseSetPushDirective() {7451MCAsmParser &Parser = getParser();7452Parser.Lex();7453if (getLexer().isNot(AsmToken::EndOfStatement))7454return reportParseError("unexpected token, expected end of statement");74557456// Create a copy of the current assembler options environment and push it.7457AssemblerOptions.push_back(7458std::make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));74597460getTargetStreamer().emitDirectiveSetPush();7461return false;7462}74637464bool MipsAsmParser::parseSetSoftFloatDirective() {7465MCAsmParser &Parser = getParser();7466Parser.Lex();7467if (getLexer().isNot(AsmToken::EndOfStatement))7468return reportParseError("unexpected token, expected end of statement");74697470setFeatureBits(Mips::FeatureSoftFloat, "soft-float");7471getTargetStreamer().emitDirectiveSetSoftFloat();7472return false;7473}74747475bool MipsAsmParser::parseSetHardFloatDirective() {7476MCAsmParser &Parser = getParser();7477Parser.Lex();7478if (getLexer().isNot(AsmToken::EndOfStatement))7479return reportParseError("unexpected token, expected end of statement");74807481clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");7482getTargetStreamer().emitDirectiveSetHardFloat();7483return false;7484}74857486bool MipsAsmParser::parseSetAssignment() {7487StringRef Name;7488MCAsmParser &Parser = getParser();74897490if (Parser.parseIdentifier(Name))7491return reportParseError("expected identifier after .set");74927493if (getLexer().isNot(AsmToken::Comma))7494return reportParseError("unexpected token, expected comma");7495Lex(); // Eat comma74967497if (getLexer().is(AsmToken::Dollar) &&7498getLexer().peekTok().is(AsmToken::Integer)) {7499// Parse assignment of a numeric register:7500// .set r1,$17501Parser.Lex(); // Eat $.7502RegisterSets[Name] = Parser.getTok();7503Parser.Lex(); // Eat identifier.7504getContext().getOrCreateSymbol(Name);7505return false;7506}75077508MCSymbol *Sym;7509const MCExpr *Value;7510if (MCParserUtils::parseAssignmentExpression(Name, /* allow_redef */ true,7511Parser, Sym, Value))7512return true;7513Sym->setVariableValue(Value);75147515return false;7516}75177518bool MipsAsmParser::parseSetMips0Directive() {7519MCAsmParser &Parser = getParser();7520Parser.Lex();7521if (getLexer().isNot(AsmToken::EndOfStatement))7522return reportParseError("unexpected token, expected end of statement");75237524// Reset assembler options to their initial values.7525MCSubtargetInfo &STI = copySTI();7526setAvailableFeatures(7527ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));7528STI.setFeatureBits(AssemblerOptions.front()->getFeatures());7529AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());75307531getTargetStreamer().emitDirectiveSetMips0();7532return false;7533}75347535bool MipsAsmParser::parseSetArchDirective() {7536MCAsmParser &Parser = getParser();7537Parser.Lex();7538if (getLexer().isNot(AsmToken::Equal))7539return reportParseError("unexpected token, expected equals sign");75407541Parser.Lex();7542StringRef Arch = getParser().parseStringToEndOfStatement().trim();7543if (Arch.empty())7544return reportParseError("expected arch identifier");75457546StringRef ArchFeatureName =7547StringSwitch<StringRef>(Arch)7548.Case("mips1", "mips1")7549.Case("mips2", "mips2")7550.Case("mips3", "mips3")7551.Case("mips4", "mips4")7552.Case("mips5", "mips5")7553.Case("mips32", "mips32")7554.Case("mips32r2", "mips32r2")7555.Case("mips32r3", "mips32r3")7556.Case("mips32r5", "mips32r5")7557.Case("mips32r6", "mips32r6")7558.Case("mips64", "mips64")7559.Case("mips64r2", "mips64r2")7560.Case("mips64r3", "mips64r3")7561.Case("mips64r5", "mips64r5")7562.Case("mips64r6", "mips64r6")7563.Case("octeon", "cnmips")7564.Case("octeon+", "cnmipsp")7565.Case("r4000", "mips3") // This is an implementation of Mips3.7566.Default("");75677568if (ArchFeatureName.empty())7569return reportParseError("unsupported architecture");75707571if (ArchFeatureName == "mips64r6" && inMicroMipsMode())7572return reportParseError("mips64r6 does not support microMIPS");75737574selectArch(ArchFeatureName);7575getTargetStreamer().emitDirectiveSetArch(Arch);7576return false;7577}75787579bool MipsAsmParser::parseSetFeature(uint64_t Feature) {7580MCAsmParser &Parser = getParser();7581Parser.Lex();7582if (getLexer().isNot(AsmToken::EndOfStatement))7583return reportParseError("unexpected token, expected end of statement");75847585switch (Feature) {7586default:7587llvm_unreachable("Unimplemented feature");7588case Mips::FeatureMips3D:7589setFeatureBits(Mips::FeatureMips3D, "mips3d");7590getTargetStreamer().emitDirectiveSetMips3D();7591break;7592case Mips::FeatureDSP:7593setFeatureBits(Mips::FeatureDSP, "dsp");7594getTargetStreamer().emitDirectiveSetDsp();7595break;7596case Mips::FeatureDSPR2:7597setFeatureBits(Mips::FeatureDSPR2, "dspr2");7598getTargetStreamer().emitDirectiveSetDspr2();7599break;7600case Mips::FeatureMicroMips:7601setFeatureBits(Mips::FeatureMicroMips, "micromips");7602getTargetStreamer().emitDirectiveSetMicroMips();7603break;7604case Mips::FeatureMips1:7605selectArch("mips1");7606getTargetStreamer().emitDirectiveSetMips1();7607break;7608case Mips::FeatureMips2:7609selectArch("mips2");7610getTargetStreamer().emitDirectiveSetMips2();7611break;7612case Mips::FeatureMips3:7613selectArch("mips3");7614getTargetStreamer().emitDirectiveSetMips3();7615break;7616case Mips::FeatureMips4:7617selectArch("mips4");7618getTargetStreamer().emitDirectiveSetMips4();7619break;7620case Mips::FeatureMips5:7621selectArch("mips5");7622getTargetStreamer().emitDirectiveSetMips5();7623break;7624case Mips::FeatureMips32:7625selectArch("mips32");7626getTargetStreamer().emitDirectiveSetMips32();7627break;7628case Mips::FeatureMips32r2:7629selectArch("mips32r2");7630getTargetStreamer().emitDirectiveSetMips32R2();7631break;7632case Mips::FeatureMips32r3:7633selectArch("mips32r3");7634getTargetStreamer().emitDirectiveSetMips32R3();7635break;7636case Mips::FeatureMips32r5:7637selectArch("mips32r5");7638getTargetStreamer().emitDirectiveSetMips32R5();7639break;7640case Mips::FeatureMips32r6:7641selectArch("mips32r6");7642getTargetStreamer().emitDirectiveSetMips32R6();7643break;7644case Mips::FeatureMips64:7645selectArch("mips64");7646getTargetStreamer().emitDirectiveSetMips64();7647break;7648case Mips::FeatureMips64r2:7649selectArch("mips64r2");7650getTargetStreamer().emitDirectiveSetMips64R2();7651break;7652case Mips::FeatureMips64r3:7653selectArch("mips64r3");7654getTargetStreamer().emitDirectiveSetMips64R3();7655break;7656case Mips::FeatureMips64r5:7657selectArch("mips64r5");7658getTargetStreamer().emitDirectiveSetMips64R5();7659break;7660case Mips::FeatureMips64r6:7661selectArch("mips64r6");7662getTargetStreamer().emitDirectiveSetMips64R6();7663break;7664case Mips::FeatureCRC:7665setFeatureBits(Mips::FeatureCRC, "crc");7666getTargetStreamer().emitDirectiveSetCRC();7667break;7668case Mips::FeatureVirt:7669setFeatureBits(Mips::FeatureVirt, "virt");7670getTargetStreamer().emitDirectiveSetVirt();7671break;7672case Mips::FeatureGINV:7673setFeatureBits(Mips::FeatureGINV, "ginv");7674getTargetStreamer().emitDirectiveSetGINV();7675break;7676}7677return false;7678}76797680bool MipsAsmParser::eatComma(StringRef ErrorStr) {7681MCAsmParser &Parser = getParser();7682if (getLexer().isNot(AsmToken::Comma)) {7683SMLoc Loc = getLexer().getLoc();7684return Error(Loc, ErrorStr);7685}76867687Parser.Lex(); // Eat the comma.7688return true;7689}76907691// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.7692// In this class, it is only used for .cprestore.7693// FIXME: Only keep track of IsPicEnabled in one place, instead of in both7694// MipsTargetELFStreamer and MipsAsmParser.7695bool MipsAsmParser::isPicAndNotNxxAbi() {7696return inPicMode() && !(isABI_N32() || isABI_N64());7697}76987699bool MipsAsmParser::parseDirectiveCpAdd(SMLoc Loc) {7700SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;7701ParseStatus Res = parseAnyRegister(Reg);7702if (Res.isNoMatch() || Res.isFailure()) {7703reportParseError("expected register");7704return false;7705}77067707MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);7708if (!RegOpnd.isGPRAsmReg()) {7709reportParseError(RegOpnd.getStartLoc(), "invalid register");7710return false;7711}77127713// If this is not the end of the statement, report an error.7714if (getLexer().isNot(AsmToken::EndOfStatement)) {7715reportParseError("unexpected token, expected end of statement");7716return false;7717}7718getParser().Lex(); // Consume the EndOfStatement.77197720getTargetStreamer().emitDirectiveCpAdd(RegOpnd.getGPR32Reg());7721return false;7722}77237724bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {7725if (AssemblerOptions.back()->isReorder())7726Warning(Loc, ".cpload should be inside a noreorder section");77277728if (inMips16Mode()) {7729reportParseError(".cpload is not supported in Mips16 mode");7730return false;7731}77327733SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;7734ParseStatus Res = parseAnyRegister(Reg);7735if (Res.isNoMatch() || Res.isFailure()) {7736reportParseError("expected register containing function address");7737return false;7738}77397740MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);7741if (!RegOpnd.isGPRAsmReg()) {7742reportParseError(RegOpnd.getStartLoc(), "invalid register");7743return false;7744}77457746// If this is not the end of the statement, report an error.7747if (getLexer().isNot(AsmToken::EndOfStatement)) {7748reportParseError("unexpected token, expected end of statement");7749return false;7750}77517752getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());7753return false;7754}77557756bool MipsAsmParser::parseDirectiveCpLocal(SMLoc Loc) {7757if (!isABI_N32() && !isABI_N64()) {7758reportParseError(".cplocal is allowed only in N32 or N64 mode");7759return false;7760}77617762SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;7763ParseStatus Res = parseAnyRegister(Reg);7764if (Res.isNoMatch() || Res.isFailure()) {7765reportParseError("expected register containing global pointer");7766return false;7767}77687769MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);7770if (!RegOpnd.isGPRAsmReg()) {7771reportParseError(RegOpnd.getStartLoc(), "invalid register");7772return false;7773}77747775// If this is not the end of the statement, report an error.7776if (getLexer().isNot(AsmToken::EndOfStatement)) {7777reportParseError("unexpected token, expected end of statement");7778return false;7779}7780getParser().Lex(); // Consume the EndOfStatement.77817782unsigned NewReg = RegOpnd.getGPR32Reg();7783if (IsPicEnabled)7784GPReg = NewReg;77857786getTargetStreamer().emitDirectiveCpLocal(NewReg);7787return false;7788}77897790bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {7791MCAsmParser &Parser = getParser();77927793// Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it7794// is used in non-PIC mode.77957796if (inMips16Mode()) {7797reportParseError(".cprestore is not supported in Mips16 mode");7798return false;7799}78007801// Get the stack offset value.7802const MCExpr *StackOffset;7803int64_t StackOffsetVal;7804if (Parser.parseExpression(StackOffset)) {7805reportParseError("expected stack offset value");7806return false;7807}78087809if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {7810reportParseError("stack offset is not an absolute expression");7811return false;7812}78137814if (StackOffsetVal < 0) {7815Warning(Loc, ".cprestore with negative stack offset has no effect");7816IsCpRestoreSet = false;7817} else {7818IsCpRestoreSet = true;7819CpRestoreOffset = StackOffsetVal;7820}78217822// If this is not the end of the statement, report an error.7823if (getLexer().isNot(AsmToken::EndOfStatement)) {7824reportParseError("unexpected token, expected end of statement");7825return false;7826}78277828if (!getTargetStreamer().emitDirectiveCpRestore(7829CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))7830return true;7831Parser.Lex(); // Consume the EndOfStatement.7832return false;7833}78347835bool MipsAsmParser::parseDirectiveCPSetup() {7836MCAsmParser &Parser = getParser();7837unsigned FuncReg;7838unsigned Save;7839bool SaveIsReg = true;78407841SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;7842ParseStatus Res = parseAnyRegister(TmpReg);7843if (Res.isNoMatch()) {7844reportParseError("expected register containing function address");7845return false;7846}78477848MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);7849if (!FuncRegOpnd.isGPRAsmReg()) {7850reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");7851return false;7852}78537854FuncReg = FuncRegOpnd.getGPR32Reg();7855TmpReg.clear();78567857if (!eatComma("unexpected token, expected comma"))7858return true;78597860Res = parseAnyRegister(TmpReg);7861if (Res.isNoMatch()) {7862const MCExpr *OffsetExpr;7863int64_t OffsetVal;7864SMLoc ExprLoc = getLexer().getLoc();78657866if (Parser.parseExpression(OffsetExpr) ||7867!OffsetExpr->evaluateAsAbsolute(OffsetVal)) {7868reportParseError(ExprLoc, "expected save register or stack offset");7869return false;7870}78717872Save = OffsetVal;7873SaveIsReg = false;7874} else {7875MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);7876if (!SaveOpnd.isGPRAsmReg()) {7877reportParseError(SaveOpnd.getStartLoc(), "invalid register");7878return false;7879}7880Save = SaveOpnd.getGPR32Reg();7881}78827883if (!eatComma("unexpected token, expected comma"))7884return true;78857886const MCExpr *Expr;7887if (Parser.parseExpression(Expr)) {7888reportParseError("expected expression");7889return false;7890}78917892if (Expr->getKind() != MCExpr::SymbolRef) {7893reportParseError("expected symbol");7894return false;7895}7896const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);78977898CpSaveLocation = Save;7899CpSaveLocationIsRegister = SaveIsReg;79007901getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),7902SaveIsReg);7903return false;7904}79057906bool MipsAsmParser::parseDirectiveCPReturn() {7907getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,7908CpSaveLocationIsRegister);7909return false;7910}79117912bool MipsAsmParser::parseDirectiveNaN() {7913MCAsmParser &Parser = getParser();7914if (getLexer().isNot(AsmToken::EndOfStatement)) {7915const AsmToken &Tok = Parser.getTok();79167917if (Tok.getString() == "2008") {7918Parser.Lex();7919getTargetStreamer().emitDirectiveNaN2008();7920return false;7921} else if (Tok.getString() == "legacy") {7922Parser.Lex();7923getTargetStreamer().emitDirectiveNaNLegacy();7924return false;7925}7926}7927// If we don't recognize the option passed to the .nan7928// directive (e.g. no option or unknown option), emit an error.7929reportParseError("invalid option in .nan directive");7930return false;7931}79327933bool MipsAsmParser::parseDirectiveSet() {7934const AsmToken &Tok = getParser().getTok();7935StringRef IdVal = Tok.getString();7936SMLoc Loc = Tok.getLoc();79377938if (IdVal == "noat")7939return parseSetNoAtDirective();7940if (IdVal == "at")7941return parseSetAtDirective();7942if (IdVal == "arch")7943return parseSetArchDirective();7944if (IdVal == "bopt") {7945Warning(Loc, "'bopt' feature is unsupported");7946getParser().Lex();7947return false;7948}7949if (IdVal == "nobopt") {7950// We're already running in nobopt mode, so nothing to do.7951getParser().Lex();7952return false;7953}7954if (IdVal == "fp")7955return parseSetFpDirective();7956if (IdVal == "oddspreg")7957return parseSetOddSPRegDirective();7958if (IdVal == "nooddspreg")7959return parseSetNoOddSPRegDirective();7960if (IdVal == "pop")7961return parseSetPopDirective();7962if (IdVal == "push")7963return parseSetPushDirective();7964if (IdVal == "reorder")7965return parseSetReorderDirective();7966if (IdVal == "noreorder")7967return parseSetNoReorderDirective();7968if (IdVal == "macro")7969return parseSetMacroDirective();7970if (IdVal == "nomacro")7971return parseSetNoMacroDirective();7972if (IdVal == "mips16")7973return parseSetMips16Directive();7974if (IdVal == "nomips16")7975return parseSetNoMips16Directive();7976if (IdVal == "nomicromips") {7977clearFeatureBits(Mips::FeatureMicroMips, "micromips");7978getTargetStreamer().emitDirectiveSetNoMicroMips();7979getParser().eatToEndOfStatement();7980return false;7981}7982if (IdVal == "micromips") {7983if (hasMips64r6()) {7984Error(Loc, ".set micromips directive is not supported with MIPS64R6");7985return false;7986}7987return parseSetFeature(Mips::FeatureMicroMips);7988}7989if (IdVal == "mips0")7990return parseSetMips0Directive();7991if (IdVal == "mips1")7992return parseSetFeature(Mips::FeatureMips1);7993if (IdVal == "mips2")7994return parseSetFeature(Mips::FeatureMips2);7995if (IdVal == "mips3")7996return parseSetFeature(Mips::FeatureMips3);7997if (IdVal == "mips4")7998return parseSetFeature(Mips::FeatureMips4);7999if (IdVal == "mips5")8000return parseSetFeature(Mips::FeatureMips5);8001if (IdVal == "mips32")8002return parseSetFeature(Mips::FeatureMips32);8003if (IdVal == "mips32r2")8004return parseSetFeature(Mips::FeatureMips32r2);8005if (IdVal == "mips32r3")8006return parseSetFeature(Mips::FeatureMips32r3);8007if (IdVal == "mips32r5")8008return parseSetFeature(Mips::FeatureMips32r5);8009if (IdVal == "mips32r6")8010return parseSetFeature(Mips::FeatureMips32r6);8011if (IdVal == "mips64")8012return parseSetFeature(Mips::FeatureMips64);8013if (IdVal == "mips64r2")8014return parseSetFeature(Mips::FeatureMips64r2);8015if (IdVal == "mips64r3")8016return parseSetFeature(Mips::FeatureMips64r3);8017if (IdVal == "mips64r5")8018return parseSetFeature(Mips::FeatureMips64r5);8019if (IdVal == "mips64r6") {8020if (inMicroMipsMode()) {8021Error(Loc, "MIPS64R6 is not supported with microMIPS");8022return false;8023}8024return parseSetFeature(Mips::FeatureMips64r6);8025}8026if (IdVal == "dsp")8027return parseSetFeature(Mips::FeatureDSP);8028if (IdVal == "dspr2")8029return parseSetFeature(Mips::FeatureDSPR2);8030if (IdVal == "nodsp")8031return parseSetNoDspDirective();8032if (IdVal == "mips3d")8033return parseSetFeature(Mips::FeatureMips3D);8034if (IdVal == "nomips3d")8035return parseSetNoMips3DDirective();8036if (IdVal == "msa")8037return parseSetMsaDirective();8038if (IdVal == "nomsa")8039return parseSetNoMsaDirective();8040if (IdVal == "mt")8041return parseSetMtDirective();8042if (IdVal == "nomt")8043return parseSetNoMtDirective();8044if (IdVal == "softfloat")8045return parseSetSoftFloatDirective();8046if (IdVal == "hardfloat")8047return parseSetHardFloatDirective();8048if (IdVal == "crc")8049return parseSetFeature(Mips::FeatureCRC);8050if (IdVal == "nocrc")8051return parseSetNoCRCDirective();8052if (IdVal == "virt")8053return parseSetFeature(Mips::FeatureVirt);8054if (IdVal == "novirt")8055return parseSetNoVirtDirective();8056if (IdVal == "ginv")8057return parseSetFeature(Mips::FeatureGINV);8058if (IdVal == "noginv")8059return parseSetNoGINVDirective();80608061// It is just an identifier, look for an assignment.8062return parseSetAssignment();8063}80648065/// parseDirectiveGpWord8066/// ::= .gpword local_sym8067bool MipsAsmParser::parseDirectiveGpWord() {8068MCAsmParser &Parser = getParser();8069const MCExpr *Value;8070// EmitGPRel32Value requires an expression, so we are using base class8071// method to evaluate the expression.8072if (getParser().parseExpression(Value))8073return true;8074getParser().getStreamer().emitGPRel32Value(Value);80758076if (getLexer().isNot(AsmToken::EndOfStatement))8077return Error(getLexer().getLoc(),8078"unexpected token, expected end of statement");8079Parser.Lex(); // Eat EndOfStatement token.8080return false;8081}80828083/// parseDirectiveGpDWord8084/// ::= .gpdword local_sym8085bool MipsAsmParser::parseDirectiveGpDWord() {8086MCAsmParser &Parser = getParser();8087const MCExpr *Value;8088// EmitGPRel64Value requires an expression, so we are using base class8089// method to evaluate the expression.8090if (getParser().parseExpression(Value))8091return true;8092getParser().getStreamer().emitGPRel64Value(Value);80938094if (getLexer().isNot(AsmToken::EndOfStatement))8095return Error(getLexer().getLoc(),8096"unexpected token, expected end of statement");8097Parser.Lex(); // Eat EndOfStatement token.8098return false;8099}81008101/// parseDirectiveDtpRelWord8102/// ::= .dtprelword tls_sym8103bool MipsAsmParser::parseDirectiveDtpRelWord() {8104MCAsmParser &Parser = getParser();8105const MCExpr *Value;8106// EmitDTPRel32Value requires an expression, so we are using base class8107// method to evaluate the expression.8108if (getParser().parseExpression(Value))8109return true;8110getParser().getStreamer().emitDTPRel32Value(Value);81118112if (getLexer().isNot(AsmToken::EndOfStatement))8113return Error(getLexer().getLoc(),8114"unexpected token, expected end of statement");8115Parser.Lex(); // Eat EndOfStatement token.8116return false;8117}81188119/// parseDirectiveDtpRelDWord8120/// ::= .dtpreldword tls_sym8121bool MipsAsmParser::parseDirectiveDtpRelDWord() {8122MCAsmParser &Parser = getParser();8123const MCExpr *Value;8124// EmitDTPRel64Value requires an expression, so we are using base class8125// method to evaluate the expression.8126if (getParser().parseExpression(Value))8127return true;8128getParser().getStreamer().emitDTPRel64Value(Value);81298130if (getLexer().isNot(AsmToken::EndOfStatement))8131return Error(getLexer().getLoc(),8132"unexpected token, expected end of statement");8133Parser.Lex(); // Eat EndOfStatement token.8134return false;8135}81368137/// parseDirectiveTpRelWord8138/// ::= .tprelword tls_sym8139bool MipsAsmParser::parseDirectiveTpRelWord() {8140MCAsmParser &Parser = getParser();8141const MCExpr *Value;8142// EmitTPRel32Value requires an expression, so we are using base class8143// method to evaluate the expression.8144if (getParser().parseExpression(Value))8145return true;8146getParser().getStreamer().emitTPRel32Value(Value);81478148if (getLexer().isNot(AsmToken::EndOfStatement))8149return Error(getLexer().getLoc(),8150"unexpected token, expected end of statement");8151Parser.Lex(); // Eat EndOfStatement token.8152return false;8153}81548155/// parseDirectiveTpRelDWord8156/// ::= .tpreldword tls_sym8157bool MipsAsmParser::parseDirectiveTpRelDWord() {8158MCAsmParser &Parser = getParser();8159const MCExpr *Value;8160// EmitTPRel64Value requires an expression, so we are using base class8161// method to evaluate the expression.8162if (getParser().parseExpression(Value))8163return true;8164getParser().getStreamer().emitTPRel64Value(Value);81658166if (getLexer().isNot(AsmToken::EndOfStatement))8167return Error(getLexer().getLoc(),8168"unexpected token, expected end of statement");8169Parser.Lex(); // Eat EndOfStatement token.8170return false;8171}81728173bool MipsAsmParser::parseDirectiveOption() {8174MCAsmParser &Parser = getParser();8175// Get the option token.8176AsmToken Tok = Parser.getTok();8177// At the moment only identifiers are supported.8178if (Tok.isNot(AsmToken::Identifier)) {8179return Error(Parser.getTok().getLoc(),8180"unexpected token, expected identifier");8181}81828183StringRef Option = Tok.getIdentifier();81848185if (Option == "pic0") {8186// MipsAsmParser needs to know if the current PIC mode changes.8187IsPicEnabled = false;81888189getTargetStreamer().emitDirectiveOptionPic0();8190Parser.Lex();8191if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {8192return Error(Parser.getTok().getLoc(),8193"unexpected token, expected end of statement");8194}8195return false;8196}81978198if (Option == "pic2") {8199// MipsAsmParser needs to know if the current PIC mode changes.8200IsPicEnabled = true;82018202getTargetStreamer().emitDirectiveOptionPic2();8203Parser.Lex();8204if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {8205return Error(Parser.getTok().getLoc(),8206"unexpected token, expected end of statement");8207}8208return false;8209}82108211// Unknown option.8212Warning(Parser.getTok().getLoc(),8213"unknown option, expected 'pic0' or 'pic2'");8214Parser.eatToEndOfStatement();8215return false;8216}82178218/// parseInsnDirective8219/// ::= .insn8220bool MipsAsmParser::parseInsnDirective() {8221// If this is not the end of the statement, report an error.8222if (getLexer().isNot(AsmToken::EndOfStatement)) {8223reportParseError("unexpected token, expected end of statement");8224return false;8225}82268227// The actual label marking happens in8228// MipsELFStreamer::createPendingLabelRelocs().8229getTargetStreamer().emitDirectiveInsn();82308231getParser().Lex(); // Eat EndOfStatement token.8232return false;8233}82348235/// parseRSectionDirective8236/// ::= .rdata8237bool MipsAsmParser::parseRSectionDirective(StringRef Section) {8238// If this is not the end of the statement, report an error.8239if (getLexer().isNot(AsmToken::EndOfStatement)) {8240reportParseError("unexpected token, expected end of statement");8241return false;8242}82438244MCSection *ELFSection = getContext().getELFSection(8245Section, ELF::SHT_PROGBITS, ELF::SHF_ALLOC);8246getParser().getStreamer().switchSection(ELFSection);82478248getParser().Lex(); // Eat EndOfStatement token.8249return false;8250}82518252/// parseSSectionDirective8253/// ::= .sbss8254/// ::= .sdata8255bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {8256// If this is not the end of the statement, report an error.8257if (getLexer().isNot(AsmToken::EndOfStatement)) {8258reportParseError("unexpected token, expected end of statement");8259return false;8260}82618262MCSection *ELFSection = getContext().getELFSection(8263Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);8264getParser().getStreamer().switchSection(ELFSection);82658266getParser().Lex(); // Eat EndOfStatement token.8267return false;8268}82698270/// parseDirectiveModule8271/// ::= .module oddspreg8272/// ::= .module nooddspreg8273/// ::= .module fp=value8274/// ::= .module softfloat8275/// ::= .module hardfloat8276/// ::= .module mt8277/// ::= .module crc8278/// ::= .module nocrc8279/// ::= .module virt8280/// ::= .module novirt8281/// ::= .module ginv8282/// ::= .module noginv8283bool MipsAsmParser::parseDirectiveModule() {8284MCAsmParser &Parser = getParser();8285MCAsmLexer &Lexer = getLexer();8286SMLoc L = Lexer.getLoc();82878288if (!getTargetStreamer().isModuleDirectiveAllowed()) {8289// TODO : get a better message.8290reportParseError(".module directive must appear before any code");8291return false;8292}82938294StringRef Option;8295if (Parser.parseIdentifier(Option)) {8296reportParseError("expected .module option identifier");8297return false;8298}82998300if (Option == "oddspreg") {8301clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");83028303// Synchronize the abiflags information with the FeatureBits information we8304// changed above.8305getTargetStreamer().updateABIInfo(*this);83068307// If printing assembly, use the recently updated abiflags information.8308// If generating ELF, don't do anything (the .MIPS.abiflags section gets8309// emitted at the end).8310getTargetStreamer().emitDirectiveModuleOddSPReg();83118312// If this is not the end of the statement, report an error.8313if (getLexer().isNot(AsmToken::EndOfStatement)) {8314reportParseError("unexpected token, expected end of statement");8315return false;8316}83178318return false; // parseDirectiveModule has finished successfully.8319} else if (Option == "nooddspreg") {8320if (!isABI_O32()) {8321return Error(L, "'.module nooddspreg' requires the O32 ABI");8322}83238324setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");83258326// Synchronize the abiflags information with the FeatureBits information we8327// changed above.8328getTargetStreamer().updateABIInfo(*this);83298330// If printing assembly, use the recently updated abiflags information.8331// If generating ELF, don't do anything (the .MIPS.abiflags section gets8332// emitted at the end).8333getTargetStreamer().emitDirectiveModuleOddSPReg();83348335// If this is not the end of the statement, report an error.8336if (getLexer().isNot(AsmToken::EndOfStatement)) {8337reportParseError("unexpected token, expected end of statement");8338return false;8339}83408341return false; // parseDirectiveModule has finished successfully.8342} else if (Option == "fp") {8343return parseDirectiveModuleFP();8344} else if (Option == "softfloat") {8345setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");83468347// Synchronize the ABI Flags information with the FeatureBits information we8348// updated above.8349getTargetStreamer().updateABIInfo(*this);83508351// If printing assembly, use the recently updated ABI Flags information.8352// If generating ELF, don't do anything (the .MIPS.abiflags section gets8353// emitted later).8354getTargetStreamer().emitDirectiveModuleSoftFloat();83558356// If this is not the end of the statement, report an error.8357if (getLexer().isNot(AsmToken::EndOfStatement)) {8358reportParseError("unexpected token, expected end of statement");8359return false;8360}83618362return false; // parseDirectiveModule has finished successfully.8363} else if (Option == "hardfloat") {8364clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");83658366// Synchronize the ABI Flags information with the FeatureBits information we8367// updated above.8368getTargetStreamer().updateABIInfo(*this);83698370// If printing assembly, use the recently updated ABI Flags information.8371// If generating ELF, don't do anything (the .MIPS.abiflags section gets8372// emitted later).8373getTargetStreamer().emitDirectiveModuleHardFloat();83748375// If this is not the end of the statement, report an error.8376if (getLexer().isNot(AsmToken::EndOfStatement)) {8377reportParseError("unexpected token, expected end of statement");8378return false;8379}83808381return false; // parseDirectiveModule has finished successfully.8382} else if (Option == "mt") {8383setModuleFeatureBits(Mips::FeatureMT, "mt");83848385// Synchronize the ABI Flags information with the FeatureBits information we8386// updated above.8387getTargetStreamer().updateABIInfo(*this);83888389// If printing assembly, use the recently updated ABI Flags information.8390// If generating ELF, don't do anything (the .MIPS.abiflags section gets8391// emitted later).8392getTargetStreamer().emitDirectiveModuleMT();83938394// If this is not the end of the statement, report an error.8395if (getLexer().isNot(AsmToken::EndOfStatement)) {8396reportParseError("unexpected token, expected end of statement");8397return false;8398}83998400return false; // parseDirectiveModule has finished successfully.8401} else if (Option == "crc") {8402setModuleFeatureBits(Mips::FeatureCRC, "crc");84038404// Synchronize the ABI Flags information with the FeatureBits information we8405// updated above.8406getTargetStreamer().updateABIInfo(*this);84078408// If printing assembly, use the recently updated ABI Flags information.8409// If generating ELF, don't do anything (the .MIPS.abiflags section gets8410// emitted later).8411getTargetStreamer().emitDirectiveModuleCRC();84128413// If this is not the end of the statement, report an error.8414if (getLexer().isNot(AsmToken::EndOfStatement)) {8415reportParseError("unexpected token, expected end of statement");8416return false;8417}84188419return false; // parseDirectiveModule has finished successfully.8420} else if (Option == "nocrc") {8421clearModuleFeatureBits(Mips::FeatureCRC, "crc");84228423// Synchronize the ABI Flags information with the FeatureBits information we8424// updated above.8425getTargetStreamer().updateABIInfo(*this);84268427// If printing assembly, use the recently updated ABI Flags information.8428// If generating ELF, don't do anything (the .MIPS.abiflags section gets8429// emitted later).8430getTargetStreamer().emitDirectiveModuleNoCRC();84318432// If this is not the end of the statement, report an error.8433if (getLexer().isNot(AsmToken::EndOfStatement)) {8434reportParseError("unexpected token, expected end of statement");8435return false;8436}84378438return false; // parseDirectiveModule has finished successfully.8439} else if (Option == "virt") {8440setModuleFeatureBits(Mips::FeatureVirt, "virt");84418442// Synchronize the ABI Flags information with the FeatureBits information we8443// updated above.8444getTargetStreamer().updateABIInfo(*this);84458446// If printing assembly, use the recently updated ABI Flags information.8447// If generating ELF, don't do anything (the .MIPS.abiflags section gets8448// emitted later).8449getTargetStreamer().emitDirectiveModuleVirt();84508451// If this is not the end of the statement, report an error.8452if (getLexer().isNot(AsmToken::EndOfStatement)) {8453reportParseError("unexpected token, expected end of statement");8454return false;8455}84568457return false; // parseDirectiveModule has finished successfully.8458} else if (Option == "novirt") {8459clearModuleFeatureBits(Mips::FeatureVirt, "virt");84608461// Synchronize the ABI Flags information with the FeatureBits information we8462// updated above.8463getTargetStreamer().updateABIInfo(*this);84648465// If printing assembly, use the recently updated ABI Flags information.8466// If generating ELF, don't do anything (the .MIPS.abiflags section gets8467// emitted later).8468getTargetStreamer().emitDirectiveModuleNoVirt();84698470// If this is not the end of the statement, report an error.8471if (getLexer().isNot(AsmToken::EndOfStatement)) {8472reportParseError("unexpected token, expected end of statement");8473return false;8474}84758476return false; // parseDirectiveModule has finished successfully.8477} else if (Option == "ginv") {8478setModuleFeatureBits(Mips::FeatureGINV, "ginv");84798480// Synchronize the ABI Flags information with the FeatureBits information we8481// updated above.8482getTargetStreamer().updateABIInfo(*this);84838484// If printing assembly, use the recently updated ABI Flags information.8485// If generating ELF, don't do anything (the .MIPS.abiflags section gets8486// emitted later).8487getTargetStreamer().emitDirectiveModuleGINV();84888489// If this is not the end of the statement, report an error.8490if (getLexer().isNot(AsmToken::EndOfStatement)) {8491reportParseError("unexpected token, expected end of statement");8492return false;8493}84948495return false; // parseDirectiveModule has finished successfully.8496} else if (Option == "noginv") {8497clearModuleFeatureBits(Mips::FeatureGINV, "ginv");84988499// Synchronize the ABI Flags information with the FeatureBits information we8500// updated above.8501getTargetStreamer().updateABIInfo(*this);85028503// If printing assembly, use the recently updated ABI Flags information.8504// If generating ELF, don't do anything (the .MIPS.abiflags section gets8505// emitted later).8506getTargetStreamer().emitDirectiveModuleNoGINV();85078508// If this is not the end of the statement, report an error.8509if (getLexer().isNot(AsmToken::EndOfStatement)) {8510reportParseError("unexpected token, expected end of statement");8511return false;8512}85138514return false; // parseDirectiveModule has finished successfully.8515} else {8516return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");8517}8518}85198520/// parseDirectiveModuleFP8521/// ::= =328522/// ::= =xx8523/// ::= =648524bool MipsAsmParser::parseDirectiveModuleFP() {8525MCAsmParser &Parser = getParser();8526MCAsmLexer &Lexer = getLexer();85278528if (Lexer.isNot(AsmToken::Equal)) {8529reportParseError("unexpected token, expected equals sign '='");8530return false;8531}8532Parser.Lex(); // Eat '=' token.85338534MipsABIFlagsSection::FpABIKind FpABI;8535if (!parseFpABIValue(FpABI, ".module"))8536return false;85378538if (getLexer().isNot(AsmToken::EndOfStatement)) {8539reportParseError("unexpected token, expected end of statement");8540return false;8541}85428543// Synchronize the abiflags information with the FeatureBits information we8544// changed above.8545getTargetStreamer().updateABIInfo(*this);85468547// If printing assembly, use the recently updated abiflags information.8548// If generating ELF, don't do anything (the .MIPS.abiflags section gets8549// emitted at the end).8550getTargetStreamer().emitDirectiveModuleFP();85518552Parser.Lex(); // Consume the EndOfStatement.8553return false;8554}85558556bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,8557StringRef Directive) {8558MCAsmParser &Parser = getParser();8559MCAsmLexer &Lexer = getLexer();8560bool ModuleLevelOptions = Directive == ".module";85618562if (Lexer.is(AsmToken::Identifier)) {8563StringRef Value = Parser.getTok().getString();8564Parser.Lex();85658566if (Value != "xx") {8567reportParseError("unsupported value, expected 'xx', '32' or '64'");8568return false;8569}85708571if (!isABI_O32()) {8572reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");8573return false;8574}85758576FpABI = MipsABIFlagsSection::FpABIKind::XX;8577if (ModuleLevelOptions) {8578setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");8579clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");8580} else {8581setFeatureBits(Mips::FeatureFPXX, "fpxx");8582clearFeatureBits(Mips::FeatureFP64Bit, "fp64");8583}8584return true;8585}85868587if (Lexer.is(AsmToken::Integer)) {8588unsigned Value = Parser.getTok().getIntVal();8589Parser.Lex();85908591if (Value != 32 && Value != 64) {8592reportParseError("unsupported value, expected 'xx', '32' or '64'");8593return false;8594}85958596if (Value == 32) {8597if (!isABI_O32()) {8598reportParseError("'" + Directive + " fp=32' requires the O32 ABI");8599return false;8600}86018602FpABI = MipsABIFlagsSection::FpABIKind::S32;8603if (ModuleLevelOptions) {8604clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");8605clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");8606} else {8607clearFeatureBits(Mips::FeatureFPXX, "fpxx");8608clearFeatureBits(Mips::FeatureFP64Bit, "fp64");8609}8610} else {8611FpABI = MipsABIFlagsSection::FpABIKind::S64;8612if (ModuleLevelOptions) {8613clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");8614setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");8615} else {8616clearFeatureBits(Mips::FeatureFPXX, "fpxx");8617setFeatureBits(Mips::FeatureFP64Bit, "fp64");8618}8619}86208621return true;8622}86238624return false;8625}86268627bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {8628// This returns false if this function recognizes the directive8629// regardless of whether it is successfully handles or reports an8630// error. Otherwise it returns true to give the generic parser a8631// chance at recognizing it.86328633MCAsmParser &Parser = getParser();8634StringRef IDVal = DirectiveID.getString();86358636if (IDVal == ".cpadd") {8637parseDirectiveCpAdd(DirectiveID.getLoc());8638return false;8639}8640if (IDVal == ".cpload") {8641parseDirectiveCpLoad(DirectiveID.getLoc());8642return false;8643}8644if (IDVal == ".cprestore") {8645parseDirectiveCpRestore(DirectiveID.getLoc());8646return false;8647}8648if (IDVal == ".cplocal") {8649parseDirectiveCpLocal(DirectiveID.getLoc());8650return false;8651}8652if (IDVal == ".ent") {8653StringRef SymbolName;86548655if (Parser.parseIdentifier(SymbolName)) {8656reportParseError("expected identifier after .ent");8657return false;8658}86598660// There's an undocumented extension that allows an integer to8661// follow the name of the procedure which AFAICS is ignored by GAS.8662// Example: .ent foo,28663if (getLexer().isNot(AsmToken::EndOfStatement)) {8664if (getLexer().isNot(AsmToken::Comma)) {8665// Even though we accept this undocumented extension for compatibility8666// reasons, the additional integer argument does not actually change8667// the behaviour of the '.ent' directive, so we would like to discourage8668// its use. We do this by not referring to the extended version in8669// error messages which are not directly related to its use.8670reportParseError("unexpected token, expected end of statement");8671return false;8672}8673Parser.Lex(); // Eat the comma.8674const MCExpr *DummyNumber;8675int64_t DummyNumberVal;8676// If the user was explicitly trying to use the extended version,8677// we still give helpful extension-related error messages.8678if (Parser.parseExpression(DummyNumber)) {8679reportParseError("expected number after comma");8680return false;8681}8682if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {8683reportParseError("expected an absolute expression after comma");8684return false;8685}8686}86878688// If this is not the end of the statement, report an error.8689if (getLexer().isNot(AsmToken::EndOfStatement)) {8690reportParseError("unexpected token, expected end of statement");8691return false;8692}86938694MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);86958696getTargetStreamer().emitDirectiveEnt(*Sym);8697CurrentFn = Sym;8698IsCpRestoreSet = false;8699return false;8700}87018702if (IDVal == ".end") {8703StringRef SymbolName;87048705if (Parser.parseIdentifier(SymbolName)) {8706reportParseError("expected identifier after .end");8707return false;8708}87098710if (getLexer().isNot(AsmToken::EndOfStatement)) {8711reportParseError("unexpected token, expected end of statement");8712return false;8713}87148715if (CurrentFn == nullptr) {8716reportParseError(".end used without .ent");8717return false;8718}87198720if ((SymbolName != CurrentFn->getName())) {8721reportParseError(".end symbol does not match .ent symbol");8722return false;8723}87248725getTargetStreamer().emitDirectiveEnd(SymbolName);8726CurrentFn = nullptr;8727IsCpRestoreSet = false;8728return false;8729}87308731if (IDVal == ".frame") {8732// .frame $stack_reg, frame_size_in_bytes, $return_reg8733SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;8734ParseStatus Res = parseAnyRegister(TmpReg);8735if (Res.isNoMatch() || Res.isFailure()) {8736reportParseError("expected stack register");8737return false;8738}87398740MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);8741if (!StackRegOpnd.isGPRAsmReg()) {8742reportParseError(StackRegOpnd.getStartLoc(),8743"expected general purpose register");8744return false;8745}8746unsigned StackReg = StackRegOpnd.getGPR32Reg();87478748if (Parser.getTok().is(AsmToken::Comma))8749Parser.Lex();8750else {8751reportParseError("unexpected token, expected comma");8752return false;8753}87548755// Parse the frame size.8756const MCExpr *FrameSize;8757int64_t FrameSizeVal;87588759if (Parser.parseExpression(FrameSize)) {8760reportParseError("expected frame size value");8761return false;8762}87638764if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {8765reportParseError("frame size not an absolute expression");8766return false;8767}87688769if (Parser.getTok().is(AsmToken::Comma))8770Parser.Lex();8771else {8772reportParseError("unexpected token, expected comma");8773return false;8774}87758776// Parse the return register.8777TmpReg.clear();8778Res = parseAnyRegister(TmpReg);8779if (Res.isNoMatch() || Res.isFailure()) {8780reportParseError("expected return register");8781return false;8782}87838784MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);8785if (!ReturnRegOpnd.isGPRAsmReg()) {8786reportParseError(ReturnRegOpnd.getStartLoc(),8787"expected general purpose register");8788return false;8789}87908791// If this is not the end of the statement, report an error.8792if (getLexer().isNot(AsmToken::EndOfStatement)) {8793reportParseError("unexpected token, expected end of statement");8794return false;8795}87968797getTargetStreamer().emitFrame(StackReg, FrameSizeVal,8798ReturnRegOpnd.getGPR32Reg());8799IsCpRestoreSet = false;8800return false;8801}88028803if (IDVal == ".set") {8804parseDirectiveSet();8805return false;8806}88078808if (IDVal == ".mask" || IDVal == ".fmask") {8809// .mask bitmask, frame_offset8810// bitmask: One bit for each register used.8811// frame_offset: Offset from Canonical Frame Address ($sp on entry) where8812// first register is expected to be saved.8813// Examples:8814// .mask 0x80000000, -48815// .fmask 0x80000000, -48816//88178818// Parse the bitmask8819const MCExpr *BitMask;8820int64_t BitMaskVal;88218822if (Parser.parseExpression(BitMask)) {8823reportParseError("expected bitmask value");8824return false;8825}88268827if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {8828reportParseError("bitmask not an absolute expression");8829return false;8830}88318832if (Parser.getTok().is(AsmToken::Comma))8833Parser.Lex();8834else {8835reportParseError("unexpected token, expected comma");8836return false;8837}88388839// Parse the frame_offset8840const MCExpr *FrameOffset;8841int64_t FrameOffsetVal;88428843if (Parser.parseExpression(FrameOffset)) {8844reportParseError("expected frame offset value");8845return false;8846}88478848if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {8849reportParseError("frame offset not an absolute expression");8850return false;8851}88528853// If this is not the end of the statement, report an error.8854if (getLexer().isNot(AsmToken::EndOfStatement)) {8855reportParseError("unexpected token, expected end of statement");8856return false;8857}88588859if (IDVal == ".mask")8860getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);8861else8862getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);8863return false;8864}88658866if (IDVal == ".nan")8867return parseDirectiveNaN();88688869if (IDVal == ".gpword") {8870parseDirectiveGpWord();8871return false;8872}88738874if (IDVal == ".gpdword") {8875parseDirectiveGpDWord();8876return false;8877}88788879if (IDVal == ".dtprelword") {8880parseDirectiveDtpRelWord();8881return false;8882}88838884if (IDVal == ".dtpreldword") {8885parseDirectiveDtpRelDWord();8886return false;8887}88888889if (IDVal == ".tprelword") {8890parseDirectiveTpRelWord();8891return false;8892}88938894if (IDVal == ".tpreldword") {8895parseDirectiveTpRelDWord();8896return false;8897}88988899if (IDVal == ".option") {8900parseDirectiveOption();8901return false;8902}89038904if (IDVal == ".abicalls") {8905getTargetStreamer().emitDirectiveAbiCalls();8906if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {8907Error(Parser.getTok().getLoc(),8908"unexpected token, expected end of statement");8909}8910return false;8911}89128913if (IDVal == ".cpsetup") {8914parseDirectiveCPSetup();8915return false;8916}8917if (IDVal == ".cpreturn") {8918parseDirectiveCPReturn();8919return false;8920}8921if (IDVal == ".module") {8922parseDirectiveModule();8923return false;8924}8925if (IDVal == ".llvm_internal_mips_reallow_module_directive") {8926parseInternalDirectiveReallowModule();8927return false;8928}8929if (IDVal == ".insn") {8930parseInsnDirective();8931return false;8932}8933if (IDVal == ".rdata") {8934parseRSectionDirective(".rodata");8935return false;8936}8937if (IDVal == ".sbss") {8938parseSSectionDirective(IDVal, ELF::SHT_NOBITS);8939return false;8940}8941if (IDVal == ".sdata") {8942parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);8943return false;8944}89458946return true;8947}89488949bool MipsAsmParser::parseInternalDirectiveReallowModule() {8950// If this is not the end of the statement, report an error.8951if (getLexer().isNot(AsmToken::EndOfStatement)) {8952reportParseError("unexpected token, expected end of statement");8953return false;8954}89558956getTargetStreamer().reallowModuleDirective();89578958getParser().Lex(); // Eat EndOfStatement token.8959return false;8960}89618962extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMipsAsmParser() {8963RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget());8964RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget());8965RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target());8966RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget());8967}89688969#define GET_REGISTER_MATCHER8970#define GET_MATCHER_IMPLEMENTATION8971#define GET_MNEMONIC_SPELL_CHECKER8972#include "MipsGenAsmMatcher.inc"89738974bool MipsAsmParser::mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {8975// Find the appropriate table for this asm variant.8976const MatchEntry *Start, *End;8977switch (VariantID) {8978default: llvm_unreachable("invalid variant!");8979case 0: Start = std::begin(MatchTable0); End = std::end(MatchTable0); break;8980}8981// Search the table.8982auto MnemonicRange = std::equal_range(Start, End, Mnemonic, LessOpcode());8983return MnemonicRange.first != MnemonicRange.second;8984}898589868987