8940 lines · cpp
1//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "MCTargetDesc/MipsABIFlagsSection.h"10#include "MCTargetDesc/MipsABIInfo.h"11#include "MCTargetDesc/MipsBaseInfo.h"12#include "MCTargetDesc/MipsMCAsmInfo.h"13#include "MCTargetDesc/MipsMCTargetDesc.h"14#include "MCTargetDesc/MipsTargetStreamer.h"15#include "TargetInfo/MipsTargetInfo.h"16#include "llvm/ADT/APFloat.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/AsmLexer.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>59 60using namespace llvm;61 62#define DEBUG_TYPE "mips-asm-parser"63 64namespace llvm {65 66class MCInstrInfo;67 68} // end namespace llvm69 70extern cl::opt<bool> EmitJalrReloc;71 72namespace {73 74class MipsAssemblerOptions {75public:76 MipsAssemblerOptions(const FeatureBitset &Features_) : Features(Features_) {}77 78 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {79 ATReg = Opts->getATRegIndex();80 Reorder = Opts->isReorder();81 Macro = Opts->isMacro();82 Features = Opts->getFeatures();83 }84 85 unsigned getATRegIndex() const { return ATReg; }86 bool setATRegIndex(unsigned Reg) {87 if (Reg > 31)88 return false;89 90 ATReg = Reg;91 return true;92 }93 94 bool isReorder() const { return Reorder; }95 void setReorder() { Reorder = true; }96 void setNoReorder() { Reorder = false; }97 98 bool isMacro() const { return Macro; }99 void setMacro() { Macro = true; }100 void setNoMacro() { Macro = false; }101 102 const FeatureBitset &getFeatures() const { return Features; }103 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }104 105 // 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.110 static const FeatureBitset AllArchRelatedMask;111 112private:113 unsigned ATReg = 1;114 bool Reorder = true;115 bool Macro = true;116 FeatureBitset Features;117};118 119} // end anonymous namespace120 121const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {122 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,123 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,124 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,125 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,126 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,127 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,128 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,129 Mips::FeatureCnMipsP, Mips::FeatureFP64Bit, Mips::FeatureGP64Bit,130 Mips::FeatureNaN2008131};132 133namespace {134 135class MipsAsmParser : public MCTargetAsmParser {136 MipsTargetStreamer &getTargetStreamer() {137 assert(getParser().getStreamer().getTargetStreamer() &&138 "do not have a target streamer");139 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();140 return static_cast<MipsTargetStreamer &>(TS);141 }142 143 MipsABIInfo ABI;144 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;145 MCSymbol *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.149 bool IsLittleEndian;150 bool IsPicEnabled;151 bool IsCpRestoreSet;152 bool CurForbiddenSlotAttr;153 int CpRestoreOffset;154 MCRegister GPReg;155 unsigned CpSaveLocation;156 /// If true, then CpSaveLocation is a register, otherwise it's an offset.157 bool CpSaveLocationIsRegister;158 159 // Map of register aliases created via the .set directive.160 StringMap<AsmToken> RegisterSets;161 162 // Print a warning along with its fix-it message at the given range.163 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,164 SMRange Range, bool ShowColors = true);165 166 void ConvertXWPOperands(MCInst &Inst, const OperandVector &Operands);167 168#define GET_ASSEMBLER_HEADER169#include "MipsGenAsmMatcher.inc"170 171 unsigned172 checkEarlyTargetMatchPredicate(MCInst &Inst,173 const OperandVector &Operands) override;174 unsigned checkTargetMatchPredicate(MCInst &Inst) override;175 176 bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,177 OperandVector &Operands, MCStreamer &Out,178 uint64_t &ErrorInfo,179 bool MatchingInlineAsm) override;180 181 /// Parse a register as used in CFI directives182 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;183 ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,184 SMLoc &EndLoc) override;185 186 bool parseParenSuffix(StringRef Name, OperandVector &Operands);187 188 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);189 190 bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);191 192 bool parseInstruction(ParseInstructionInfo &Info, StringRef Name,193 SMLoc NameLoc, OperandVector &Operands) override;194 195 bool ParseDirective(AsmToken DirectiveID) override;196 197 ParseStatus parseMemOperand(OperandVector &Operands);198 ParseStatus matchAnyRegisterNameWithoutDollar(OperandVector &Operands,199 StringRef Identifier, SMLoc S);200 ParseStatus matchAnyRegisterWithoutDollar(OperandVector &Operands,201 const AsmToken &Token, SMLoc S);202 ParseStatus matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);203 ParseStatus parseAnyRegister(OperandVector &Operands);204 ParseStatus parseImm(OperandVector &Operands);205 ParseStatus parseJumpTarget(OperandVector &Operands);206 ParseStatus parseInvNum(OperandVector &Operands);207 ParseStatus parseRegisterList(OperandVector &Operands);208 const MCExpr *parseRelocExpr();209 210 bool searchSymbolAlias(OperandVector &Operands);211 212 bool parseOperand(OperandVector &, StringRef Mnemonic);213 214 enum MacroExpanderResultTy {215 MER_NotAMacro,216 MER_Success,217 MER_Fail,218 };219 220 // Expands assembly pseudo instructions.221 MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,222 MCStreamer &Out,223 const MCSubtargetInfo *STI);224 225 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,226 const MCSubtargetInfo *STI);227 228 bool loadImmediate(int64_t ImmValue, MCRegister DstReg, MCRegister SrcReg,229 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,230 MCStreamer &Out, const MCSubtargetInfo *STI);231 232 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, MCRegister DstReg,233 MCRegister SrcReg, bool Is32BitSym, SMLoc IDLoc,234 MCStreamer &Out, const MCSubtargetInfo *STI);235 236 bool emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc, MCSymbol *Sym);237 238 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,239 MCStreamer &Out, const MCSubtargetInfo *STI);240 241 bool expandLoadSingleImmToGPR(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,242 const MCSubtargetInfo *STI);243 bool expandLoadSingleImmToFPR(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,244 const MCSubtargetInfo *STI);245 bool expandLoadDoubleImmToGPR(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,246 const MCSubtargetInfo *STI);247 bool expandLoadDoubleImmToFPR(MCInst &Inst, bool Is64FPU, SMLoc IDLoc,248 MCStreamer &Out, const MCSubtargetInfo *STI);249 250 bool expandLoadAddress(MCRegister DstReg, MCRegister BaseReg,251 const MCOperand &Offset, bool Is32BitAddress,252 SMLoc IDLoc, MCStreamer &Out,253 const MCSubtargetInfo *STI);254 255 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,256 const MCSubtargetInfo *STI);257 258 void expandMem16Inst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,259 const MCSubtargetInfo *STI, bool IsLoad);260 void expandMem9Inst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,261 const MCSubtargetInfo *STI, bool IsLoad);262 263 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,264 const MCSubtargetInfo *STI);265 266 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,267 const MCSubtargetInfo *STI);268 269 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,270 const MCSubtargetInfo *STI);271 272 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,273 const MCSubtargetInfo *STI);274 275 bool expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,276 const MCSubtargetInfo *STI, const bool IsMips64,277 const bool Signed);278 279 bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,280 MCStreamer &Out, const MCSubtargetInfo *STI);281 282 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out,283 const MCSubtargetInfo *STI);284 285 bool expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,286 const MCSubtargetInfo *STI);287 288 bool expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,289 const MCSubtargetInfo *STI);290 291 bool expandSge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,292 const MCSubtargetInfo *STI);293 294 bool expandSgeImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,295 const MCSubtargetInfo *STI);296 297 bool expandSgtImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,298 const MCSubtargetInfo *STI);299 300 bool expandSle(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,301 const MCSubtargetInfo *STI);302 303 bool expandSleImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,304 const MCSubtargetInfo *STI);305 306 bool expandRotation(MCInst &Inst, SMLoc IDLoc,307 MCStreamer &Out, const MCSubtargetInfo *STI);308 bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,309 const MCSubtargetInfo *STI);310 bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,311 const MCSubtargetInfo *STI);312 bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,313 const MCSubtargetInfo *STI);314 315 bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,316 const MCSubtargetInfo *STI);317 318 bool expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,319 const MCSubtargetInfo *STI);320 321 bool expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,322 const MCSubtargetInfo *STI);323 324 bool expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,325 const MCSubtargetInfo *STI);326 327 bool expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,328 const MCSubtargetInfo *STI);329 330 bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,331 const MCSubtargetInfo *STI, bool IsLoad);332 333 bool expandStoreDM1Macro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,334 const MCSubtargetInfo *STI);335 336 bool expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,337 const MCSubtargetInfo *STI);338 339 bool expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,340 const MCSubtargetInfo *STI);341 342 bool expandSne(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,343 const MCSubtargetInfo *STI);344 345 bool expandSneI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,346 const MCSubtargetInfo *STI);347 348 bool expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,349 const MCSubtargetInfo *STI);350 351 bool expandSaaAddr(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,352 const MCSubtargetInfo *STI);353 354 bool reportParseError(const Twine &ErrorMsg);355 bool reportParseError(SMLoc Loc, const Twine &ErrorMsg);356 357 bool parseSetMips0Directive();358 bool parseSetArchDirective();359 bool parseSetFeature(uint64_t Feature);360 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.361 bool parseDirectiveCpAdd(SMLoc Loc);362 bool parseDirectiveCpLoad(SMLoc Loc);363 bool parseDirectiveCpLocal(SMLoc Loc);364 bool parseDirectiveCpRestore(SMLoc Loc);365 bool parseDirectiveCPSetup();366 bool parseDirectiveCPReturn();367 bool parseDirectiveNaN();368 bool parseDirectiveSet();369 bool parseDirectiveOption();370 bool parseInsnDirective();371 bool parseRSectionDirective(StringRef Section);372 bool parseSSectionDirective(StringRef Section, unsigned Type);373 374 bool parseSetAtDirective();375 bool parseSetNoAtDirective();376 bool parseSetMacroDirective();377 bool parseSetNoMacroDirective();378 bool parseSetMsaDirective();379 bool parseSetNoMsaDirective();380 bool parseSetNoDspDirective();381 bool parseSetNoMips3DDirective();382 bool parseSetReorderDirective();383 bool parseSetNoReorderDirective();384 bool parseSetMips16Directive();385 bool parseSetNoMips16Directive();386 bool parseSetFpDirective();387 bool parseSetOddSPRegDirective();388 bool parseSetNoOddSPRegDirective();389 bool parseSetPopDirective();390 bool parseSetPushDirective();391 bool parseSetSoftFloatDirective();392 bool parseSetHardFloatDirective();393 bool parseSetMtDirective();394 bool parseSetNoMtDirective();395 bool parseSetNoCRCDirective();396 bool parseSetNoVirtDirective();397 bool parseSetNoGINVDirective();398 399 bool parseSetAssignment();400 401 bool parseDirectiveGpWord();402 bool parseDirectiveGpDWord();403 bool parseDirectiveDtpRelWord();404 bool parseDirectiveDtpRelDWord();405 bool parseDirectiveTpRelWord();406 bool parseDirectiveTpRelDWord();407 bool parseDirectiveModule();408 bool parseDirectiveModuleFP();409 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,410 StringRef Directive);411 412 bool parseInternalDirectiveReallowModule();413 414 bool eatComma(StringRef ErrorStr);415 416 int matchCPURegisterName(StringRef Symbol);417 418 int matchHWRegsRegisterName(StringRef Symbol);419 420 int matchFPURegisterName(StringRef Name);421 422 int matchFCCRegisterName(StringRef Name);423 424 int matchACRegisterName(StringRef Name);425 426 int matchMSA128RegisterName(StringRef Name);427 428 int matchMSA128CtrlRegisterName(StringRef Name);429 430 MCRegister getReg(int RC, int RegNo);431 432 /// Returns the internal register number for the current AT. Also checks if433 /// the current AT is unavailable (set to $0) and gives an error if it is.434 /// This should be used in pseudo-instruction expansions which need AT.435 MCRegister getATReg(SMLoc Loc);436 437 bool canUseATReg();438 439 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,440 const MCSubtargetInfo *STI);441 442 // Helper function that checks if the value of a vector index is within the443 // boundaries of accepted values for each RegisterKind444 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0445 bool validateMSAIndex(int Val, int RegKind);446 447 // Selects a new architecture by updating the FeatureBits with the necessary448 // info including implied dependencies.449 // Internally, it clears all the feature bits related to *any* architecture450 // and selects the new one using the ToggleFeature functionality of the451 // MCSubtargetInfo object that handles implied dependencies. The reason we452 // clear all the arch related bits manually is because ToggleFeature only453 // clears the features that imply the feature being cleared and not the454 // features implied by the feature being cleared. This is easier to see455 // with an example:456 // --------------------------------------------------457 // | Feature | Implies |458 // | -------------------------------------------------|459 // | FeatureMips1 | None |460 // | FeatureMips2 | FeatureMips1 |461 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |462 // | FeatureMips4 | FeatureMips3 |463 // | ... | |464 // --------------------------------------------------465 //466 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |467 // FeatureMipsGP64 | FeatureMips1)468 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).469 void selectArch(StringRef ArchFeature) {470 MCSubtargetInfo &STI = copySTI();471 FeatureBitset FeatureBits = STI.getFeatureBits();472 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;473 STI.setFeatureBits(FeatureBits);474 setAvailableFeatures(475 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));476 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());477 }478 479 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {480 if (!(getSTI().hasFeature(Feature))) {481 MCSubtargetInfo &STI = copySTI();482 setAvailableFeatures(483 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));484 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());485 }486 }487 488 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {489 if (getSTI().hasFeature(Feature)) {490 MCSubtargetInfo &STI = copySTI();491 setAvailableFeatures(492 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));493 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());494 }495 }496 497 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {498 setFeatureBits(Feature, FeatureString);499 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());500 }501 502 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {503 clearFeatureBits(Feature, FeatureString);504 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());505 }506 507public:508 enum MipsMatchResultTy {509 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,510 Match_RequiresDifferentOperands,511 Match_RequiresNoZeroRegister,512 Match_RequiresSameSrcAndDst,513 Match_NoFCCRegisterForCurrentISA,514 Match_NonZeroOperandForSync,515 Match_NonZeroOperandForMTCX,516 Match_RequiresPosSizeRange0_32,517 Match_RequiresPosSizeRange33_64,518 Match_RequiresPosSizeUImm6,519#define GET_OPERAND_DIAGNOSTIC_TYPES520#include "MipsGenAsmMatcher.inc"521#undef GET_OPERAND_DIAGNOSTIC_TYPES522 };523 524 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,525 const MCInstrInfo &MII, const MCTargetOptions &Options)526 : MCTargetAsmParser(Options, sti, MII),527 ABI(MipsABIInfo::computeTargetABI(sti.getTargetTriple(),528 Options.getABIName())) {529 MCAsmParserExtension::Initialize(parser);530 531 parser.addAliasForDirective(".asciiz", ".asciz");532 parser.addAliasForDirective(".hword", ".2byte");533 parser.addAliasForDirective(".word", ".4byte");534 parser.addAliasForDirective(".dword", ".8byte");535 536 // Initialize the set of available features.537 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));538 539 // Remember the initial assembler options. The user can not modify these.540 AssemblerOptions.push_back(541 std::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));542 543 // Create an assembler options environment for the user to modify.544 AssemblerOptions.push_back(545 std::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));546 547 getTargetStreamer().updateABIInfo(*this);548 549 if (!isABI_O32() && !useOddSPReg() != 0)550 report_fatal_error("-mno-odd-spreg requires the O32 ABI");551 552 CurrentFn = nullptr;553 554 CurForbiddenSlotAttr = false;555 IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();556 557 IsCpRestoreSet = false;558 CpRestoreOffset = -1;559 GPReg = ABI.GetGlobalPtr();560 561 const Triple &TheTriple = sti.getTargetTriple();562 IsLittleEndian = TheTriple.isLittleEndian();563 564 if (getSTI().getCPU() == "mips64r6" && inMicroMipsMode())565 report_fatal_error("microMIPS64R6 is not supported", false);566 567 if (!isABI_O32() && inMicroMipsMode())568 report_fatal_error("microMIPS64 is not supported", false);569 }570 571 /// True if all of $fcc0 - $fcc7 exist for the current ISA.572 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }573 574 bool isGP64bit() const {575 return getSTI().hasFeature(Mips::FeatureGP64Bit);576 }577 578 bool isFP64bit() const {579 return getSTI().hasFeature(Mips::FeatureFP64Bit);580 }581 582 bool isJalrRelocAvailable(const MCExpr *JalExpr) {583 if (!EmitJalrReloc)584 return false;585 MCValue Res;586 if (!JalExpr->evaluateAsRelocatable(Res, nullptr))587 return false;588 if (Res.getSubSym())589 return false;590 if (Res.getConstant() != 0)591 return ABI.IsN32() || ABI.IsN64();592 return true;593 }594 595 const MipsABIInfo &getABI() const { return ABI; }596 bool isABI_N32() const { return ABI.IsN32(); }597 bool isABI_N64() const { return ABI.IsN64(); }598 bool isABI_O32() const { return ABI.IsO32(); }599 bool isABI_FPXX() const {600 return getSTI().hasFeature(Mips::FeatureFPXX);601 }602 603 bool useOddSPReg() const {604 return !(getSTI().hasFeature(Mips::FeatureNoOddSPReg));605 }606 607 bool inMicroMipsMode() const {608 return getSTI().hasFeature(Mips::FeatureMicroMips);609 }610 611 bool hasMips1() const {612 return getSTI().hasFeature(Mips::FeatureMips1);613 }614 615 bool hasMips2() const {616 return getSTI().hasFeature(Mips::FeatureMips2);617 }618 619 bool hasMips3() const {620 return getSTI().hasFeature(Mips::FeatureMips3);621 }622 623 bool hasMips4() const {624 return getSTI().hasFeature(Mips::FeatureMips4);625 }626 627 bool hasMips5() const {628 return getSTI().hasFeature(Mips::FeatureMips5);629 }630 631 bool hasMips32() const {632 return getSTI().hasFeature(Mips::FeatureMips32);633 }634 635 bool hasMips64() const {636 return getSTI().hasFeature(Mips::FeatureMips64);637 }638 639 bool hasMips32r2() const {640 return getSTI().hasFeature(Mips::FeatureMips32r2);641 }642 643 bool hasMips64r2() const {644 return getSTI().hasFeature(Mips::FeatureMips64r2);645 }646 647 bool hasMips32r3() const {648 return (getSTI().hasFeature(Mips::FeatureMips32r3));649 }650 651 bool hasMips64r3() const {652 return (getSTI().hasFeature(Mips::FeatureMips64r3));653 }654 655 bool hasMips32r5() const {656 return (getSTI().hasFeature(Mips::FeatureMips32r5));657 }658 659 bool hasMips64r5() const {660 return (getSTI().hasFeature(Mips::FeatureMips64r5));661 }662 663 bool hasMips32r6() const {664 return getSTI().hasFeature(Mips::FeatureMips32r6);665 }666 667 bool hasMips64r6() const {668 return getSTI().hasFeature(Mips::FeatureMips64r6);669 }670 671 bool hasDSP() const {672 return getSTI().hasFeature(Mips::FeatureDSP);673 }674 675 bool hasDSPR2() const {676 return getSTI().hasFeature(Mips::FeatureDSPR2);677 }678 679 bool hasDSPR3() const {680 return getSTI().hasFeature(Mips::FeatureDSPR3);681 }682 683 bool hasMSA() const {684 return getSTI().hasFeature(Mips::FeatureMSA);685 }686 687 bool hasCnMips() const {688 return (getSTI().hasFeature(Mips::FeatureCnMips));689 }690 691 bool hasCnMipsP() const {692 return (getSTI().hasFeature(Mips::FeatureCnMipsP));693 }694 695 bool inPicMode() {696 return IsPicEnabled;697 }698 699 bool inMips16Mode() const {700 return getSTI().hasFeature(Mips::FeatureMips16);701 }702 703 bool useTraps() const {704 return getSTI().hasFeature(Mips::FeatureUseTCCInDIV);705 }706 707 bool useSoftFloat() const {708 return getSTI().hasFeature(Mips::FeatureSoftFloat);709 }710 bool hasMT() const {711 return getSTI().hasFeature(Mips::FeatureMT);712 }713 714 bool hasCRC() const {715 return getSTI().hasFeature(Mips::FeatureCRC);716 }717 718 bool hasVirt() const {719 return getSTI().hasFeature(Mips::FeatureVirt);720 }721 722 bool hasGINV() const {723 return getSTI().hasFeature(Mips::FeatureGINV);724 }725 726 bool hasForbiddenSlot(const MCInstrDesc &MCID) const {727 return !inMicroMipsMode() && (MCID.TSFlags & MipsII::HasForbiddenSlot);728 }729 730 bool SafeInForbiddenSlot(const MCInstrDesc &MCID) const {731 return !(MCID.TSFlags & MipsII::IsCTI);732 }733 734 void onEndOfFile() override;735 736 /// Warn if RegIndex is the same as the current AT.737 void warnIfRegIndexIsAT(MCRegister RegIndex, SMLoc Loc);738 739 void warnIfNoMacro(SMLoc Loc);740 741 bool isLittle() const { return IsLittleEndian; }742 743 bool areEqualRegs(const MCParsedAsmOperand &Op1,744 const MCParsedAsmOperand &Op2) const override;745};746 747/// MipsOperand - Instances of this class represent a parsed Mips machine748/// instruction.749class MipsOperand : public MCParsedAsmOperand {750public:751 /// Broad categories of register classes752 /// The exact class is finalized by the render method.753 enum RegKind {754 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())755 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and756 /// isFP64bit())757 RegKind_FCC = 4, /// FCC758 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)759 RegKind_MSACtrl = 16, /// MSA control registers760 RegKind_COP2 = 32, /// COP2761 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on762 /// context).763 RegKind_CCR = 128, /// CCR764 RegKind_HWRegs = 256, /// HWRegs765 RegKind_COP3 = 512, /// COP3766 RegKind_COP0 = 1024, /// COP0767 /// Potentially any (e.g. $1)768 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |769 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |770 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0771 };772 773private:774 enum KindTy {775 k_Immediate, /// An immediate (possibly involving symbol references)776 k_Memory, /// Base + Offset Memory Address777 k_RegisterIndex, /// A register index in one or more RegKind.778 k_Token, /// A simple token779 k_RegList, /// A physical register list780 } Kind;781 782public:783 MipsOperand(KindTy K, MipsAsmParser &Parser) : Kind(K), AsmParser(Parser) {}784 785 ~MipsOperand() override {786 switch (Kind) {787 case k_Memory:788 delete Mem.Base;789 break;790 case k_RegList:791 delete RegList.List;792 break;793 case k_Immediate:794 case k_RegisterIndex:795 case k_Token:796 break;797 }798 }799 800private:801 /// For diagnostics, and checking the assembler temporary802 MipsAsmParser &AsmParser;803 804 struct Token {805 const char *Data;806 unsigned Length;807 };808 809 struct RegIdxOp {810 unsigned Index; /// Index into the register class811 RegKind Kind; /// Bitfield of the kinds it could possibly be812 struct Token Tok; /// The input token this operand originated from.813 const MCRegisterInfo *RegInfo;814 };815 816 struct ImmOp {817 const MCExpr *Val;818 };819 820 struct MemOp {821 MipsOperand *Base;822 const MCExpr *Off;823 };824 825 struct RegListOp {826 SmallVector<MCRegister, 10> *List;827 };828 829 union {830 struct Token Tok;831 struct RegIdxOp RegIdx;832 struct ImmOp Imm;833 struct MemOp Mem;834 struct RegListOp RegList;835 };836 837 SMLoc StartLoc, EndLoc;838 839 /// Internal constructor for register kinds840 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str,841 RegKind RegKind,842 const MCRegisterInfo *RegInfo,843 SMLoc S, SMLoc E,844 MipsAsmParser &Parser) {845 auto Op = std::make_unique<MipsOperand>(k_RegisterIndex, Parser);846 Op->RegIdx.Index = Index;847 Op->RegIdx.RegInfo = RegInfo;848 Op->RegIdx.Kind = RegKind;849 Op->RegIdx.Tok.Data = Str.data();850 Op->RegIdx.Tok.Length = Str.size();851 Op->StartLoc = S;852 Op->EndLoc = E;853 return Op;854 }855 856public:857 /// Coerce the register to GPR32 and return the real register for the current858 /// target.859 MCRegister getGPR32Reg() const {860 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");861 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);862 unsigned ClassID = Mips::GPR32RegClassID;863 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);864 }865 866 /// Coerce the register to GPR32 and return the real register for the current867 /// target.868 MCRegister getGPRMM16Reg() const {869 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");870 unsigned ClassID = Mips::GPR32RegClassID;871 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);872 }873 874 /// Coerce the register to GPR64 and return the real register for the current875 /// target.876 MCRegister getGPR64Reg() const {877 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");878 unsigned ClassID = Mips::GPR64RegClassID;879 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);880 }881 882private:883 /// Coerce the register to AFGR64 and return the real register for the current884 /// target.885 MCRegister getAFGR64Reg() const {886 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");887 if (RegIdx.Index % 2 != 0)888 AsmParser.Warning(StartLoc, "Float register should be even.");889 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)890 .getRegister(RegIdx.Index / 2);891 }892 893 /// Coerce the register to FGR64 and return the real register for the current894 /// target.895 MCRegister getFGR64Reg() const {896 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");897 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)898 .getRegister(RegIdx.Index);899 }900 901 /// Coerce the register to FGR32 and return the real register for the current902 /// target.903 MCRegister getFGR32Reg() const {904 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");905 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)906 .getRegister(RegIdx.Index);907 }908 909 /// Coerce the register to FCC and return the real register for the current910 /// target.911 MCRegister getFCCReg() const {912 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");913 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)914 .getRegister(RegIdx.Index);915 }916 917 /// Coerce the register to MSA128 and return the real register for the current918 /// target.919 MCRegister getMSA128Reg() const {920 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");921 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all922 // identical923 unsigned ClassID = Mips::MSA128BRegClassID;924 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);925 }926 927 /// Coerce the register to MSACtrl and return the real register for the928 /// current target.929 MCRegister getMSACtrlReg() const {930 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");931 unsigned ClassID = Mips::MSACtrlRegClassID;932 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);933 }934 935 /// Coerce the register to COP0 and return the real register for the936 /// current target.937 MCRegister getCOP0Reg() const {938 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");939 unsigned ClassID = Mips::COP0RegClassID;940 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);941 }942 943 /// Coerce the register to COP2 and return the real register for the944 /// current target.945 MCRegister getCOP2Reg() const {946 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");947 unsigned ClassID = Mips::COP2RegClassID;948 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);949 }950 951 /// Coerce the register to COP3 and return the real register for the952 /// current target.953 MCRegister getCOP3Reg() const {954 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");955 unsigned ClassID = Mips::COP3RegClassID;956 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);957 }958 959 /// Coerce the register to ACC64DSP and return the real register for the960 /// current target.961 MCRegister getACC64DSPReg() const {962 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");963 unsigned ClassID = Mips::ACC64DSPRegClassID;964 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);965 }966 967 /// Coerce the register to HI32DSP and return the real register for the968 /// current target.969 MCRegister getHI32DSPReg() const {970 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");971 unsigned ClassID = Mips::HI32DSPRegClassID;972 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);973 }974 975 /// Coerce the register to LO32DSP and return the real register for the976 /// current target.977 MCRegister getLO32DSPReg() const {978 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");979 unsigned ClassID = Mips::LO32DSPRegClassID;980 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);981 }982 983 /// Coerce the register to CCR and return the real register for the984 /// current target.985 MCRegister getCCRReg() const {986 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");987 unsigned ClassID = Mips::CCRRegClassID;988 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);989 }990 991 /// Coerce the register to HWRegs and return the real register for the992 /// current target.993 MCRegister getHWRegsReg() const {994 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");995 unsigned ClassID = Mips::HWRegsRegClassID;996 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);997 }998 999public:1000 void addExpr(MCInst &Inst, const MCExpr *Expr) const {1001 // Add as immediate when possible. Null MCExpr = 0.1002 if (!Expr)1003 Inst.addOperand(MCOperand::createImm(0));1004 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))1005 Inst.addOperand(MCOperand::createImm(CE->getValue()));1006 else1007 Inst.addOperand(MCOperand::createExpr(Expr));1008 }1009 1010 void addRegOperands(MCInst &Inst, unsigned N) const {1011 llvm_unreachable("Use a custom parser instead");1012 }1013 1014 /// Render the operand to an MCInst as a GPR321015 /// Asserts if the wrong number of operands are requested, or the operand1016 /// is not a k_RegisterIndex compatible with RegKind_GPR1017 void addGPR32ZeroAsmRegOperands(MCInst &Inst, unsigned N) const {1018 assert(N == 1 && "Invalid number of operands!");1019 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));1020 }1021 1022 void addGPR32NonZeroAsmRegOperands(MCInst &Inst, unsigned N) const {1023 assert(N == 1 && "Invalid number of operands!");1024 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));1025 }1026 1027 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {1028 assert(N == 1 && "Invalid number of operands!");1029 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));1030 }1031 1032 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {1033 assert(N == 1 && "Invalid number of operands!");1034 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));1035 }1036 1037 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {1038 assert(N == 1 && "Invalid number of operands!");1039 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));1040 }1041 1042 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {1043 assert(N == 1 && "Invalid number of operands!");1044 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));1045 }1046 1047 void addGPRMM16AsmRegMovePPairFirstOperands(MCInst &Inst, unsigned N) const {1048 assert(N == 1 && "Invalid number of operands!");1049 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));1050 }1051 1052 void addGPRMM16AsmRegMovePPairSecondOperands(MCInst &Inst,1053 unsigned N) const {1054 assert(N == 1 && "Invalid number of operands!");1055 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));1056 }1057 1058 /// Render the operand to an MCInst as a GPR641059 /// Asserts if the wrong number of operands are requested, or the operand1060 /// is not a k_RegisterIndex compatible with RegKind_GPR1061 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {1062 assert(N == 1 && "Invalid number of operands!");1063 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));1064 }1065 1066 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {1067 assert(N == 1 && "Invalid number of operands!");1068 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));1069 }1070 1071 void addStrictlyAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {1072 assert(N == 1 && "Invalid number of operands!");1073 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));1074 }1075 1076 void addStrictlyFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {1077 assert(N == 1 && "Invalid number of operands!");1078 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));1079 }1080 1081 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {1082 assert(N == 1 && "Invalid number of operands!");1083 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));1084 }1085 1086 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {1087 assert(N == 1 && "Invalid number of operands!");1088 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));1089 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.1090 // FIXME: This should propagate failure up to parseStatement.1091 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)1092 AsmParser.getParser().printError(1093 StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "1094 "registers");1095 }1096 1097 void addStrictlyFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {1098 assert(N == 1 && "Invalid number of operands!");1099 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));1100 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.1101 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)1102 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "1103 "registers");1104 }1105 1106 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {1107 assert(N == 1 && "Invalid number of operands!");1108 Inst.addOperand(MCOperand::createReg(getFCCReg()));1109 }1110 1111 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {1112 assert(N == 1 && "Invalid number of operands!");1113 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));1114 }1115 1116 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {1117 assert(N == 1 && "Invalid number of operands!");1118 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));1119 }1120 1121 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {1122 assert(N == 1 && "Invalid number of operands!");1123 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));1124 }1125 1126 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {1127 assert(N == 1 && "Invalid number of operands!");1128 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));1129 }1130 1131 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {1132 assert(N == 1 && "Invalid number of operands!");1133 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));1134 }1135 1136 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {1137 assert(N == 1 && "Invalid number of operands!");1138 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));1139 }1140 1141 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {1142 assert(N == 1 && "Invalid number of operands!");1143 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));1144 }1145 1146 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {1147 assert(N == 1 && "Invalid number of operands!");1148 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));1149 }1150 1151 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {1152 assert(N == 1 && "Invalid number of operands!");1153 Inst.addOperand(MCOperand::createReg(getCCRReg()));1154 }1155 1156 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {1157 assert(N == 1 && "Invalid number of operands!");1158 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));1159 }1160 1161 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>1162 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {1163 assert(N == 1 && "Invalid number of operands!");1164 uint64_t Imm = getConstantImm() - Offset;1165 Imm &= (1ULL << Bits) - 1;1166 Imm += Offset;1167 Imm += AdjustOffset;1168 Inst.addOperand(MCOperand::createImm(Imm));1169 }1170 1171 template <unsigned Bits>1172 void addSImmOperands(MCInst &Inst, unsigned N) const {1173 if (isImm() && !isConstantImm()) {1174 addExpr(Inst, getImm());1175 return;1176 }1177 addConstantSImmOperands<Bits, 0, 0>(Inst, N);1178 }1179 1180 template <unsigned Bits>1181 void addUImmOperands(MCInst &Inst, unsigned N) const {1182 if (isImm() && !isConstantImm()) {1183 addExpr(Inst, getImm());1184 return;1185 }1186 addConstantUImmOperands<Bits, 0, 0>(Inst, N);1187 }1188 1189 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>1190 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {1191 assert(N == 1 && "Invalid number of operands!");1192 int64_t Imm = getConstantImm() - Offset;1193 Imm = SignExtend64<Bits>(Imm);1194 Imm += Offset;1195 Imm += AdjustOffset;1196 Inst.addOperand(MCOperand::createImm(Imm));1197 }1198 1199 void addImmOperands(MCInst &Inst, unsigned N) const {1200 assert(N == 1 && "Invalid number of operands!");1201 const MCExpr *Expr = getImm();1202 addExpr(Inst, Expr);1203 }1204 1205 void addMemOperands(MCInst &Inst, unsigned N) const {1206 assert(N == 2 && "Invalid number of operands!");1207 1208 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()1209 ? getMemBase()->getGPR64Reg()1210 : getMemBase()->getGPR32Reg()));1211 1212 const MCExpr *Expr = getMemOff();1213 addExpr(Inst, Expr);1214 }1215 1216 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {1217 assert(N == 2 && "Invalid number of operands!");1218 1219 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));1220 1221 const MCExpr *Expr = getMemOff();1222 addExpr(Inst, Expr);1223 }1224 1225 void addRegListOperands(MCInst &Inst, unsigned N) const {1226 assert(N == 1 && "Invalid number of operands!");1227 1228 for (auto RegNo : getRegList())1229 Inst.addOperand(MCOperand::createReg(RegNo));1230 }1231 1232 bool isReg() const override {1233 // As a special case until we sort out the definition of div/divu, accept1234 // $0/$zero here so that MCK_ZERO works correctly.1235 return isGPRAsmReg() && RegIdx.Index == 0;1236 }1237 1238 bool isRegIdx() const { return Kind == k_RegisterIndex; }1239 bool isImm() const override { return Kind == k_Immediate; }1240 1241 bool isConstantImm() const {1242 int64_t Res;1243 return isImm() && getImm()->evaluateAsAbsolute(Res);1244 }1245 1246 bool isConstantImmz() const {1247 return isConstantImm() && getConstantImm() == 0;1248 }1249 1250 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {1251 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);1252 }1253 1254 template <unsigned Bits> bool isSImm() const {1255 if (!isImm())1256 return false;1257 int64_t Res;1258 if (getImm()->evaluateAsAbsolute(Res))1259 return isInt<Bits>(Res);1260 // Allow conservatively if not a parse-time constant.1261 return true;1262 }1263 1264 template <unsigned Bits> bool isUImm() const {1265 if (!isImm())1266 return false;1267 int64_t Res;1268 if (getImm()->evaluateAsAbsolute(Res))1269 return isUInt<Bits>(Res);1270 // Allow conservatively if not a parse-time constant.1271 return true;1272 }1273 1274 template <unsigned Bits> bool isAnyImm() const {1275 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||1276 isUInt<Bits>(getConstantImm()))1277 : isImm();1278 }1279 1280 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {1281 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);1282 }1283 1284 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {1285 return isConstantImm() && getConstantImm() >= Bottom &&1286 getConstantImm() <= Top;1287 }1288 1289 bool isToken() const override {1290 // Note: It's not possible to pretend that other operand kinds are tokens.1291 // The matcher emitter checks tokens first.1292 return Kind == k_Token;1293 }1294 1295 bool isMem() const override { return Kind == k_Memory; }1296 1297 bool isConstantMemOff() const {1298 return isMem() && isa<MCConstantExpr>(getMemOff());1299 }1300 1301 // Allow relocation operators.1302 template <unsigned Bits, unsigned ShiftAmount = 0>1303 bool isMemWithSimmOffset() const {1304 if (!isMem())1305 return false;1306 if (!getMemBase()->isGPRAsmReg())1307 return false;1308 if (isa<MCSpecifierExpr>(getMemOff()) ||1309 (isConstantMemOff() &&1310 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))1311 return true;1312 MCValue Res;1313 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr);1314 return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());1315 }1316 1317 bool isMemWithPtrSizeOffset() const {1318 if (!isMem())1319 return false;1320 if (!getMemBase()->isGPRAsmReg())1321 return false;1322 const unsigned PtrBits = AsmParser.getABI().ArePtrs64bit() ? 64 : 32;1323 if (isa<MCSpecifierExpr>(getMemOff()) ||1324 (isConstantMemOff() && isIntN(PtrBits, getConstantMemOff())))1325 return true;1326 MCValue Res;1327 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr);1328 return IsReloc && isIntN(PtrBits, Res.getConstant());1329 }1330 1331 bool isMemWithGRPMM16Base() const {1332 return isMem() && getMemBase()->isMM16AsmReg();1333 }1334 1335 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {1336 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())1337 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);1338 }1339 1340 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {1341 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())1342 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()1343 && (getMemBase()->getGPR32Reg() == Mips::SP);1344 }1345 1346 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {1347 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())1348 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()1349 && (getMemBase()->getGPR32Reg() == Mips::GP);1350 }1351 1352 template <unsigned Bits, unsigned ShiftLeftAmount>1353 bool isScaledUImm() const {1354 return isConstantImm() &&1355 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());1356 }1357 1358 template <unsigned Bits, unsigned ShiftLeftAmount>1359 bool isScaledSImm() const {1360 if (isConstantImm() &&1361 isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))1362 return true;1363 // Operand can also be a symbol or symbol plus1364 // offset in case of relocations.1365 if (Kind != k_Immediate)1366 return false;1367 MCValue Res;1368 bool Success = getImm()->evaluateAsRelocatable(Res, nullptr);1369 return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());1370 }1371 1372 bool isRegList16() const {1373 if (!isRegList())1374 return false;1375 1376 int Size = RegList.List->size();1377 if (Size < 2 || Size > 5)1378 return false;1379 1380 MCRegister R0 = RegList.List->front();1381 MCRegister R1 = RegList.List->back();1382 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||1383 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))1384 return false;1385 1386 MCRegister PrevReg = RegList.List->front();1387 for (int i = 1; i < Size - 1; i++) {1388 MCRegister Reg = (*(RegList.List))[i];1389 if ( Reg != PrevReg + 1)1390 return false;1391 PrevReg = Reg;1392 }1393 1394 return true;1395 }1396 1397 bool isInvNum() const { return Kind == k_Immediate; }1398 1399 bool isLSAImm() const {1400 if (!isConstantImm())1401 return false;1402 int64_t Val = getConstantImm();1403 return 1 <= Val && Val <= 4;1404 }1405 1406 bool isRegList() const { return Kind == k_RegList; }1407 1408 StringRef getToken() const {1409 assert(Kind == k_Token && "Invalid access!");1410 return StringRef(Tok.Data, Tok.Length);1411 }1412 1413 MCRegister getReg() const override {1414 // As a special case until we sort out the definition of div/divu, accept1415 // $0/$zero here so that MCK_ZERO works correctly.1416 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&1417 RegIdx.Kind & RegKind_GPR)1418 return getGPR32Reg(); // FIXME: GPR64 too1419 1420 llvm_unreachable("Invalid access!");1421 return 0;1422 }1423 1424 const MCExpr *getImm() const {1425 assert((Kind == k_Immediate) && "Invalid access!");1426 return Imm.Val;1427 }1428 1429 int64_t getConstantImm() const {1430 const MCExpr *Val = getImm();1431 int64_t Value = 0;1432 (void)Val->evaluateAsAbsolute(Value);1433 return Value;1434 }1435 1436 MipsOperand *getMemBase() const {1437 assert((Kind == k_Memory) && "Invalid access!");1438 return Mem.Base;1439 }1440 1441 const MCExpr *getMemOff() const {1442 assert((Kind == k_Memory) && "Invalid access!");1443 return Mem.Off;1444 }1445 1446 int64_t getConstantMemOff() const {1447 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();1448 }1449 1450 const SmallVectorImpl<MCRegister> &getRegList() const {1451 assert((Kind == k_RegList) && "Invalid access!");1452 return *(RegList.List);1453 }1454 1455 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,1456 MipsAsmParser &Parser) {1457 auto Op = std::make_unique<MipsOperand>(k_Token, Parser);1458 Op->Tok.Data = Str.data();1459 Op->Tok.Length = Str.size();1460 Op->StartLoc = S;1461 Op->EndLoc = S;1462 return Op;1463 }1464 1465 /// Create a numeric register (e.g. $1). The exact register remains1466 /// unresolved until an instruction successfully matches1467 static std::unique_ptr<MipsOperand>1468 createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,1469 SMLoc S, SMLoc E, MipsAsmParser &Parser) {1470 LLVM_DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");1471 return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);1472 }1473 1474 /// Create a register that is definitely a GPR.1475 /// This is typically only used for named registers such as $gp.1476 static std::unique_ptr<MipsOperand>1477 createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,1478 SMLoc S, SMLoc E, MipsAsmParser &Parser) {1479 return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser);1480 }1481 1482 /// Create a register that is definitely a FGR.1483 /// This is typically only used for named registers such as $f0.1484 static std::unique_ptr<MipsOperand>1485 createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,1486 SMLoc S, SMLoc E, MipsAsmParser &Parser) {1487 return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser);1488 }1489 1490 /// Create a register that is definitely a HWReg.1491 /// This is typically only used for named registers such as $hwr_cpunum.1492 static std::unique_ptr<MipsOperand>1493 createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,1494 SMLoc S, SMLoc E, MipsAsmParser &Parser) {1495 return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, Parser);1496 }1497 1498 /// Create a register that is definitely an FCC.1499 /// This is typically only used for named registers such as $fcc0.1500 static std::unique_ptr<MipsOperand>1501 createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,1502 SMLoc S, SMLoc E, MipsAsmParser &Parser) {1503 return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser);1504 }1505 1506 /// Create a register that is definitely an ACC.1507 /// This is typically only used for named registers such as $ac0.1508 static std::unique_ptr<MipsOperand>1509 createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,1510 SMLoc S, SMLoc E, MipsAsmParser &Parser) {1511 return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser);1512 }1513 1514 /// Create a register that is definitely an MSA128.1515 /// This is typically only used for named registers such as $w0.1516 static std::unique_ptr<MipsOperand>1517 createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,1518 SMLoc S, SMLoc E, MipsAsmParser &Parser) {1519 return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser);1520 }1521 1522 /// Create a register that is definitely an MSACtrl.1523 /// This is typically only used for named registers such as $msaaccess.1524 static std::unique_ptr<MipsOperand>1525 createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,1526 SMLoc S, SMLoc E, MipsAsmParser &Parser) {1527 return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser);1528 }1529 1530 static std::unique_ptr<MipsOperand>1531 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {1532 auto Op = std::make_unique<MipsOperand>(k_Immediate, Parser);1533 Op->Imm.Val = Val;1534 Op->StartLoc = S;1535 Op->EndLoc = E;1536 return Op;1537 }1538 1539 static std::unique_ptr<MipsOperand>1540 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,1541 SMLoc E, MipsAsmParser &Parser) {1542 auto Op = std::make_unique<MipsOperand>(k_Memory, Parser);1543 Op->Mem.Base = Base.release();1544 Op->Mem.Off = Off;1545 Op->StartLoc = S;1546 Op->EndLoc = E;1547 return Op;1548 }1549 1550 static std::unique_ptr<MipsOperand>1551 CreateRegList(SmallVectorImpl<MCRegister> &Regs, SMLoc StartLoc, SMLoc EndLoc,1552 MipsAsmParser &Parser) {1553 assert(!Regs.empty() && "Empty list not allowed");1554 1555 auto Op = std::make_unique<MipsOperand>(k_RegList, Parser);1556 Op->RegList.List =1557 new SmallVector<MCRegister, 10>(Regs.begin(), Regs.end());1558 Op->StartLoc = StartLoc;1559 Op->EndLoc = EndLoc;1560 return Op;1561 }1562 1563 bool isGPRZeroAsmReg() const {1564 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index == 0;1565 }1566 1567 bool isGPRNonZeroAsmReg() const {1568 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index > 0 &&1569 RegIdx.Index <= 31;1570 }1571 1572 bool isGPRAsmReg() const {1573 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;1574 }1575 1576 bool isMM16AsmReg() const {1577 if (!(isRegIdx() && RegIdx.Kind))1578 return false;1579 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)1580 || RegIdx.Index == 16 || RegIdx.Index == 17);1581 1582 }1583 bool isMM16AsmRegZero() const {1584 if (!(isRegIdx() && RegIdx.Kind))1585 return false;1586 return (RegIdx.Index == 0 ||1587 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||1588 RegIdx.Index == 17);1589 }1590 1591 bool isMM16AsmRegMoveP() const {1592 if (!(isRegIdx() && RegIdx.Kind))1593 return false;1594 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||1595 (RegIdx.Index >= 16 && RegIdx.Index <= 20));1596 }1597 1598 bool isMM16AsmRegMovePPairFirst() const {1599 if (!(isRegIdx() && RegIdx.Kind))1600 return false;1601 return RegIdx.Index >= 4 && RegIdx.Index <= 6;1602 }1603 1604 bool isMM16AsmRegMovePPairSecond() const {1605 if (!(isRegIdx() && RegIdx.Kind))1606 return false;1607 return (RegIdx.Index == 21 || RegIdx.Index == 22 ||1608 (RegIdx.Index >= 5 && RegIdx.Index <= 7));1609 }1610 1611 bool isFGRAsmReg() const {1612 // AFGR64 is $0-$15 but we handle this in getAFGR64()1613 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;1614 }1615 1616 bool isStrictlyFGRAsmReg() const {1617 // AFGR64 is $0-$15 but we handle this in getAFGR64()1618 return isRegIdx() && RegIdx.Kind == RegKind_FGR && RegIdx.Index <= 31;1619 }1620 1621 bool isHWRegsAsmReg() const {1622 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;1623 }1624 1625 bool isCCRAsmReg() const {1626 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;1627 }1628 1629 bool isFCCAsmReg() const {1630 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))1631 return false;1632 return RegIdx.Index <= 7;1633 }1634 1635 bool isACCAsmReg() const {1636 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;1637 }1638 1639 bool isCOP0AsmReg() const {1640 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;1641 }1642 1643 bool isCOP2AsmReg() const {1644 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;1645 }1646 1647 bool isCOP3AsmReg() const {1648 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;1649 }1650 1651 bool isMSA128AsmReg() const {1652 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;1653 }1654 1655 bool isMSACtrlAsmReg() const {1656 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;1657 }1658 1659 /// getStartLoc - Get the location of the first token of this operand.1660 SMLoc getStartLoc() const override { return StartLoc; }1661 /// getEndLoc - Get the location of the last token of this operand.1662 SMLoc getEndLoc() const override { return EndLoc; }1663 1664 void print(raw_ostream &OS, const MCAsmInfo &MAI) const override {1665 switch (Kind) {1666 case k_Immediate:1667 OS << "Imm<";1668 MAI.printExpr(OS, *Imm.Val);1669 OS << ">";1670 break;1671 case k_Memory:1672 OS << "Mem<";1673 Mem.Base->print(OS, MAI);1674 OS << ", ";1675 MAI.printExpr(OS, *Mem.Off);1676 OS << ">";1677 break;1678 case k_RegisterIndex:1679 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "1680 << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";1681 break;1682 case k_Token:1683 OS << getToken();1684 break;1685 case k_RegList:1686 OS << "RegList< ";1687 for (auto Reg : (*RegList.List))1688 OS << Reg.id() << " ";1689 OS << ">";1690 break;1691 }1692 }1693 1694 bool isValidForTie(const MipsOperand &Other) const {1695 if (Kind != Other.Kind)1696 return false;1697 1698 switch (Kind) {1699 default:1700 llvm_unreachable("Unexpected kind");1701 return false;1702 case k_RegisterIndex: {1703 StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);1704 StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);1705 return Token == OtherToken;1706 }1707 }1708 }1709}; // class MipsOperand1710 1711} // end anonymous namespace1712 1713static bool hasShortDelaySlot(MCInst &Inst) {1714 switch (Inst.getOpcode()) {1715 case Mips::BEQ_MM:1716 case Mips::BNE_MM:1717 case Mips::BLTZ_MM:1718 case Mips::BGEZ_MM:1719 case Mips::BLEZ_MM:1720 case Mips::BGTZ_MM:1721 case Mips::JRC16_MM:1722 case Mips::JALS_MM:1723 case Mips::JALRS_MM:1724 case Mips::JALRS16_MM:1725 case Mips::BGEZALS_MM:1726 case Mips::BLTZALS_MM:1727 return true;1728 case Mips::J_MM:1729 return !Inst.getOperand(0).isReg();1730 default:1731 return false;1732 }1733}1734 1735static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {1736 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {1737 return &SRExpr->getSymbol();1738 }1739 1740 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {1741 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());1742 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());1743 1744 if (LHSSym)1745 return LHSSym;1746 1747 if (RHSSym)1748 return RHSSym;1749 1750 return nullptr;1751 }1752 1753 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))1754 return getSingleMCSymbol(UExpr->getSubExpr());1755 1756 return nullptr;1757}1758 1759static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {1760 if (isa<MCSymbolRefExpr>(Expr))1761 return 1;1762 1763 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))1764 return countMCSymbolRefExpr(BExpr->getLHS()) +1765 countMCSymbolRefExpr(BExpr->getRHS());1766 1767 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))1768 return countMCSymbolRefExpr(UExpr->getSubExpr());1769 1770 return 0;1771}1772 1773static bool isEvaluated(const MCExpr *Expr) {1774 switch (Expr->getKind()) {1775 case MCExpr::Constant:1776 return true;1777 case MCExpr::SymbolRef:1778 return (cast<MCSymbolRefExpr>(Expr)->getSpecifier());1779 case MCExpr::Binary: {1780 const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);1781 if (!isEvaluated(BE->getLHS()))1782 return false;1783 return isEvaluated(BE->getRHS());1784 }1785 case MCExpr::Unary:1786 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());1787 case MCExpr::Specifier:1788 return true;1789 case MCExpr::Target:1790 llvm_unreachable("unused by this backend");1791 }1792 return false;1793}1794 1795static bool needsExpandMemInst(MCInst &Inst, const MCInstrDesc &MCID) {1796 unsigned NumOp = MCID.getNumOperands();1797 if (NumOp != 3 && NumOp != 4)1798 return false;1799 1800 const MCOperandInfo &OpInfo = MCID.operands()[NumOp - 1];1801 if (OpInfo.OperandType != MCOI::OPERAND_MEMORY &&1802 OpInfo.OperandType != MCOI::OPERAND_UNKNOWN &&1803 OpInfo.OperandType != MipsII::OPERAND_MEM_SIMM9)1804 return false;1805 1806 MCOperand &Op = Inst.getOperand(NumOp - 1);1807 if (Op.isImm()) {1808 if (OpInfo.OperandType == MipsII::OPERAND_MEM_SIMM9)1809 return !isInt<9>(Op.getImm());1810 // Offset can't exceed 16bit value.1811 return !isInt<16>(Op.getImm());1812 }1813 1814 if (Op.isExpr()) {1815 const MCExpr *Expr = Op.getExpr();1816 if (Expr->getKind() != MCExpr::SymbolRef)1817 return !isEvaluated(Expr);1818 1819 // Expand symbol.1820 const MCSymbolRefExpr *SR = static_cast<const MCSymbolRefExpr *>(Expr);1821 return SR->getSpecifier() == 0;1822 }1823 1824 return false;1825}1826 1827bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,1828 MCStreamer &Out,1829 const MCSubtargetInfo *STI) {1830 MipsTargetStreamer &TOut = getTargetStreamer();1831 const unsigned Opcode = Inst.getOpcode();1832 const MCInstrDesc &MCID = MII.get(Opcode);1833 bool ExpandedJalSym = false;1834 1835 Inst.setLoc(IDLoc);1836 1837 if (MCID.isBranch() || MCID.isCall()) {1838 MCOperand Offset;1839 1840 switch (Opcode) {1841 default:1842 break;1843 case Mips::BBIT0:1844 case Mips::BBIT032:1845 case Mips::BBIT1:1846 case Mips::BBIT132:1847 assert(hasCnMips() && "instruction only valid for octeon cpus");1848 [[fallthrough]];1849 1850 case Mips::BEQ:1851 case Mips::BNE:1852 case Mips::BEQ_MM:1853 case Mips::BNE_MM:1854 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");1855 Offset = Inst.getOperand(2);1856 if (!Offset.isImm())1857 break; // We'll deal with this situation later on when applying fixups.1858 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))1859 return Error(IDLoc, "branch target out of range");1860 if (offsetToAlignment(Offset.getImm(),1861 (inMicroMipsMode() ? Align(2) : Align(4))))1862 return Error(IDLoc, "branch to misaligned address");1863 break;1864 case Mips::BGEZ:1865 case Mips::BGTZ:1866 case Mips::BLEZ:1867 case Mips::BLTZ:1868 case Mips::BGEZAL:1869 case Mips::BLTZAL:1870 case Mips::BC1F:1871 case Mips::BC1T:1872 case Mips::BGEZ_MM:1873 case Mips::BGTZ_MM:1874 case Mips::BLEZ_MM:1875 case Mips::BLTZ_MM:1876 case Mips::BGEZAL_MM:1877 case Mips::BLTZAL_MM:1878 case Mips::BC1F_MM:1879 case Mips::BC1T_MM:1880 case Mips::BC1EQZC_MMR6:1881 case Mips::BC1NEZC_MMR6:1882 case Mips::BC2EQZC_MMR6:1883 case Mips::BC2NEZC_MMR6:1884 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");1885 Offset = Inst.getOperand(1);1886 if (!Offset.isImm())1887 break; // We'll deal with this situation later on when applying fixups.1888 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))1889 return Error(IDLoc, "branch target out of range");1890 if (offsetToAlignment(Offset.getImm(),1891 (inMicroMipsMode() ? Align(2) : Align(4))))1892 return Error(IDLoc, "branch to misaligned address");1893 break;1894 case Mips::BGEC: case Mips::BGEC_MMR6:1895 case Mips::BLTC: case Mips::BLTC_MMR6:1896 case Mips::BGEUC: case Mips::BGEUC_MMR6:1897 case Mips::BLTUC: case Mips::BLTUC_MMR6:1898 case Mips::BEQC: case Mips::BEQC_MMR6:1899 case Mips::BNEC: case Mips::BNEC_MMR6:1900 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");1901 Offset = Inst.getOperand(2);1902 if (!Offset.isImm())1903 break; // We'll deal with this situation later on when applying fixups.1904 if (!isIntN(18, Offset.getImm()))1905 return Error(IDLoc, "branch target out of range");1906 if (offsetToAlignment(Offset.getImm(), Align(4)))1907 return Error(IDLoc, "branch to misaligned address");1908 break;1909 case Mips::BLEZC: case Mips::BLEZC_MMR6:1910 case Mips::BGEZC: case Mips::BGEZC_MMR6:1911 case Mips::BGTZC: case Mips::BGTZC_MMR6:1912 case Mips::BLTZC: case Mips::BLTZC_MMR6:1913 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");1914 Offset = Inst.getOperand(1);1915 if (!Offset.isImm())1916 break; // We'll deal with this situation later on when applying fixups.1917 if (!isIntN(18, Offset.getImm()))1918 return Error(IDLoc, "branch target out of range");1919 if (offsetToAlignment(Offset.getImm(), Align(4)))1920 return Error(IDLoc, "branch to misaligned address");1921 break;1922 case Mips::BEQZC: case Mips::BEQZC_MMR6:1923 case Mips::BNEZC: case Mips::BNEZC_MMR6:1924 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");1925 Offset = Inst.getOperand(1);1926 if (!Offset.isImm())1927 break; // We'll deal with this situation later on when applying fixups.1928 if (!isIntN(23, Offset.getImm()))1929 return Error(IDLoc, "branch target out of range");1930 if (offsetToAlignment(Offset.getImm(), Align(4)))1931 return Error(IDLoc, "branch to misaligned address");1932 break;1933 case Mips::BEQZ16_MM:1934 case Mips::BEQZC16_MMR6:1935 case Mips::BNEZ16_MM:1936 case Mips::BNEZC16_MMR6:1937 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");1938 Offset = Inst.getOperand(1);1939 if (!Offset.isImm())1940 break; // We'll deal with this situation later on when applying fixups.1941 if (!isInt<8>(Offset.getImm()))1942 return Error(IDLoc, "branch target out of range");1943 if (offsetToAlignment(Offset.getImm(), Align(2)))1944 return Error(IDLoc, "branch to misaligned address");1945 break;1946 }1947 }1948 1949 // SSNOP is deprecated on MIPS32r6/MIPS64r61950 // We still accept it but it is a normal nop.1951 if (hasMips32r6() && Opcode == Mips::SSNOP) {1952 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";1953 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "1954 "nop instruction");1955 }1956 1957 if (hasCnMips()) {1958 MCOperand Opnd;1959 int Imm;1960 1961 switch (Opcode) {1962 default:1963 break;1964 1965 case Mips::BBIT0:1966 case Mips::BBIT032:1967 case Mips::BBIT1:1968 case Mips::BBIT132:1969 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");1970 // The offset is handled above1971 Opnd = Inst.getOperand(1);1972 if (!Opnd.isImm())1973 return Error(IDLoc, "expected immediate operand kind");1974 Imm = Opnd.getImm();1975 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||1976 Opcode == Mips::BBIT1 ? 63 : 31))1977 return Error(IDLoc, "immediate operand value out of range");1978 if (Imm > 31) {1979 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT0321980 : Mips::BBIT132);1981 Inst.getOperand(1).setImm(Imm - 32);1982 }1983 break;1984 1985 case Mips::SEQi:1986 case Mips::SNEi:1987 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");1988 Opnd = Inst.getOperand(2);1989 if (!Opnd.isImm())1990 return Error(IDLoc, "expected immediate operand kind");1991 Imm = Opnd.getImm();1992 if (!isInt<10>(Imm))1993 return Error(IDLoc, "immediate operand value out of range");1994 break;1995 }1996 }1997 1998 // Warn on division by zero. We're checking here as all instructions get1999 // processed here, not just the macros that need expansion.2000 //2001 // The MIPS backend models most of the divison instructions and macros as2002 // three operand instructions. The pre-R6 divide instructions however have2003 // two operands and explicitly define HI/LO as part of the instruction,2004 // not in the operands.2005 unsigned FirstOp = 1;2006 unsigned SecondOp = 2;2007 switch (Opcode) {2008 default:2009 break;2010 case Mips::SDivIMacro:2011 case Mips::UDivIMacro:2012 case Mips::DSDivIMacro:2013 case Mips::DUDivIMacro:2014 if (Inst.getOperand(2).getImm() == 0) {2015 if (Inst.getOperand(1).getReg() == Mips::ZERO ||2016 Inst.getOperand(1).getReg() == Mips::ZERO_64)2017 Warning(IDLoc, "dividing zero by zero");2018 else2019 Warning(IDLoc, "division by zero");2020 }2021 break;2022 case Mips::DSDIV:2023 case Mips::SDIV:2024 case Mips::UDIV:2025 case Mips::DUDIV:2026 case Mips::UDIV_MM:2027 case Mips::SDIV_MM:2028 FirstOp = 0;2029 SecondOp = 1;2030 [[fallthrough]];2031 case Mips::SDivMacro:2032 case Mips::DSDivMacro:2033 case Mips::UDivMacro:2034 case Mips::DUDivMacro:2035 case Mips::DIV:2036 case Mips::DIVU:2037 case Mips::DDIV:2038 case Mips::DDIVU:2039 case Mips::DIVU_MMR6:2040 case Mips::DIV_MMR6:2041 if (Inst.getOperand(SecondOp).getReg() == Mips::ZERO ||2042 Inst.getOperand(SecondOp).getReg() == Mips::ZERO_64) {2043 if (Inst.getOperand(FirstOp).getReg() == Mips::ZERO ||2044 Inst.getOperand(FirstOp).getReg() == Mips::ZERO_64)2045 Warning(IDLoc, "dividing zero by zero");2046 else2047 Warning(IDLoc, "division by zero");2048 }2049 break;2050 }2051 2052 // For PIC code convert unconditional jump to unconditional branch.2053 if ((Opcode == Mips::J || Opcode == Mips::J_MM) && inPicMode()) {2054 MCInst BInst;2055 BInst.setOpcode(inMicroMipsMode() ? Mips::BEQ_MM : Mips::BEQ);2056 BInst.addOperand(MCOperand::createReg(Mips::ZERO));2057 BInst.addOperand(MCOperand::createReg(Mips::ZERO));2058 BInst.addOperand(Inst.getOperand(0));2059 Inst = BInst;2060 }2061 2062 // This expansion is not in a function called by tryExpandInstruction()2063 // because the pseudo-instruction doesn't have a distinct opcode.2064 if ((Opcode == Mips::JAL || Opcode == Mips::JAL_MM) && inPicMode()) {2065 warnIfNoMacro(IDLoc);2066 2067 if (!Inst.getOperand(0).isExpr()) {2068 return Error(IDLoc, "unsupported constant in relocation");2069 }2070 2071 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();2072 2073 // We can do this expansion if there's only 1 symbol in the argument2074 // expression.2075 if (countMCSymbolRefExpr(JalExpr) > 1)2076 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");2077 2078 // FIXME: This is checking the expression can be handled by the later stages2079 // of the assembler. We ought to leave it to those later stages.2080 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);2081 2082 if (expandLoadAddress(Mips::T9, MCRegister(), Inst.getOperand(0),2083 !isGP64bit(), IDLoc, Out, STI))2084 return true;2085 2086 MCInst JalrInst;2087 if (inMicroMipsMode())2088 JalrInst.setOpcode(IsCpRestoreSet ? Mips::JALRS_MM : Mips::JALR_MM);2089 else2090 JalrInst.setOpcode(Mips::JALR);2091 JalrInst.addOperand(MCOperand::createReg(Mips::RA));2092 JalrInst.addOperand(MCOperand::createReg(Mips::T9));2093 2094 if (isJalrRelocAvailable(JalExpr)) {2095 // As an optimization hint for the linker, before the JALR we add:2096 // .reloc tmplabel, R_{MICRO}MIPS_JALR, symbol2097 // tmplabel:2098 MCSymbol *TmpLabel = getContext().createTempSymbol();2099 const MCExpr *TmpExpr = MCSymbolRefExpr::create(TmpLabel, getContext());2100 const MCExpr *RelocJalrExpr =2101 MCSymbolRefExpr::create(JalSym, getContext(), IDLoc);2102 2103 TOut.getStreamer().emitRelocDirective(2104 *TmpExpr, inMicroMipsMode() ? "R_MICROMIPS_JALR" : "R_MIPS_JALR",2105 RelocJalrExpr);2106 TOut.getStreamer().emitLabel(TmpLabel);2107 }2108 2109 Inst = JalrInst;2110 ExpandedJalSym = true;2111 }2112 2113 if (MCID.mayLoad() || MCID.mayStore()) {2114 // Check the offset of memory operand, if it is a symbol2115 // reference or immediate we may have to expand instructions.2116 if (needsExpandMemInst(Inst, MCID)) {2117 switch (MCID.operands()[MCID.getNumOperands() - 1].OperandType) {2118 case MipsII::OPERAND_MEM_SIMM9:2119 expandMem9Inst(Inst, IDLoc, Out, STI, MCID.mayLoad());2120 break;2121 default:2122 expandMem16Inst(Inst, IDLoc, Out, STI, MCID.mayLoad());2123 break;2124 }2125 return getParser().hasPendingError();2126 }2127 }2128 2129 if (inMicroMipsMode()) {2130 if (MCID.mayLoad() && Opcode != Mips::LWP_MM) {2131 // Try to create 16-bit GP relative load instruction.2132 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {2133 const MCOperandInfo &OpInfo = MCID.operands()[i];2134 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||2135 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {2136 MCOperand &Op = Inst.getOperand(i);2137 if (Op.isImm()) {2138 int MemOffset = Op.getImm();2139 MCOperand &DstReg = Inst.getOperand(0);2140 MCOperand &BaseReg = Inst.getOperand(1);2141 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&2142 getContext().getRegisterInfo()->getRegClass(2143 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&2144 (BaseReg.getReg() == Mips::GP ||2145 BaseReg.getReg() == Mips::GP_64)) {2146 2147 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,2148 IDLoc, STI);2149 return false;2150 }2151 }2152 }2153 } // for2154 } // if load2155 2156 // TODO: Handle this with the AsmOperandClass.PredicateMethod.2157 2158 MCOperand Opnd;2159 int Imm;2160 2161 switch (Opcode) {2162 default:2163 break;2164 case Mips::ADDIUSP_MM:2165 Opnd = Inst.getOperand(0);2166 if (!Opnd.isImm())2167 return Error(IDLoc, "expected immediate operand kind");2168 Imm = Opnd.getImm();2169 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||2170 Imm % 4 != 0)2171 return Error(IDLoc, "immediate operand value out of range");2172 break;2173 case Mips::SLL16_MM:2174 case Mips::SRL16_MM:2175 Opnd = Inst.getOperand(2);2176 if (!Opnd.isImm())2177 return Error(IDLoc, "expected immediate operand kind");2178 Imm = Opnd.getImm();2179 if (Imm < 1 || Imm > 8)2180 return Error(IDLoc, "immediate operand value out of range");2181 break;2182 case Mips::LI16_MM:2183 Opnd = Inst.getOperand(1);2184 if (!Opnd.isImm())2185 return Error(IDLoc, "expected immediate operand kind");2186 Imm = Opnd.getImm();2187 if (Imm < -1 || Imm > 126)2188 return Error(IDLoc, "immediate operand value out of range");2189 break;2190 case Mips::ADDIUR2_MM:2191 Opnd = Inst.getOperand(2);2192 if (!Opnd.isImm())2193 return Error(IDLoc, "expected immediate operand kind");2194 Imm = Opnd.getImm();2195 if (!(Imm == 1 || Imm == -1 ||2196 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))2197 return Error(IDLoc, "immediate operand value out of range");2198 break;2199 case Mips::ANDI16_MM:2200 Opnd = Inst.getOperand(2);2201 if (!Opnd.isImm())2202 return Error(IDLoc, "expected immediate operand kind");2203 Imm = Opnd.getImm();2204 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||2205 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||2206 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))2207 return Error(IDLoc, "immediate operand value out of range");2208 break;2209 case Mips::LBU16_MM:2210 Opnd = Inst.getOperand(2);2211 if (!Opnd.isImm())2212 return Error(IDLoc, "expected immediate operand kind");2213 Imm = Opnd.getImm();2214 if (Imm < -1 || Imm > 14)2215 return Error(IDLoc, "immediate operand value out of range");2216 break;2217 case Mips::SB16_MM:2218 case Mips::SB16_MMR6:2219 Opnd = Inst.getOperand(2);2220 if (!Opnd.isImm())2221 return Error(IDLoc, "expected immediate operand kind");2222 Imm = Opnd.getImm();2223 if (Imm < 0 || Imm > 15)2224 return Error(IDLoc, "immediate operand value out of range");2225 break;2226 case Mips::LHU16_MM:2227 case Mips::SH16_MM:2228 case Mips::SH16_MMR6:2229 Opnd = Inst.getOperand(2);2230 if (!Opnd.isImm())2231 return Error(IDLoc, "expected immediate operand kind");2232 Imm = Opnd.getImm();2233 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))2234 return Error(IDLoc, "immediate operand value out of range");2235 break;2236 case Mips::LW16_MM:2237 case Mips::SW16_MM:2238 case Mips::SW16_MMR6:2239 Opnd = Inst.getOperand(2);2240 if (!Opnd.isImm())2241 return Error(IDLoc, "expected immediate operand kind");2242 Imm = Opnd.getImm();2243 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))2244 return Error(IDLoc, "immediate operand value out of range");2245 break;2246 case Mips::ADDIUPC_MM:2247 Opnd = Inst.getOperand(1);2248 if (!Opnd.isImm())2249 return Error(IDLoc, "expected immediate operand kind");2250 Imm = Opnd.getImm();2251 if ((Imm % 4 != 0) || !isInt<25>(Imm))2252 return Error(IDLoc, "immediate operand value out of range");2253 break;2254 case Mips::LWP_MM:2255 case Mips::SWP_MM:2256 if (Inst.getOperand(0).getReg() == Mips::RA)2257 return Error(IDLoc, "invalid operand for instruction");2258 break;2259 case Mips::MOVEP_MM:2260 case Mips::MOVEP_MMR6: {2261 MCRegister R0 = Inst.getOperand(0).getReg();2262 MCRegister R1 = Inst.getOperand(1).getReg();2263 bool RegPair = ((R0 == Mips::A1 && R1 == Mips::A2) ||2264 (R0 == Mips::A1 && R1 == Mips::A3) ||2265 (R0 == Mips::A2 && R1 == Mips::A3) ||2266 (R0 == Mips::A0 && R1 == Mips::S5) ||2267 (R0 == Mips::A0 && R1 == Mips::S6) ||2268 (R0 == Mips::A0 && R1 == Mips::A1) ||2269 (R0 == Mips::A0 && R1 == Mips::A2) ||2270 (R0 == Mips::A0 && R1 == Mips::A3));2271 if (!RegPair)2272 return Error(IDLoc, "invalid operand for instruction");2273 break;2274 }2275 }2276 }2277 2278 bool FillDelaySlot =2279 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();2280 2281 // Get previous instruction`s forbidden slot attribute and2282 // whether set reorder.2283 bool PrevForbiddenSlotAttr = CurForbiddenSlotAttr;2284 2285 // Flag represents we set reorder after nop.2286 bool SetReorderAfterNop = false;2287 2288 // If previous instruction has forbidden slot and .set reorder2289 // is active and current instruction is CTI.2290 // Then emit a NOP after it.2291 if (PrevForbiddenSlotAttr && !SafeInForbiddenSlot(MCID)) {2292 TOut.emitEmptyDelaySlot(false, IDLoc, STI);2293 // When 'FillDelaySlot' is true, the existing logic will add2294 // noreorder before instruction and reorder after it. So there2295 // need exclude this case avoiding two '.set reorder'.2296 // The format of the first case is:2297 // .set noreorder2298 // bnezc2299 // nop2300 // .set reorder2301 if (AssemblerOptions.back()->isReorder() && !FillDelaySlot) {2302 SetReorderAfterNop = true;2303 TOut.emitDirectiveSetReorder();2304 }2305 }2306 2307 // Save current instruction`s forbidden slot and whether set reorder.2308 // This is the judgment condition for whether to add nop.2309 // We would add a couple of '.set noreorder' and '.set reorder' to2310 // wrap the current instruction and the next instruction.2311 CurForbiddenSlotAttr =2312 hasForbiddenSlot(MCID) && AssemblerOptions.back()->isReorder();2313 2314 if (FillDelaySlot || CurForbiddenSlotAttr)2315 TOut.emitDirectiveSetNoReorder();2316 2317 MacroExpanderResultTy ExpandResult =2318 tryExpandInstruction(Inst, IDLoc, Out, STI);2319 switch (ExpandResult) {2320 case MER_NotAMacro:2321 Out.emitInstruction(Inst, *STI);2322 break;2323 case MER_Success:2324 break;2325 case MER_Fail:2326 return true;2327 }2328 2329 // When current instruction was not CTI, recover reorder state.2330 // The format of the second case is:2331 // .set noreoder2332 // bnezc2333 // add2334 // .set reorder2335 if (PrevForbiddenSlotAttr && !SetReorderAfterNop && !FillDelaySlot &&2336 AssemblerOptions.back()->isReorder()) {2337 TOut.emitDirectiveSetReorder();2338 }2339 2340 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.2341 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.2342 if (inMicroMipsMode()) {2343 TOut.setUsesMicroMips();2344 TOut.updateABIInfo(*this);2345 }2346 2347 // If this instruction has a delay slot and .set reorder is active,2348 // emit a NOP after it.2349 // The format of the third case is:2350 // .set noreorder2351 // bnezc2352 // nop2353 // .set noreorder2354 // j2355 // nop2356 // .set reorder2357 if (FillDelaySlot) {2358 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst), IDLoc, STI);2359 TOut.emitDirectiveSetReorder();2360 }2361 2362 if ((Opcode == Mips::JalOneReg || Opcode == Mips::JalTwoReg ||2363 ExpandedJalSym) &&2364 isPicAndNotNxxAbi()) {2365 if (IsCpRestoreSet) {2366 // We need a NOP between the JALR and the LW:2367 // If .set reorder has been used, we've already emitted a NOP.2368 // If .set noreorder has been used, we need to emit a NOP at this point.2369 if (!AssemblerOptions.back()->isReorder())2370 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst), IDLoc,2371 STI);2372 2373 // Load the $gp from the stack.2374 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);2375 } else2376 Warning(IDLoc, "no .cprestore used in PIC mode");2377 }2378 2379 return false;2380}2381 2382void MipsAsmParser::onEndOfFile() {2383 MipsTargetStreamer &TOut = getTargetStreamer();2384 SMLoc IDLoc = SMLoc();2385 // If has pending forbidden slot, fill nop and recover reorder.2386 if (CurForbiddenSlotAttr) {2387 TOut.emitEmptyDelaySlot(false, IDLoc, STI);2388 if (AssemblerOptions.back()->isReorder())2389 TOut.emitDirectiveSetReorder();2390 }2391}2392 2393MipsAsmParser::MacroExpanderResultTy2394MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,2395 const MCSubtargetInfo *STI) {2396 switch (Inst.getOpcode()) {2397 default:2398 return MER_NotAMacro;2399 case Mips::LoadImm32:2400 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;2401 case Mips::LoadImm64:2402 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;2403 case Mips::LoadAddrImm32:2404 case Mips::LoadAddrImm64:2405 assert(Inst.getOperand(0).isReg() && "expected register operand kind");2406 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&2407 "expected immediate operand kind");2408 2409 return expandLoadAddress(2410 Inst.getOperand(0).getReg(), MCRegister(), Inst.getOperand(1),2411 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc, Out, STI)2412 ? MER_Fail2413 : MER_Success;2414 case Mips::LoadAddrReg32:2415 case Mips::LoadAddrReg64:2416 assert(Inst.getOperand(0).isReg() && "expected register operand kind");2417 assert(Inst.getOperand(1).isReg() && "expected register operand kind");2418 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&2419 "expected immediate operand kind");2420 2421 return expandLoadAddress(Inst.getOperand(0).getReg(),2422 Inst.getOperand(1).getReg(), Inst.getOperand(2),2423 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,2424 Out, STI)2425 ? MER_Fail2426 : MER_Success;2427 case Mips::B_MM_Pseudo:2428 case Mips::B_MMR6_Pseudo:2429 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail2430 : MER_Success;2431 case Mips::SWM_MM:2432 case Mips::LWM_MM:2433 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail2434 : MER_Success;2435 case Mips::JalOneReg:2436 case Mips::JalTwoReg:2437 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2438 case Mips::BneImm:2439 case Mips::BeqImm:2440 case Mips::BEQLImmMacro:2441 case Mips::BNELImmMacro:2442 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2443 case Mips::BLT:2444 case Mips::BLE:2445 case Mips::BGE:2446 case Mips::BGT:2447 case Mips::BLTU:2448 case Mips::BLEU:2449 case Mips::BGEU:2450 case Mips::BGTU:2451 case Mips::BLTL:2452 case Mips::BLEL:2453 case Mips::BGEL:2454 case Mips::BGTL:2455 case Mips::BLTUL:2456 case Mips::BLEUL:2457 case Mips::BGEUL:2458 case Mips::BGTUL:2459 case Mips::BLTImmMacro:2460 case Mips::BLEImmMacro:2461 case Mips::BGEImmMacro:2462 case Mips::BGTImmMacro:2463 case Mips::BLTUImmMacro:2464 case Mips::BLEUImmMacro:2465 case Mips::BGEUImmMacro:2466 case Mips::BGTUImmMacro:2467 case Mips::BLTLImmMacro:2468 case Mips::BLELImmMacro:2469 case Mips::BGELImmMacro:2470 case Mips::BGTLImmMacro:2471 case Mips::BLTULImmMacro:2472 case Mips::BLEULImmMacro:2473 case Mips::BGEULImmMacro:2474 case Mips::BGTULImmMacro:2475 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2476 case Mips::SDivMacro:2477 case Mips::SDivIMacro:2478 case Mips::SRemMacro:2479 case Mips::SRemIMacro:2480 return expandDivRem(Inst, IDLoc, Out, STI, false, true) ? MER_Fail2481 : MER_Success;2482 case Mips::DSDivMacro:2483 case Mips::DSDivIMacro:2484 case Mips::DSRemMacro:2485 case Mips::DSRemIMacro:2486 return expandDivRem(Inst, IDLoc, Out, STI, true, true) ? MER_Fail2487 : MER_Success;2488 case Mips::UDivMacro:2489 case Mips::UDivIMacro:2490 case Mips::URemMacro:2491 case Mips::URemIMacro:2492 return expandDivRem(Inst, IDLoc, Out, STI, false, false) ? MER_Fail2493 : MER_Success;2494 case Mips::DUDivMacro:2495 case Mips::DUDivIMacro:2496 case Mips::DURemMacro:2497 case Mips::DURemIMacro:2498 return expandDivRem(Inst, IDLoc, Out, STI, true, false) ? MER_Fail2499 : MER_Success;2500 case Mips::PseudoTRUNC_W_S:2501 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail2502 : MER_Success;2503 case Mips::PseudoTRUNC_W_D32:2504 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail2505 : MER_Success;2506 case Mips::PseudoTRUNC_W_D:2507 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail2508 : MER_Success;2509 2510 case Mips::LoadImmSingleGPR:2511 return expandLoadSingleImmToGPR(Inst, IDLoc, Out, STI) ? MER_Fail2512 : MER_Success;2513 case Mips::LoadImmSingleFGR:2514 return expandLoadSingleImmToFPR(Inst, IDLoc, Out, STI) ? MER_Fail2515 : MER_Success;2516 case Mips::LoadImmDoubleGPR:2517 return expandLoadDoubleImmToGPR(Inst, IDLoc, Out, STI) ? MER_Fail2518 : MER_Success;2519 case Mips::LoadImmDoubleFGR:2520 return expandLoadDoubleImmToFPR(Inst, true, IDLoc, Out, STI) ? MER_Fail2521 : MER_Success;2522 case Mips::LoadImmDoubleFGR_32:2523 return expandLoadDoubleImmToFPR(Inst, false, IDLoc, Out, STI) ? MER_Fail2524 : MER_Success;2525 2526 case Mips::Ulh:2527 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;2528 case Mips::Ulhu:2529 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;2530 case Mips::Ush:2531 return expandUsh(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2532 case Mips::Ulw:2533 case Mips::Usw:2534 return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2535 case Mips::NORImm:2536 case Mips::NORImm64:2537 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2538 case Mips::SGE:2539 case Mips::SGEU:2540 return expandSge(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2541 case Mips::SGEImm:2542 case Mips::SGEUImm:2543 case Mips::SGEImm64:2544 case Mips::SGEUImm64:2545 return expandSgeImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2546 case Mips::SGTImm:2547 case Mips::SGTUImm:2548 case Mips::SGTImm64:2549 case Mips::SGTUImm64:2550 return expandSgtImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2551 case Mips::SLE:2552 case Mips::SLEU:2553 return expandSle(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2554 case Mips::SLEImm:2555 case Mips::SLEUImm:2556 case Mips::SLEImm64:2557 case Mips::SLEUImm64:2558 return expandSleImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2559 case Mips::SLTImm64:2560 if (isInt<16>(Inst.getOperand(2).getImm())) {2561 Inst.setOpcode(Mips::SLTi64);2562 return MER_NotAMacro;2563 }2564 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2565 case Mips::SLTUImm64:2566 if (isInt<16>(Inst.getOperand(2).getImm())) {2567 Inst.setOpcode(Mips::SLTiu64);2568 return MER_NotAMacro;2569 }2570 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2571 case Mips::ADDi: case Mips::ADDi_MM:2572 case Mips::ADDiu: case Mips::ADDiu_MM:2573 case Mips::SLTi: case Mips::SLTi_MM:2574 case Mips::SLTiu: case Mips::SLTiu_MM:2575 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&2576 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {2577 int64_t ImmValue = Inst.getOperand(2).getImm();2578 if (isInt<16>(ImmValue))2579 return MER_NotAMacro;2580 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail2581 : MER_Success;2582 }2583 return MER_NotAMacro;2584 case Mips::ANDi: case Mips::ANDi_MM: case Mips::ANDi64:2585 case Mips::ORi: case Mips::ORi_MM: case Mips::ORi64:2586 case Mips::XORi: case Mips::XORi_MM: case Mips::XORi64:2587 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&2588 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {2589 int64_t ImmValue = Inst.getOperand(2).getImm();2590 if (isUInt<16>(ImmValue))2591 return MER_NotAMacro;2592 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail2593 : MER_Success;2594 }2595 return MER_NotAMacro;2596 case Mips::ROL:2597 case Mips::ROR:2598 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2599 case Mips::ROLImm:2600 case Mips::RORImm:2601 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2602 case Mips::DROL:2603 case Mips::DROR:2604 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2605 case Mips::DROLImm:2606 case Mips::DRORImm:2607 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2608 case Mips::ABSMacro:2609 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2610 case Mips::MULImmMacro:2611 case Mips::DMULImmMacro:2612 return expandMulImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2613 case Mips::MULOMacro:2614 case Mips::DMULOMacro:2615 return expandMulO(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2616 case Mips::MULOUMacro:2617 case Mips::DMULOUMacro:2618 return expandMulOU(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2619 case Mips::DMULMacro:2620 return expandDMULMacro(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2621 case Mips::LDMacro:2622 case Mips::SDMacro:2623 return expandLoadStoreDMacro(Inst, IDLoc, Out, STI,2624 Inst.getOpcode() == Mips::LDMacro)2625 ? MER_Fail2626 : MER_Success;2627 case Mips::SDC1_M1:2628 return expandStoreDM1Macro(Inst, IDLoc, Out, STI)2629 ? MER_Fail2630 : MER_Success;2631 case Mips::SEQMacro:2632 return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2633 case Mips::SEQIMacro:2634 return expandSeqI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2635 case Mips::SNEMacro:2636 return expandSne(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2637 case Mips::SNEIMacro:2638 return expandSneI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2639 case Mips::MFTC0: case Mips::MTTC0:2640 case Mips::MFTGPR: case Mips::MTTGPR:2641 case Mips::MFTLO: case Mips::MTTLO:2642 case Mips::MFTHI: case Mips::MTTHI:2643 case Mips::MFTACX: case Mips::MTTACX:2644 case Mips::MFTDSP: case Mips::MTTDSP:2645 case Mips::MFTC1: case Mips::MTTC1:2646 case Mips::MFTHC1: case Mips::MTTHC1:2647 case Mips::CFTC1: case Mips::CTTC1:2648 return expandMXTRAlias(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2649 case Mips::SaaAddr:2650 case Mips::SaadAddr:2651 return expandSaaAddr(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;2652 }2653}2654 2655bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,2656 MCStreamer &Out,2657 const MCSubtargetInfo *STI) {2658 MipsTargetStreamer &TOut = getTargetStreamer();2659 2660 // Create a JALR instruction which is going to replace the pseudo-JAL.2661 MCInst JalrInst;2662 JalrInst.setLoc(IDLoc);2663 const MCOperand FirstRegOp = Inst.getOperand(0);2664 const unsigned Opcode = Inst.getOpcode();2665 2666 if (Opcode == Mips::JalOneReg) {2667 // jal $rs => jalr $rs2668 if (IsCpRestoreSet && inMicroMipsMode()) {2669 JalrInst.setOpcode(Mips::JALRS16_MM);2670 JalrInst.addOperand(FirstRegOp);2671 } else if (inMicroMipsMode()) {2672 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);2673 JalrInst.addOperand(FirstRegOp);2674 } else {2675 JalrInst.setOpcode(Mips::JALR);2676 JalrInst.addOperand(MCOperand::createReg(Mips::RA));2677 JalrInst.addOperand(FirstRegOp);2678 }2679 } else if (Opcode == Mips::JalTwoReg) {2680 // jal $rd, $rs => jalr $rd, $rs2681 if (IsCpRestoreSet && inMicroMipsMode())2682 JalrInst.setOpcode(Mips::JALRS_MM);2683 else2684 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);2685 JalrInst.addOperand(FirstRegOp);2686 const MCOperand SecondRegOp = Inst.getOperand(1);2687 JalrInst.addOperand(SecondRegOp);2688 }2689 Out.emitInstruction(JalrInst, *STI);2690 2691 // If .set reorder is active and branch instruction has a delay slot,2692 // emit a NOP after it.2693 const MCInstrDesc &MCID = MII.get(JalrInst.getOpcode());2694 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())2695 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst), IDLoc,2696 STI);2697 2698 return false;2699}2700 2701/// Can the value be represented by a unsigned N-bit value and a shift left?2702template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {2703 return x && isUInt<N>(x >> llvm::countr_zero(x));2704}2705 2706/// Load (or add) an immediate into a register.2707///2708/// @param ImmValue The immediate to load.2709/// @param DstReg The register that will hold the immediate.2710/// @param SrcReg A register to add to the immediate or MCRegister()2711/// for a simple initialization.2712/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?2713/// @param IsAddress True if the immediate represents an address. False if it2714/// is an integer.2715/// @param IDLoc Location of the immediate in the source file.2716bool MipsAsmParser::loadImmediate(int64_t ImmValue, MCRegister DstReg,2717 MCRegister SrcReg, bool Is32BitImm,2718 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,2719 const MCSubtargetInfo *STI) {2720 MipsTargetStreamer &TOut = getTargetStreamer();2721 2722 if (!Is32BitImm && !isGP64bit()) {2723 Error(IDLoc, "instruction requires a 64-bit architecture");2724 return true;2725 }2726 2727 if (Is32BitImm) {2728 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {2729 // Sign extend up to 64-bit so that the predicates match the hardware2730 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be2731 // true.2732 ImmValue = SignExtend64<32>(ImmValue);2733 } else {2734 Error(IDLoc, "instruction requires a 32-bit immediate");2735 return true;2736 }2737 }2738 2739 MCRegister ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();2740 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;2741 2742 bool UseSrcReg = false;2743 if (SrcReg)2744 UseSrcReg = true;2745 2746 MCRegister TmpReg = DstReg;2747 if (UseSrcReg &&2748 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {2749 // At this point we need AT to perform the expansions and we exit if it is2750 // not available.2751 MCRegister ATReg = getATReg(IDLoc);2752 if (!ATReg)2753 return true;2754 TmpReg = ATReg;2755 }2756 2757 if (isInt<16>(ImmValue)) {2758 if (!UseSrcReg)2759 SrcReg = ZeroReg;2760 2761 // This doesn't quite follow the usual ABI expectations for N32 but matches2762 // traditional assembler behaviour. N32 would normally use addiu for both2763 // integers and addresses.2764 if (IsAddress && !Is32BitImm) {2765 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);2766 return false;2767 }2768 2769 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);2770 return false;2771 }2772 2773 if (isUInt<16>(ImmValue)) {2774 MCRegister TmpReg = DstReg;2775 if (SrcReg == DstReg) {2776 TmpReg = getATReg(IDLoc);2777 if (!TmpReg)2778 return true;2779 }2780 2781 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);2782 if (UseSrcReg)2783 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);2784 return false;2785 }2786 2787 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {2788 warnIfNoMacro(IDLoc);2789 2790 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;2791 uint16_t Bits15To0 = ImmValue & 0xffff;2792 if (!Is32BitImm && !isInt<32>(ImmValue)) {2793 // Traditional behaviour seems to special case this particular value. It's2794 // not clear why other masks are handled differently.2795 if (ImmValue == 0xffffffff) {2796 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);2797 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);2798 if (UseSrcReg)2799 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);2800 return false;2801 }2802 2803 // Expand to an ORi instead of a LUi to avoid sign-extending into the2804 // upper 32 bits.2805 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);2806 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);2807 if (Bits15To0)2808 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);2809 if (UseSrcReg)2810 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);2811 return false;2812 }2813 2814 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);2815 if (Bits15To0)2816 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);2817 if (UseSrcReg)2818 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);2819 return false;2820 }2821 2822 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {2823 if (Is32BitImm) {2824 Error(IDLoc, "instruction requires a 32-bit immediate");2825 return true;2826 }2827 2828 // We've processed ImmValue satisfying isUInt<16> above, so ImmValue must be2829 // at least 17-bit wide here.2830 unsigned BitWidth = llvm::bit_width((uint64_t)ImmValue);2831 assert(BitWidth >= 17 && "ImmValue must be at least 17-bit wide");2832 2833 // Traditionally, these immediates are shifted as little as possible and as2834 // such we align the most significant bit to bit 15 of our temporary.2835 unsigned ShiftAmount = BitWidth - 16;2836 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;2837 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);2838 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);2839 2840 if (UseSrcReg)2841 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);2842 2843 return false;2844 }2845 2846 warnIfNoMacro(IDLoc);2847 2848 // The remaining case is packed with a sequence of dsll and ori with zeros2849 // being omitted and any neighbouring dsll's being coalesced.2850 // The highest 32-bit's are equivalent to a 32-bit immediate load.2851 2852 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.2853 if (loadImmediate(ImmValue >> 32, TmpReg, MCRegister(), true, false, IDLoc,2854 Out, STI))2855 return false;2856 2857 // Shift and accumulate into the register. If a 16-bit chunk is zero, then2858 // skip it and defer the shift to the next chunk.2859 unsigned ShiftCarriedForwards = 16;2860 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {2861 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;2862 2863 if (ImmChunk != 0) {2864 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);2865 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);2866 ShiftCarriedForwards = 0;2867 }2868 2869 ShiftCarriedForwards += 16;2870 }2871 ShiftCarriedForwards -= 16;2872 2873 // Finish any remaining shifts left by trailing zeros.2874 if (ShiftCarriedForwards)2875 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);2876 2877 if (UseSrcReg)2878 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);2879 2880 return false;2881}2882 2883bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,2884 MCStreamer &Out, const MCSubtargetInfo *STI) {2885 const MCOperand &ImmOp = Inst.getOperand(1);2886 assert(ImmOp.isImm() && "expected immediate operand kind");2887 const MCOperand &DstRegOp = Inst.getOperand(0);2888 assert(DstRegOp.isReg() && "expected register operand kind");2889 2890 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), MCRegister(), Is32BitImm,2891 false, IDLoc, Out, STI))2892 return true;2893 2894 return false;2895}2896 2897bool MipsAsmParser::expandLoadAddress(MCRegister DstReg, MCRegister BaseReg,2898 const MCOperand &Offset,2899 bool Is32BitAddress, SMLoc IDLoc,2900 MCStreamer &Out,2901 const MCSubtargetInfo *STI) {2902 // la can't produce a usable address when addresses are 64-bit.2903 if (Is32BitAddress && ABI.ArePtrs64bit()) {2904 Warning(IDLoc, "la used to load 64-bit address");2905 // Continue as if we had 'dla' instead.2906 Is32BitAddress = false;2907 }2908 2909 // dla requires 64-bit addresses.2910 if (!Is32BitAddress && !hasMips3()) {2911 Error(IDLoc, "instruction requires a 64-bit architecture");2912 return true;2913 }2914 2915 if (!Offset.isImm())2916 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,2917 Is32BitAddress, IDLoc, Out, STI);2918 2919 if (!ABI.ArePtrs64bit()) {2920 // Continue as if we had 'la' whether we had 'la' or 'dla'.2921 Is32BitAddress = true;2922 }2923 2924 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,2925 IDLoc, Out, STI);2926}2927 2928bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,2929 MCRegister DstReg,2930 MCRegister SrcReg, bool Is32BitSym,2931 SMLoc IDLoc, MCStreamer &Out,2932 const MCSubtargetInfo *STI) {2933 MipsTargetStreamer &TOut = getTargetStreamer();2934 bool UseSrcReg =2935 SrcReg.isValid() && SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64;2936 warnIfNoMacro(IDLoc);2937 2938 if (inPicMode()) {2939 MCValue Res;2940 if (!SymExpr->evaluateAsRelocatable(Res, nullptr)) {2941 Error(IDLoc, "expected relocatable expression");2942 return true;2943 }2944 if (Res.getSubSym()) {2945 Error(IDLoc, "expected relocatable expression with only one symbol");2946 return true;2947 }2948 2949 bool IsPtr64 = ABI.ArePtrs64bit();2950 bool IsLocalSym =2951 Res.getAddSym()->isInSection() || Res.getAddSym()->isTemporary() ||2952 (getContext().isELF() &&2953 static_cast<const MCSymbolELF *>(Res.getAddSym())->getBinding() ==2954 ELF::STB_LOCAL);2955 // For O32, "$"-prefixed symbols are recognized as temporary while2956 // .L-prefixed symbols are not (PrivateGlobalPrefix is "$"). Recognize ".L"2957 // manually.2958 if (ABI.IsO32() && Res.getAddSym()->getName().starts_with(".L"))2959 IsLocalSym = true;2960 bool UseXGOT = STI->hasFeature(Mips::FeatureXGOT) && !IsLocalSym;2961 2962 // The case where the result register is $25 is somewhat special. If the2963 // symbol in the final relocation is external and not modified with a2964 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT162965 // or R_MIPS_CALL16 instead of R_MIPS_GOT_DISP in 64-bit case.2966 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&2967 Res.getConstant() == 0 && !IsLocalSym) {2968 if (UseXGOT) {2969 const MCExpr *CallHiExpr =2970 MCSpecifierExpr::create(SymExpr, Mips::S_CALL_HI16, getContext());2971 const MCExpr *CallLoExpr =2972 MCSpecifierExpr::create(SymExpr, Mips::S_CALL_LO16, getContext());2973 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(CallHiExpr), IDLoc,2974 STI);2975 TOut.emitRRR(IsPtr64 ? Mips::DADDu : Mips::ADDu, DstReg, DstReg, GPReg,2976 IDLoc, STI);2977 TOut.emitRRX(IsPtr64 ? Mips::LD : Mips::LW, DstReg, DstReg,2978 MCOperand::createExpr(CallLoExpr), IDLoc, STI);2979 } else {2980 const MCExpr *CallExpr =2981 MCSpecifierExpr::create(SymExpr, Mips::S_GOT_CALL, getContext());2982 TOut.emitRRX(IsPtr64 ? Mips::LD : Mips::LW, DstReg, GPReg,2983 MCOperand::createExpr(CallExpr), IDLoc, STI);2984 }2985 return false;2986 }2987 2988 MCRegister TmpReg = DstReg;2989 if (UseSrcReg &&2990 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,2991 SrcReg)) {2992 // If $rs is the same as $rd, we need to use AT.2993 // If it is not available we exit.2994 MCRegister ATReg = getATReg(IDLoc);2995 if (!ATReg)2996 return true;2997 TmpReg = ATReg;2998 }2999 3000 // FIXME: In case of N32 / N64 ABI and emabled XGOT, local addresses3001 // loaded using R_MIPS_GOT_PAGE / R_MIPS_GOT_OFST pair of relocations.3002 // FIXME: Implement XGOT for microMIPS.3003 if (UseXGOT) {3004 // Loading address from XGOT3005 // External GOT: lui $tmp, %got_hi(symbol)($gp)3006 // addu $tmp, $tmp, $gp3007 // lw $tmp, %got_lo(symbol)($tmp)3008 // >addiu $tmp, $tmp, offset3009 // >addiu $rd, $tmp, $rs3010 // The addiu's marked with a '>' may be omitted if they are redundant. If3011 // this happens then the last instruction must use $rd as the result3012 // register.3013 const MCExpr *CallHiExpr =3014 MCSpecifierExpr::create(SymExpr, Mips::S_GOT_HI16, getContext());3015 const MCExpr *CallLoExpr = MCSpecifierExpr::create(3016 Res.getAddSym(), Mips::S_GOT_LO16, getContext());3017 3018 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(CallHiExpr), IDLoc,3019 STI);3020 TOut.emitRRR(IsPtr64 ? Mips::DADDu : Mips::ADDu, TmpReg, TmpReg, GPReg,3021 IDLoc, STI);3022 TOut.emitRRX(IsPtr64 ? Mips::LD : Mips::LW, TmpReg, TmpReg,3023 MCOperand::createExpr(CallLoExpr), IDLoc, STI);3024 3025 if (Res.getConstant() != 0)3026 TOut.emitRRX(IsPtr64 ? Mips::DADDiu : Mips::ADDiu, TmpReg, TmpReg,3027 MCOperand::createExpr(MCConstantExpr::create(3028 Res.getConstant(), getContext())),3029 IDLoc, STI);3030 3031 if (UseSrcReg)3032 TOut.emitRRR(IsPtr64 ? Mips::DADDu : Mips::ADDu, DstReg, TmpReg, SrcReg,3033 IDLoc, STI);3034 return false;3035 }3036 3037 const MCSpecifierExpr *GotExpr = nullptr;3038 const MCExpr *LoExpr = nullptr;3039 if (ABI.IsN32() || ABI.IsN64()) {3040 // The remaining cases are:3041 // Small offset: ld $tmp, %got_disp(symbol)($gp)3042 // >daddiu $tmp, $tmp, offset3043 // >daddu $rd, $tmp, $rs3044 // The daddiu's marked with a '>' may be omitted if they are redundant. If3045 // this happens then the last instruction must use $rd as the result3046 // register.3047 GotExpr = MCSpecifierExpr::create(Res.getAddSym(), Mips::S_GOT_DISP,3048 getContext());3049 if (Res.getConstant() != 0) {3050 // Symbols fully resolve with just the %got_disp(symbol) but we3051 // must still account for any offset to the symbol for3052 // expressions like symbol+8.3053 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());3054 3055 // FIXME: Offsets greater than 16 bits are not yet implemented.3056 // FIXME: The correct range is a 32-bit sign-extended number.3057 if (Res.getConstant() < -0x8000 || Res.getConstant() > 0x7fff) {3058 Error(IDLoc, "macro instruction uses large offset, which is not "3059 "currently supported");3060 return true;3061 }3062 }3063 } else {3064 // The remaining cases are:3065 // External GOT: lw $tmp, %got(symbol)($gp)3066 // >addiu $tmp, $tmp, offset3067 // >addiu $rd, $tmp, $rs3068 // Local GOT: lw $tmp, %got(symbol+offset)($gp)3069 // addiu $tmp, $tmp, %lo(symbol+offset)($gp)3070 // >addiu $rd, $tmp, $rs3071 // The addiu's marked with a '>' may be omitted if they are redundant. If3072 // this happens then the last instruction must use $rd as the result3073 // register.3074 if (IsLocalSym) {3075 GotExpr = MCSpecifierExpr::create(SymExpr, Mips::S_GOT, getContext());3076 LoExpr = MCSpecifierExpr::create(SymExpr, Mips::S_LO, getContext());3077 } else {3078 // External symbols fully resolve the symbol with just the %got(symbol)3079 // but we must still account for any offset to the symbol for3080 // expressions like symbol+8.3081 GotExpr =3082 MCSpecifierExpr::create(Res.getAddSym(), Mips::S_GOT, getContext());3083 if (Res.getConstant() != 0)3084 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());3085 }3086 }3087 3088 TOut.emitRRX(IsPtr64 ? Mips::LD : Mips::LW, TmpReg, GPReg,3089 MCOperand::createExpr(GotExpr), IDLoc, STI);3090 3091 if (LoExpr)3092 TOut.emitRRX(IsPtr64 ? Mips::DADDiu : Mips::ADDiu, TmpReg, TmpReg,3093 MCOperand::createExpr(LoExpr), IDLoc, STI);3094 3095 if (UseSrcReg)3096 TOut.emitRRR(IsPtr64 ? Mips::DADDu : Mips::ADDu, DstReg, TmpReg, SrcReg,3097 IDLoc, STI);3098 3099 return false;3100 }3101 3102 const auto *HiExpr =3103 MCSpecifierExpr::create(SymExpr, Mips::S_HI, getContext());3104 const auto *LoExpr =3105 MCSpecifierExpr::create(SymExpr, Mips::S_LO, getContext());3106 3107 // This is the 64-bit symbol address expansion.3108 if (ABI.ArePtrs64bit() && isGP64bit()) {3109 // We need AT for the 64-bit expansion in the cases where the optional3110 // source register is the destination register and for the superscalar3111 // scheduled form.3112 //3113 // If it is not available we exit if the destination is the same as the3114 // source register.3115 3116 const auto *HighestExpr =3117 MCSpecifierExpr::create(SymExpr, Mips::S_HIGHEST, getContext());3118 const auto *HigherExpr =3119 MCSpecifierExpr::create(SymExpr, Mips::S_HIGHER, getContext());3120 3121 bool RdRegIsRsReg =3122 UseSrcReg &&3123 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg);3124 3125 if (canUseATReg() && UseSrcReg && RdRegIsRsReg) {3126 MCRegister ATReg = getATReg(IDLoc);3127 3128 // If $rs is the same as $rd:3129 // (d)la $rd, sym($rd) => lui $at, %highest(sym)3130 // daddiu $at, $at, %higher(sym)3131 // dsll $at, $at, 163132 // daddiu $at, $at, %hi(sym)3133 // dsll $at, $at, 163134 // daddiu $at, $at, %lo(sym)3135 // daddu $rd, $at, $rd3136 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,3137 STI);3138 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,3139 MCOperand::createExpr(HigherExpr), IDLoc, STI);3140 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);3141 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),3142 IDLoc, STI);3143 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);3144 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),3145 IDLoc, STI);3146 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);3147 3148 return false;3149 } else if (canUseATReg() && !RdRegIsRsReg && DstReg != getATReg(IDLoc)) {3150 MCRegister ATReg = getATReg(IDLoc);3151 3152 // If the $rs is different from $rd or if $rs isn't specified and we3153 // have $at available:3154 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)3155 // lui $at, %hi(sym)3156 // daddiu $rd, $rd, %higher(sym)3157 // daddiu $at, $at, %lo(sym)3158 // dsll32 $rd, $rd, 03159 // daddu $rd, $rd, $at3160 // (daddu $rd, $rd, $rs)3161 //3162 // Which is preferred for superscalar issue.3163 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,3164 STI);3165 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);3166 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,3167 MCOperand::createExpr(HigherExpr), IDLoc, STI);3168 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),3169 IDLoc, STI);3170 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);3171 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);3172 if (UseSrcReg)3173 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);3174 3175 return false;3176 } else if ((!canUseATReg() && !RdRegIsRsReg) ||3177 (canUseATReg() && DstReg == getATReg(IDLoc))) {3178 // Otherwise, synthesize the address in the destination register3179 // serially:3180 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)3181 // daddiu $rd, $rd, %higher(sym)3182 // dsll $rd, $rd, 163183 // daddiu $rd, $rd, %hi(sym)3184 // dsll $rd, $rd, 163185 // daddiu $rd, $rd, %lo(sym)3186 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,3187 STI);3188 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,3189 MCOperand::createExpr(HigherExpr), IDLoc, STI);3190 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);3191 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,3192 MCOperand::createExpr(HiExpr), IDLoc, STI);3193 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);3194 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,3195 MCOperand::createExpr(LoExpr), IDLoc, STI);3196 if (UseSrcReg)3197 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);3198 3199 return false;3200 } else {3201 // We have a case where SrcReg == DstReg and we don't have $at3202 // available. We can't expand this case, so error out appropriately.3203 assert(SrcReg == DstReg && !canUseATReg() &&3204 "Could have expanded dla but didn't?");3205 reportParseError(IDLoc,3206 "pseudo-instruction requires $at, which is not available");3207 return true;3208 }3209 }3210 3211 // And now, the 32-bit symbol address expansion:3212 // If $rs is the same as $rd:3213 // (d)la $rd, sym($rd) => lui $at, %hi(sym)3214 // ori $at, $at, %lo(sym)3215 // addu $rd, $at, $rd3216 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:3217 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)3218 // ori $rd, $rd, %lo(sym)3219 // (addu $rd, $rd, $rs)3220 MCRegister TmpReg = DstReg;3221 if (UseSrcReg &&3222 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {3223 // If $rs is the same as $rd, we need to use AT.3224 // If it is not available we exit.3225 MCRegister ATReg = getATReg(IDLoc);3226 if (!ATReg)3227 return true;3228 TmpReg = ATReg;3229 }3230 3231 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);3232 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),3233 IDLoc, STI);3234 3235 if (UseSrcReg)3236 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);3237 else3238 assert(3239 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));3240 3241 return false;3242}3243 3244// Each double-precision register DO-D15 overlaps with two of the single3245// precision registers F0-F31. As an example, all of the following hold true:3246// D0 + 1 == F1, F1 + 1 == D1, F1 + 1 == F2, depending on the context.3247static MCRegister nextReg(MCRegister Reg) {3248 if (MipsMCRegisterClasses[Mips::FGR32RegClassID].contains(Reg))3249 return Reg == (unsigned)Mips::F31 ? (unsigned)Mips::F0 : Reg + 1;3250 switch (Reg.id()) {3251 default: llvm_unreachable("Unknown register in assembly macro expansion!");3252 case Mips::ZERO: return Mips::AT;3253 case Mips::AT: return Mips::V0;3254 case Mips::V0: return Mips::V1;3255 case Mips::V1: return Mips::A0;3256 case Mips::A0: return Mips::A1;3257 case Mips::A1: return Mips::A2;3258 case Mips::A2: return Mips::A3;3259 case Mips::A3: return Mips::T0;3260 case Mips::T0: return Mips::T1;3261 case Mips::T1: return Mips::T2;3262 case Mips::T2: return Mips::T3;3263 case Mips::T3: return Mips::T4;3264 case Mips::T4: return Mips::T5;3265 case Mips::T5: return Mips::T6;3266 case Mips::T6: return Mips::T7;3267 case Mips::T7: return Mips::S0;3268 case Mips::S0: return Mips::S1;3269 case Mips::S1: return Mips::S2;3270 case Mips::S2: return Mips::S3;3271 case Mips::S3: return Mips::S4;3272 case Mips::S4: return Mips::S5;3273 case Mips::S5: return Mips::S6;3274 case Mips::S6: return Mips::S7;3275 case Mips::S7: return Mips::T8;3276 case Mips::T8: return Mips::T9;3277 case Mips::T9: return Mips::K0;3278 case Mips::K0: return Mips::K1;3279 case Mips::K1: return Mips::GP;3280 case Mips::GP: return Mips::SP;3281 case Mips::SP: return Mips::FP;3282 case Mips::FP: return Mips::RA;3283 case Mips::RA: return Mips::ZERO;3284 case Mips::D0: return Mips::F1;3285 case Mips::D1: return Mips::F3;3286 case Mips::D2: return Mips::F5;3287 case Mips::D3: return Mips::F7;3288 case Mips::D4: return Mips::F9;3289 case Mips::D5: return Mips::F11;3290 case Mips::D6: return Mips::F13;3291 case Mips::D7: return Mips::F15;3292 case Mips::D8: return Mips::F17;3293 case Mips::D9: return Mips::F19;3294 case Mips::D10: return Mips::F21;3295 case Mips::D11: return Mips::F23;3296 case Mips::D12: return Mips::F25;3297 case Mips::D13: return Mips::F27;3298 case Mips::D14: return Mips::F29;3299 case Mips::D15: return Mips::F31;3300 }3301}3302 3303// FIXME: This method is too general. In principle we should compute the number3304// of instructions required to synthesize the immediate inline compared to3305// synthesizing the address inline and relying on non .text sections.3306// For static O32 and N32 this may yield a small benefit, for static N64 this is3307// likely to yield a much larger benefit as we have to synthesize a 64bit3308// address to load a 64 bit value.3309bool MipsAsmParser::emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc,3310 MCSymbol *Sym) {3311 MCRegister ATReg = getATReg(IDLoc);3312 if (!ATReg)3313 return true;3314 3315 if(IsPicEnabled) {3316 const MCExpr *GotSym = MCSymbolRefExpr::create(Sym, getContext());3317 const auto *GotExpr =3318 MCSpecifierExpr::create(GotSym, Mips::S_GOT, getContext());3319 3320 if(isABI_O32() || isABI_N32()) {3321 TOut.emitRRX(Mips::LW, ATReg, GPReg, MCOperand::createExpr(GotExpr),3322 IDLoc, STI);3323 } else { //isABI_N64()3324 TOut.emitRRX(Mips::LD, ATReg, GPReg, MCOperand::createExpr(GotExpr),3325 IDLoc, STI);3326 }3327 } else { //!IsPicEnabled3328 const MCExpr *HiSym = MCSymbolRefExpr::create(Sym, getContext());3329 const auto *HiExpr =3330 MCSpecifierExpr::create(HiSym, Mips::S_HI, getContext());3331 3332 // FIXME: This is technically correct but gives a different result to gas,3333 // but gas is incomplete there (it has a fixme noting it doesn't work with3334 // 64-bit addresses).3335 // FIXME: With -msym32 option, the address expansion for N64 should probably3336 // use the O32 / N32 case. It's safe to use the 64 address expansion as the3337 // symbol's value is considered sign extended.3338 if(isABI_O32() || isABI_N32()) {3339 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);3340 } else { //isABI_N64()3341 const MCExpr *HighestSym = MCSymbolRefExpr::create(Sym, getContext());3342 const auto *HighestExpr =3343 MCSpecifierExpr::create(HighestSym, Mips::S_HIGHEST, getContext());3344 const MCExpr *HigherSym = MCSymbolRefExpr::create(Sym, getContext());3345 const auto *HigherExpr =3346 MCSpecifierExpr::create(HigherSym, Mips::S_HIGHER, getContext());3347 3348 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,3349 STI);3350 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,3351 MCOperand::createExpr(HigherExpr), IDLoc, STI);3352 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);3353 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),3354 IDLoc, STI);3355 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);3356 }3357 }3358 return false;3359}3360 3361static uint64_t convertIntToDoubleImm(uint64_t ImmOp64) {3362 // If ImmOp64 is AsmToken::Integer type (all bits set to zero in the3363 // exponent field), convert it to double (e.g. 1 to 1.0)3364 if ((Hi_32(ImmOp64) & 0x7ff00000) == 0) {3365 APFloat RealVal(APFloat::IEEEdouble(), ImmOp64);3366 ImmOp64 = RealVal.bitcastToAPInt().getZExtValue();3367 }3368 return ImmOp64;3369}3370 3371static uint32_t covertDoubleImmToSingleImm(uint64_t ImmOp64) {3372 // Conversion of a double in an uint64_t to a float in a uint32_t,3373 // retaining the bit pattern of a float.3374 double DoubleImm = llvm::bit_cast<double>(ImmOp64);3375 float TmpFloat = static_cast<float>(DoubleImm);3376 return llvm::bit_cast<uint32_t>(TmpFloat);3377}3378 3379bool MipsAsmParser::expandLoadSingleImmToGPR(MCInst &Inst, SMLoc IDLoc,3380 MCStreamer &Out,3381 const MCSubtargetInfo *STI) {3382 assert(Inst.getNumOperands() == 2 && "Invalid operand count");3383 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&3384 "Invalid instruction operand.");3385 3386 MCRegister FirstReg = Inst.getOperand(0).getReg();3387 uint64_t ImmOp64 = Inst.getOperand(1).getImm();3388 3389 uint32_t ImmOp32 = covertDoubleImmToSingleImm(convertIntToDoubleImm(ImmOp64));3390 3391 return loadImmediate(ImmOp32, FirstReg, MCRegister(), true, false, IDLoc, Out,3392 STI);3393}3394 3395bool MipsAsmParser::expandLoadSingleImmToFPR(MCInst &Inst, SMLoc IDLoc,3396 MCStreamer &Out,3397 const MCSubtargetInfo *STI) {3398 MipsTargetStreamer &TOut = getTargetStreamer();3399 assert(Inst.getNumOperands() == 2 && "Invalid operand count");3400 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&3401 "Invalid instruction operand.");3402 3403 MCRegister FirstReg = Inst.getOperand(0).getReg();3404 uint64_t ImmOp64 = Inst.getOperand(1).getImm();3405 3406 ImmOp64 = convertIntToDoubleImm(ImmOp64);3407 3408 uint32_t ImmOp32 = covertDoubleImmToSingleImm(ImmOp64);3409 3410 MCRegister TmpReg = Mips::ZERO;3411 if (ImmOp32 != 0) {3412 TmpReg = getATReg(IDLoc);3413 if (!TmpReg)3414 return true;3415 }3416 3417 if (Lo_32(ImmOp64) == 0) {3418 if (TmpReg != Mips::ZERO && loadImmediate(ImmOp32, TmpReg, MCRegister(),3419 true, false, IDLoc, Out, STI))3420 return true;3421 TOut.emitRR(Mips::MTC1, FirstReg, TmpReg, IDLoc, STI);3422 return false;3423 }3424 3425 MCSection *CS = getStreamer().getCurrentSectionOnly();3426 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections3427 // where appropriate.3428 MCSection *ReadOnlySection =3429 getContext().getELFSection(".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);3430 3431 MCSymbol *Sym = getContext().createTempSymbol();3432 const MCExpr *LoSym = MCSymbolRefExpr::create(Sym, getContext());3433 const auto *LoExpr = MCSpecifierExpr::create(LoSym, Mips::S_LO, getContext());3434 3435 getStreamer().switchSection(ReadOnlySection);3436 getStreamer().emitLabel(Sym, IDLoc);3437 getStreamer().emitInt32(ImmOp32);3438 getStreamer().switchSection(CS);3439 3440 if (emitPartialAddress(TOut, IDLoc, Sym))3441 return true;3442 TOut.emitRRX(Mips::LWC1, FirstReg, TmpReg, MCOperand::createExpr(LoExpr),3443 IDLoc, STI);3444 return false;3445}3446 3447bool MipsAsmParser::expandLoadDoubleImmToGPR(MCInst &Inst, SMLoc IDLoc,3448 MCStreamer &Out,3449 const MCSubtargetInfo *STI) {3450 MipsTargetStreamer &TOut = getTargetStreamer();3451 assert(Inst.getNumOperands() == 2 && "Invalid operand count");3452 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&3453 "Invalid instruction operand.");3454 3455 MCRegister FirstReg = Inst.getOperand(0).getReg();3456 uint64_t ImmOp64 = Inst.getOperand(1).getImm();3457 3458 ImmOp64 = convertIntToDoubleImm(ImmOp64);3459 3460 if (Lo_32(ImmOp64) == 0) {3461 if (isGP64bit()) {3462 if (loadImmediate(ImmOp64, FirstReg, MCRegister(), false, false, IDLoc,3463 Out, STI))3464 return true;3465 } else {3466 if (loadImmediate(Hi_32(ImmOp64), FirstReg, MCRegister(), true, false,3467 IDLoc, Out, STI))3468 return true;3469 3470 if (loadImmediate(0, nextReg(FirstReg), MCRegister(), true, false, IDLoc,3471 Out, STI))3472 return true;3473 }3474 return false;3475 }3476 3477 MCSection *CS = getStreamer().getCurrentSectionOnly();3478 MCSection *ReadOnlySection =3479 getContext().getELFSection(".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);3480 3481 MCSymbol *Sym = getContext().createTempSymbol();3482 const MCExpr *LoSym = MCSymbolRefExpr::create(Sym, getContext());3483 const auto *LoExpr = MCSpecifierExpr::create(LoSym, Mips::S_LO, getContext());3484 3485 getStreamer().switchSection(ReadOnlySection);3486 getStreamer().emitLabel(Sym, IDLoc);3487 getStreamer().emitValueToAlignment(Align(8));3488 getStreamer().emitIntValue(ImmOp64, 8);3489 getStreamer().switchSection(CS);3490 3491 MCRegister TmpReg = getATReg(IDLoc);3492 if (!TmpReg)3493 return true;3494 3495 if (emitPartialAddress(TOut, IDLoc, Sym))3496 return true;3497 3498 TOut.emitRRX(isABI_N64() ? Mips::DADDiu : Mips::ADDiu, TmpReg, TmpReg,3499 MCOperand::createExpr(LoExpr), IDLoc, STI);3500 3501 if (isGP64bit())3502 TOut.emitRRI(Mips::LD, FirstReg, TmpReg, 0, IDLoc, STI);3503 else {3504 TOut.emitRRI(Mips::LW, FirstReg, TmpReg, 0, IDLoc, STI);3505 TOut.emitRRI(Mips::LW, nextReg(FirstReg), TmpReg, 4, IDLoc, STI);3506 }3507 return false;3508}3509 3510bool MipsAsmParser::expandLoadDoubleImmToFPR(MCInst &Inst, bool Is64FPU,3511 SMLoc IDLoc, MCStreamer &Out,3512 const MCSubtargetInfo *STI) {3513 MipsTargetStreamer &TOut = getTargetStreamer();3514 assert(Inst.getNumOperands() == 2 && "Invalid operand count");3515 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&3516 "Invalid instruction operand.");3517 3518 MCRegister FirstReg = Inst.getOperand(0).getReg();3519 uint64_t ImmOp64 = Inst.getOperand(1).getImm();3520 3521 ImmOp64 = convertIntToDoubleImm(ImmOp64);3522 3523 MCRegister TmpReg = Mips::ZERO;3524 if (ImmOp64 != 0) {3525 TmpReg = getATReg(IDLoc);3526 if (!TmpReg)3527 return true;3528 }3529 3530 if ((Lo_32(ImmOp64) == 0) &&3531 !((Hi_32(ImmOp64) & 0xffff0000) && (Hi_32(ImmOp64) & 0x0000ffff))) {3532 if (isGP64bit()) {3533 if (TmpReg != Mips::ZERO && loadImmediate(ImmOp64, TmpReg, MCRegister(),3534 false, false, IDLoc, Out, STI))3535 return true;3536 TOut.emitRR(Mips::DMTC1, FirstReg, TmpReg, IDLoc, STI);3537 return false;3538 }3539 3540 if (TmpReg != Mips::ZERO &&3541 loadImmediate(Hi_32(ImmOp64), TmpReg, MCRegister(), true, false, IDLoc,3542 Out, STI))3543 return true;3544 3545 if (hasMips32r2()) {3546 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);3547 TOut.emitRRR(Mips::MTHC1_D32, FirstReg, FirstReg, TmpReg, IDLoc, STI);3548 } else {3549 TOut.emitRR(Mips::MTC1, nextReg(FirstReg), TmpReg, IDLoc, STI);3550 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);3551 }3552 return false;3553 }3554 3555 MCSection *CS = getStreamer().getCurrentSectionOnly();3556 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections3557 // where appropriate.3558 MCSection *ReadOnlySection =3559 getContext().getELFSection(".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);3560 3561 MCSymbol *Sym = getContext().createTempSymbol();3562 const MCExpr *LoSym = MCSymbolRefExpr::create(Sym, getContext());3563 const auto *LoExpr = MCSpecifierExpr::create(LoSym, Mips::S_LO, getContext());3564 3565 getStreamer().switchSection(ReadOnlySection);3566 getStreamer().emitLabel(Sym, IDLoc);3567 getStreamer().emitValueToAlignment(Align(8));3568 getStreamer().emitIntValue(ImmOp64, 8);3569 getStreamer().switchSection(CS);3570 3571 if (emitPartialAddress(TOut, IDLoc, Sym))3572 return true;3573 3574 TOut.emitRRX(Is64FPU ? Mips::LDC164 : Mips::LDC1, FirstReg, TmpReg,3575 MCOperand::createExpr(LoExpr), IDLoc, STI);3576 3577 return false;3578}3579 3580bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,3581 MCStreamer &Out,3582 const MCSubtargetInfo *STI) {3583 MipsTargetStreamer &TOut = getTargetStreamer();3584 3585 assert(MII.get(Inst.getOpcode()).getNumOperands() == 1 &&3586 "unexpected number of operands");3587 3588 MCOperand Offset = Inst.getOperand(0);3589 if (Offset.isExpr()) {3590 Inst.clear();3591 Inst.setOpcode(Mips::BEQ_MM);3592 Inst.addOperand(MCOperand::createReg(Mips::ZERO));3593 Inst.addOperand(MCOperand::createReg(Mips::ZERO));3594 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));3595 } else {3596 assert(Offset.isImm() && "expected immediate operand kind");3597 if (isInt<11>(Offset.getImm())) {3598 // If offset fits into 11 bits then this instruction becomes microMIPS3599 // 16-bit unconditional branch instruction.3600 if (inMicroMipsMode())3601 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);3602 } else {3603 if (!isInt<17>(Offset.getImm()))3604 return Error(IDLoc, "branch target out of range");3605 if (offsetToAlignment(Offset.getImm(), Align(2)))3606 return Error(IDLoc, "branch to misaligned address");3607 Inst.clear();3608 Inst.setOpcode(Mips::BEQ_MM);3609 Inst.addOperand(MCOperand::createReg(Mips::ZERO));3610 Inst.addOperand(MCOperand::createReg(Mips::ZERO));3611 Inst.addOperand(MCOperand::createImm(Offset.getImm()));3612 }3613 }3614 Out.emitInstruction(Inst, *STI);3615 3616 // If .set reorder is active and branch instruction has a delay slot,3617 // emit a NOP after it.3618 const MCInstrDesc &MCID = MII.get(Inst.getOpcode());3619 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())3620 TOut.emitEmptyDelaySlot(true, IDLoc, STI);3621 3622 return false;3623}3624 3625bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,3626 const MCSubtargetInfo *STI) {3627 MipsTargetStreamer &TOut = getTargetStreamer();3628 const MCOperand &DstRegOp = Inst.getOperand(0);3629 assert(DstRegOp.isReg() && "expected register operand kind");3630 3631 const MCOperand &ImmOp = Inst.getOperand(1);3632 assert(ImmOp.isImm() && "expected immediate operand kind");3633 3634 const MCOperand &MemOffsetOp = Inst.getOperand(2);3635 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&3636 "expected immediate or expression operand");3637 3638 bool IsLikely = false;3639 3640 unsigned OpCode = 0;3641 switch(Inst.getOpcode()) {3642 case Mips::BneImm:3643 OpCode = Mips::BNE;3644 break;3645 case Mips::BeqImm:3646 OpCode = Mips::BEQ;3647 break;3648 case Mips::BEQLImmMacro:3649 OpCode = Mips::BEQL;3650 IsLikely = true;3651 break;3652 case Mips::BNELImmMacro:3653 OpCode = Mips::BNEL;3654 IsLikely = true;3655 break;3656 default:3657 llvm_unreachable("Unknown immediate branch pseudo-instruction.");3658 break;3659 }3660 3661 int64_t ImmValue = ImmOp.getImm();3662 if (ImmValue == 0) {3663 if (IsLikely) {3664 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO,3665 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);3666 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);3667 } else3668 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,3669 STI);3670 } else {3671 warnIfNoMacro(IDLoc);3672 3673 MCRegister ATReg = getATReg(IDLoc);3674 if (!ATReg)3675 return true;3676 3677 if (loadImmediate(ImmValue, ATReg, MCRegister(), !isGP64bit(), true, IDLoc,3678 Out, STI))3679 return true;3680 3681 if (IsLikely && MemOffsetOp.isExpr()) {3682 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg,3683 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);3684 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);3685 } else3686 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);3687 }3688 return false;3689}3690 3691void MipsAsmParser::expandMem16Inst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,3692 const MCSubtargetInfo *STI, bool IsLoad) {3693 unsigned NumOp = Inst.getNumOperands();3694 assert((NumOp == 3 || NumOp == 4) && "unexpected operands number");3695 unsigned StartOp = NumOp == 3 ? 0 : 1;3696 3697 const MCOperand &DstRegOp = Inst.getOperand(StartOp);3698 assert(DstRegOp.isReg() && "expected register operand kind");3699 const MCOperand &BaseRegOp = Inst.getOperand(StartOp + 1);3700 assert(BaseRegOp.isReg() && "expected register operand kind");3701 const MCOperand &OffsetOp = Inst.getOperand(StartOp + 2);3702 3703 MipsTargetStreamer &TOut = getTargetStreamer();3704 unsigned OpCode = Inst.getOpcode();3705 MCRegister DstReg = DstRegOp.getReg();3706 MCRegister BaseReg = BaseRegOp.getReg();3707 MCRegister TmpReg = DstReg;3708 3709 const MCInstrDesc &Desc = MII.get(OpCode);3710 int16_t DstRegClass =3711 MII.getOpRegClassID(Desc.operands()[StartOp],3712 STI->getHwMode(MCSubtargetInfo::HwMode_RegInfo));3713 unsigned DstRegClassID =3714 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();3715 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||3716 (DstRegClassID == Mips::GPR64RegClassID);3717 3718 if (!IsLoad || !IsGPR || (BaseReg == DstReg)) {3719 // At this point we need AT to perform the expansions3720 // and we exit if it is not available.3721 TmpReg = getATReg(IDLoc);3722 if (!TmpReg)3723 return;3724 }3725 3726 auto emitInstWithOffset = [&](const MCOperand &Off) {3727 if (NumOp == 3)3728 TOut.emitRRX(OpCode, DstReg, TmpReg, Off, IDLoc, STI);3729 else3730 TOut.emitRRRX(OpCode, DstReg, DstReg, TmpReg, Off, IDLoc, STI);3731 };3732 3733 if (OffsetOp.isImm()) {3734 int64_t LoOffset = OffsetOp.getImm() & 0xffff;3735 int64_t HiOffset = OffsetOp.getImm() & ~0xffff;3736 3737 // If msb of LoOffset is 1(negative number) we must increment3738 // HiOffset to account for the sign-extension of the low part.3739 if (LoOffset & 0x8000)3740 HiOffset += 0x10000;3741 3742 bool IsLargeOffset = HiOffset != 0;3743 3744 if (IsLargeOffset) {3745 bool Is32BitImm = isInt<32>(OffsetOp.getImm());3746 if (loadImmediate(HiOffset, TmpReg, MCRegister(), Is32BitImm, true, IDLoc,3747 Out, STI))3748 return;3749 }3750 3751 if (BaseReg != Mips::ZERO && BaseReg != Mips::ZERO_64)3752 TOut.emitRRR(ABI.ArePtrs64bit() ? Mips::DADDu : Mips::ADDu, TmpReg,3753 TmpReg, BaseReg, IDLoc, STI);3754 emitInstWithOffset(MCOperand::createImm(int16_t(LoOffset)));3755 return;3756 }3757 3758 if (OffsetOp.isExpr()) {3759 if (inPicMode()) {3760 // FIXME:3761 // c) Check that immediates of R_MIPS_GOT16/R_MIPS_LO16 relocations3762 // do not exceed 16-bit.3763 // d) Use R_MIPS_GOT_PAGE/R_MIPS_GOT_OFST relocations instead3764 // of R_MIPS_GOT_DISP in appropriate cases to reduce number3765 // of GOT entries.3766 MCValue Res;3767 if (!OffsetOp.getExpr()->evaluateAsRelocatable(Res, nullptr)) {3768 Error(IDLoc, "expected relocatable expression");3769 return;3770 }3771 if (Res.getSubSym()) {3772 Error(IDLoc, "expected relocatable expression with only one symbol");3773 return;3774 }3775 3776 loadAndAddSymbolAddress(3777 MCSymbolRefExpr::create(Res.getAddSym(), getContext()), TmpReg,3778 BaseReg, !ABI.ArePtrs64bit(), IDLoc, Out, STI);3779 emitInstWithOffset(MCOperand::createImm(int16_t(Res.getConstant())));3780 } else {3781 // FIXME: Implement 64-bit case.3782 // 1) lw $8, sym => lui $8, %hi(sym)3783 // lw $8, %lo(sym)($8)3784 // 2) sw $8, sym => lui $at, %hi(sym)3785 // sw $8, %lo(sym)($at)3786 const MCExpr *OffExpr = OffsetOp.getExpr();3787 MCOperand LoOperand = MCOperand::createExpr(3788 MCSpecifierExpr::create(OffExpr, Mips::S_LO, getContext()));3789 MCOperand HiOperand = MCOperand::createExpr(3790 MCSpecifierExpr::create(OffExpr, Mips::S_HI, getContext()));3791 3792 if (ABI.IsN64()) {3793 MCOperand HighestOperand = MCOperand::createExpr(3794 MCSpecifierExpr::create(OffExpr, Mips::S_HIGHEST, getContext()));3795 MCOperand HigherOperand = MCOperand::createExpr(3796 MCSpecifierExpr::create(OffExpr, Mips::S_HIGHER, getContext()));3797 3798 TOut.emitRX(Mips::LUi, TmpReg, HighestOperand, IDLoc, STI);3799 TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, HigherOperand, IDLoc, STI);3800 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);3801 TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, HiOperand, IDLoc, STI);3802 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);3803 if (BaseReg != Mips::ZERO && BaseReg != Mips::ZERO_64)3804 TOut.emitRRR(Mips::DADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI);3805 emitInstWithOffset(LoOperand);3806 } else {3807 // Generate the base address in TmpReg.3808 TOut.emitRX(Mips::LUi, TmpReg, HiOperand, IDLoc, STI);3809 if (BaseReg != Mips::ZERO)3810 TOut.emitRRR(Mips::ADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI);3811 // Emit the load or store with the adjusted base and offset.3812 emitInstWithOffset(LoOperand);3813 }3814 }3815 return;3816 }3817 3818 llvm_unreachable("unexpected operand type");3819}3820 3821void MipsAsmParser::expandMem9Inst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,3822 const MCSubtargetInfo *STI, bool IsLoad) {3823 unsigned NumOp = Inst.getNumOperands();3824 assert((NumOp == 3 || NumOp == 4) && "unexpected operands number");3825 unsigned StartOp = NumOp == 3 ? 0 : 1;3826 3827 const MCOperand &DstRegOp = Inst.getOperand(StartOp);3828 assert(DstRegOp.isReg() && "expected register operand kind");3829 const MCOperand &BaseRegOp = Inst.getOperand(StartOp + 1);3830 assert(BaseRegOp.isReg() && "expected register operand kind");3831 const MCOperand &OffsetOp = Inst.getOperand(StartOp + 2);3832 3833 MipsTargetStreamer &TOut = getTargetStreamer();3834 unsigned OpCode = Inst.getOpcode();3835 MCRegister DstReg = DstRegOp.getReg();3836 MCRegister BaseReg = BaseRegOp.getReg();3837 MCRegister TmpReg = DstReg;3838 3839 const MCInstrDesc &Desc = MII.get(OpCode);3840 int16_t DstRegClass =3841 MII.getOpRegClassID(Desc.operands()[StartOp],3842 STI->getHwMode(MCSubtargetInfo::HwMode_RegInfo));3843 3844 unsigned DstRegClassID =3845 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();3846 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||3847 (DstRegClassID == Mips::GPR64RegClassID);3848 3849 if (!IsLoad || !IsGPR || (BaseReg == DstReg)) {3850 // At this point we need AT to perform the expansions3851 // and we exit if it is not available.3852 TmpReg = getATReg(IDLoc);3853 if (!TmpReg)3854 return;3855 }3856 3857 auto emitInst = [&]() {3858 if (NumOp == 3)3859 TOut.emitRRX(OpCode, DstReg, TmpReg, MCOperand::createImm(0), IDLoc, STI);3860 else3861 TOut.emitRRRX(OpCode, DstReg, DstReg, TmpReg, MCOperand::createImm(0),3862 IDLoc, STI);3863 };3864 3865 if (OffsetOp.isImm()) {3866 loadImmediate(OffsetOp.getImm(), TmpReg, BaseReg, !ABI.ArePtrs64bit(), true,3867 IDLoc, Out, STI);3868 emitInst();3869 return;3870 }3871 3872 if (OffsetOp.isExpr()) {3873 loadAndAddSymbolAddress(OffsetOp.getExpr(), TmpReg, BaseReg,3874 !ABI.ArePtrs64bit(), IDLoc, Out, STI);3875 emitInst();3876 return;3877 }3878 3879 llvm_unreachable("unexpected operand type");3880}3881 3882bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,3883 MCStreamer &Out,3884 const MCSubtargetInfo *STI) {3885 unsigned OpNum = Inst.getNumOperands();3886 unsigned Opcode = Inst.getOpcode();3887 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;3888 3889 assert(Inst.getOperand(OpNum - 1).isImm() &&3890 Inst.getOperand(OpNum - 2).isReg() &&3891 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");3892 3893 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&3894 Inst.getOperand(OpNum - 1).getImm() >= 0 &&3895 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||3896 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&3897 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||3898 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {3899 // It can be implemented as SWM16 or LWM16 instruction.3900 if (inMicroMipsMode() && hasMips32r6())3901 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;3902 else3903 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;3904 }3905 3906 Inst.setOpcode(NewOpcode);3907 Out.emitInstruction(Inst, *STI);3908 return false;3909}3910 3911bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,3912 MCStreamer &Out,3913 const MCSubtargetInfo *STI) {3914 MipsTargetStreamer &TOut = getTargetStreamer();3915 bool EmittedNoMacroWarning = false;3916 unsigned PseudoOpcode = Inst.getOpcode();3917 MCRegister SrcReg = Inst.getOperand(0).getReg();3918 const MCOperand &TrgOp = Inst.getOperand(1);3919 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();3920 3921 unsigned ZeroSrcOpcode, ZeroTrgOpcode;3922 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;3923 3924 MCRegister TrgReg;3925 if (TrgOp.isReg())3926 TrgReg = TrgOp.getReg();3927 else if (TrgOp.isImm()) {3928 warnIfNoMacro(IDLoc);3929 EmittedNoMacroWarning = true;3930 3931 TrgReg = getATReg(IDLoc);3932 if (!TrgReg)3933 return true;3934 3935 switch(PseudoOpcode) {3936 default:3937 llvm_unreachable("unknown opcode for branch pseudo-instruction");3938 case Mips::BLTImmMacro:3939 PseudoOpcode = Mips::BLT;3940 break;3941 case Mips::BLEImmMacro:3942 PseudoOpcode = Mips::BLE;3943 break;3944 case Mips::BGEImmMacro:3945 PseudoOpcode = Mips::BGE;3946 break;3947 case Mips::BGTImmMacro:3948 PseudoOpcode = Mips::BGT;3949 break;3950 case Mips::BLTUImmMacro:3951 PseudoOpcode = Mips::BLTU;3952 break;3953 case Mips::BLEUImmMacro:3954 PseudoOpcode = Mips::BLEU;3955 break;3956 case Mips::BGEUImmMacro:3957 PseudoOpcode = Mips::BGEU;3958 break;3959 case Mips::BGTUImmMacro:3960 PseudoOpcode = Mips::BGTU;3961 break;3962 case Mips::BLTLImmMacro:3963 PseudoOpcode = Mips::BLTL;3964 break;3965 case Mips::BLELImmMacro:3966 PseudoOpcode = Mips::BLEL;3967 break;3968 case Mips::BGELImmMacro:3969 PseudoOpcode = Mips::BGEL;3970 break;3971 case Mips::BGTLImmMacro:3972 PseudoOpcode = Mips::BGTL;3973 break;3974 case Mips::BLTULImmMacro:3975 PseudoOpcode = Mips::BLTUL;3976 break;3977 case Mips::BLEULImmMacro:3978 PseudoOpcode = Mips::BLEUL;3979 break;3980 case Mips::BGEULImmMacro:3981 PseudoOpcode = Mips::BGEUL;3982 break;3983 case Mips::BGTULImmMacro:3984 PseudoOpcode = Mips::BGTUL;3985 break;3986 }3987 3988 if (loadImmediate(TrgOp.getImm(), TrgReg, MCRegister(), !isGP64bit(), false,3989 IDLoc, Out, STI))3990 return true;3991 }3992 3993 switch (PseudoOpcode) {3994 case Mips::BLT:3995 case Mips::BLTU:3996 case Mips::BLTL:3997 case Mips::BLTUL:3998 AcceptsEquality = false;3999 ReverseOrderSLT = false;4000 IsUnsigned =4001 ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));4002 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));4003 ZeroSrcOpcode = Mips::BGTZ;4004 ZeroTrgOpcode = Mips::BLTZ;4005 break;4006 case Mips::BLE:4007 case Mips::BLEU:4008 case Mips::BLEL:4009 case Mips::BLEUL:4010 AcceptsEquality = true;4011 ReverseOrderSLT = true;4012 IsUnsigned =4013 ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));4014 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));4015 ZeroSrcOpcode = Mips::BGEZ;4016 ZeroTrgOpcode = Mips::BLEZ;4017 break;4018 case Mips::BGE:4019 case Mips::BGEU:4020 case Mips::BGEL:4021 case Mips::BGEUL:4022 AcceptsEquality = true;4023 ReverseOrderSLT = false;4024 IsUnsigned =4025 ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));4026 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));4027 ZeroSrcOpcode = Mips::BLEZ;4028 ZeroTrgOpcode = Mips::BGEZ;4029 break;4030 case Mips::BGT:4031 case Mips::BGTU:4032 case Mips::BGTL:4033 case Mips::BGTUL:4034 AcceptsEquality = false;4035 ReverseOrderSLT = true;4036 IsUnsigned =4037 ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));4038 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));4039 ZeroSrcOpcode = Mips::BLTZ;4040 ZeroTrgOpcode = Mips::BGTZ;4041 break;4042 default:4043 llvm_unreachable("unknown opcode for branch pseudo-instruction");4044 }4045 4046 bool IsTrgRegZero = (TrgReg == Mips::ZERO);4047 bool IsSrcRegZero = (SrcReg == Mips::ZERO);4048 if (IsSrcRegZero && IsTrgRegZero) {4049 // FIXME: All of these Opcode-specific if's are needed for compatibility4050 // with GAS' behaviour. However, they may not generate the most efficient4051 // code in some circumstances.4052 if (PseudoOpcode == Mips::BLT) {4053 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),4054 IDLoc, STI);4055 return false;4056 }4057 if (PseudoOpcode == Mips::BLE) {4058 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),4059 IDLoc, STI);4060 Warning(IDLoc, "branch is always taken");4061 return false;4062 }4063 if (PseudoOpcode == Mips::BGE) {4064 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),4065 IDLoc, STI);4066 Warning(IDLoc, "branch is always taken");4067 return false;4068 }4069 if (PseudoOpcode == Mips::BGT) {4070 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),4071 IDLoc, STI);4072 return false;4073 }4074 if (PseudoOpcode == Mips::BGTU) {4075 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,4076 MCOperand::createExpr(OffsetExpr), IDLoc, STI);4077 return false;4078 }4079 if (AcceptsEquality) {4080 // If both registers are $0 and the pseudo-branch accepts equality, it4081 // will always be taken, so we emit an unconditional branch.4082 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,4083 MCOperand::createExpr(OffsetExpr), IDLoc, STI);4084 Warning(IDLoc, "branch is always taken");4085 return false;4086 }4087 // If both registers are $0 and the pseudo-branch does not accept4088 // equality, it will never be taken, so we don't have to emit anything.4089 return false;4090 }4091 if (IsSrcRegZero || IsTrgRegZero) {4092 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||4093 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {4094 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or4095 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),4096 // the pseudo-branch will never be taken, so we don't emit anything.4097 // This only applies to unsigned pseudo-branches.4098 return false;4099 }4100 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||4101 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {4102 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or4103 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),4104 // the pseudo-branch will always be taken, so we emit an unconditional4105 // branch.4106 // This only applies to unsigned pseudo-branches.4107 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,4108 MCOperand::createExpr(OffsetExpr), IDLoc, STI);4109 Warning(IDLoc, "branch is always taken");4110 return false;4111 }4112 if (IsUnsigned) {4113 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or4114 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),4115 // the pseudo-branch will be taken only when the non-zero register is4116 // different from 0, so we emit a BNEZ.4117 //4118 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or4119 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),4120 // the pseudo-branch will be taken only when the non-zero register is4121 // equal to 0, so we emit a BEQZ.4122 //4123 // Because only BLEU and BGEU branch on equality, we can use the4124 // AcceptsEquality variable to decide when to emit the BEQZ.4125 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,4126 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,4127 MCOperand::createExpr(OffsetExpr), IDLoc, STI);4128 return false;4129 }4130 // If we have a signed pseudo-branch and one of the registers is $0,4131 // we can use an appropriate compare-to-zero branch. We select which one4132 // to use in the switch statement above.4133 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,4134 IsSrcRegZero ? TrgReg : SrcReg,4135 MCOperand::createExpr(OffsetExpr), IDLoc, STI);4136 return false;4137 }4138 4139 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the4140 // expansions. If it is not available, we return.4141 MCRegister ATRegNum = getATReg(IDLoc);4142 if (!ATRegNum)4143 return true;4144 4145 if (!EmittedNoMacroWarning)4146 warnIfNoMacro(IDLoc);4147 4148 // SLT fits well with 2 of our 4 pseudo-branches:4149 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and4150 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".4151 // If the result of the SLT is 1, we branch, and if it's 0, we don't.4152 // This is accomplished by using a BNEZ with the result of the SLT.4153 //4154 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT4155 // and BLE with BGT), so we change the BNEZ into a BEQZ.4156 // Because only BGE and BLE branch on equality, we can use the4157 // AcceptsEquality variable to decide when to emit the BEQZ.4158 // Note that the order of the SLT arguments doesn't change between4159 // opposites.4160 //4161 // The same applies to the unsigned variants, except that SLTu is used4162 // instead of SLT.4163 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,4164 ReverseOrderSLT ? TrgReg : SrcReg,4165 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);4166 4167 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)4168 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),4169 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,4170 STI);4171 return false;4172}4173 4174// Expand a integer division macro.4175//4176// Notably we don't have to emit a warning when encountering $rt as the $zero4177// register, or 0 as an immediate. processInstruction() has already done that.4178//4179// The destination register can only be $zero when expanding (S)DivIMacro or4180// D(S)DivMacro.4181 4182bool MipsAsmParser::expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,4183 const MCSubtargetInfo *STI,4184 const bool IsMips64, const bool Signed) {4185 MipsTargetStreamer &TOut = getTargetStreamer();4186 4187 warnIfNoMacro(IDLoc);4188 4189 const MCOperand &RdRegOp = Inst.getOperand(0);4190 assert(RdRegOp.isReg() && "expected register operand kind");4191 MCRegister RdReg = RdRegOp.getReg();4192 4193 const MCOperand &RsRegOp = Inst.getOperand(1);4194 assert(RsRegOp.isReg() && "expected register operand kind");4195 MCRegister RsReg = RsRegOp.getReg();4196 4197 MCRegister RtReg;4198 int64_t ImmValue;4199 4200 const MCOperand &RtOp = Inst.getOperand(2);4201 assert((RtOp.isReg() || RtOp.isImm()) &&4202 "expected register or immediate operand kind");4203 if (RtOp.isReg())4204 RtReg = RtOp.getReg();4205 else4206 ImmValue = RtOp.getImm();4207 4208 unsigned DivOp;4209 unsigned ZeroReg;4210 unsigned SubOp;4211 4212 if (IsMips64) {4213 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;4214 ZeroReg = Mips::ZERO_64;4215 SubOp = Mips::DSUB;4216 } else {4217 DivOp = Signed ? Mips::SDIV : Mips::UDIV;4218 ZeroReg = Mips::ZERO;4219 SubOp = Mips::SUB;4220 }4221 4222 bool UseTraps = useTraps();4223 4224 unsigned Opcode = Inst.getOpcode();4225 bool isDiv = Opcode == Mips::SDivMacro || Opcode == Mips::SDivIMacro ||4226 Opcode == Mips::UDivMacro || Opcode == Mips::UDivIMacro ||4227 Opcode == Mips::DSDivMacro || Opcode == Mips::DSDivIMacro ||4228 Opcode == Mips::DUDivMacro || Opcode == Mips::DUDivIMacro;4229 4230 bool isRem = Opcode == Mips::SRemMacro || Opcode == Mips::SRemIMacro ||4231 Opcode == Mips::URemMacro || Opcode == Mips::URemIMacro ||4232 Opcode == Mips::DSRemMacro || Opcode == Mips::DSRemIMacro ||4233 Opcode == Mips::DURemMacro || Opcode == Mips::DURemIMacro;4234 4235 if (RtOp.isImm()) {4236 MCRegister ATReg = getATReg(IDLoc);4237 if (!ATReg)4238 return true;4239 4240 if (ImmValue == 0) {4241 if (UseTraps)4242 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);4243 else4244 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);4245 return false;4246 }4247 4248 if (isRem && (ImmValue == 1 || (Signed && (ImmValue == -1)))) {4249 TOut.emitRRR(Mips::OR, RdReg, ZeroReg, ZeroReg, IDLoc, STI);4250 return false;4251 } else if (isDiv && ImmValue == 1) {4252 TOut.emitRRR(Mips::OR, RdReg, RsReg, Mips::ZERO, IDLoc, STI);4253 return false;4254 } else if (isDiv && Signed && ImmValue == -1) {4255 TOut.emitRRR(SubOp, RdReg, ZeroReg, RsReg, IDLoc, STI);4256 return false;4257 } else {4258 if (loadImmediate(ImmValue, ATReg, MCRegister(), isInt<32>(ImmValue),4259 false, Inst.getLoc(), Out, STI))4260 return true;4261 TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI);4262 TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);4263 return false;4264 }4265 return true;4266 }4267 4268 // If the macro expansion of (d)div(u) or (d)rem(u) would always trap or4269 // break, insert the trap/break and exit. This gives a different result to4270 // GAS. GAS has an inconsistency/missed optimization in that not all cases4271 // are handled equivalently. As the observed behaviour is the same, we're ok.4272 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {4273 if (UseTraps) {4274 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);4275 return false;4276 }4277 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);4278 return false;4279 }4280 4281 // (d)rem(u) $0, $X, $Y is a special case. Like div $zero, $X, $Y, it does4282 // not expand to macro sequence.4283 if (isRem && (RdReg == Mips::ZERO || RdReg == Mips::ZERO_64)) {4284 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);4285 return false;4286 }4287 4288 // Temporary label for first branch traget4289 MCContext &Context = TOut.getContext();4290 MCSymbol *BrTarget;4291 MCOperand LabelOp;4292 4293 if (UseTraps) {4294 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);4295 } else {4296 // Branch to the li instruction.4297 BrTarget = Context.createTempSymbol();4298 LabelOp = MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));4299 TOut.emitRRX(Mips::BNE, RtReg, ZeroReg, LabelOp, IDLoc, STI);4300 }4301 4302 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);4303 4304 if (!UseTraps)4305 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);4306 4307 if (!Signed) {4308 if (!UseTraps)4309 TOut.getStreamer().emitLabel(BrTarget);4310 4311 TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);4312 return false;4313 }4314 4315 MCRegister ATReg = getATReg(IDLoc);4316 if (!ATReg)4317 return true;4318 4319 if (!UseTraps)4320 TOut.getStreamer().emitLabel(BrTarget);4321 4322 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);4323 4324 // Temporary label for the second branch target.4325 MCSymbol *BrTargetEnd = Context.createTempSymbol();4326 MCOperand LabelOpEnd =4327 MCOperand::createExpr(MCSymbolRefExpr::create(BrTargetEnd, Context));4328 4329 // Branch to the mflo instruction.4330 TOut.emitRRX(Mips::BNE, RtReg, ATReg, LabelOpEnd, IDLoc, STI);4331 4332 if (IsMips64) {4333 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);4334 TOut.emitDSLL(ATReg, ATReg, 63, IDLoc, STI);4335 } else {4336 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);4337 }4338 4339 if (UseTraps)4340 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);4341 else {4342 // Branch to the mflo instruction.4343 TOut.emitRRX(Mips::BNE, RsReg, ATReg, LabelOpEnd, IDLoc, STI);4344 TOut.emitNop(IDLoc, STI);4345 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);4346 }4347 4348 TOut.getStreamer().emitLabel(BrTargetEnd);4349 TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);4350 return false;4351}4352 4353bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,4354 SMLoc IDLoc, MCStreamer &Out,4355 const MCSubtargetInfo *STI) {4356 MipsTargetStreamer &TOut = getTargetStreamer();4357 4358 assert(Inst.getNumOperands() == 3 && "Invalid operand count");4359 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&4360 Inst.getOperand(2).isReg() && "Invalid instruction operand.");4361 4362 MCRegister FirstReg = Inst.getOperand(0).getReg();4363 MCRegister SecondReg = Inst.getOperand(1).getReg();4364 MCRegister ThirdReg = Inst.getOperand(2).getReg();4365 4366 if (hasMips1() && !hasMips2()) {4367 MCRegister ATReg = getATReg(IDLoc);4368 if (!ATReg)4369 return true;4370 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);4371 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);4372 TOut.emitNop(IDLoc, STI);4373 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);4374 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);4375 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);4376 TOut.emitNop(IDLoc, STI);4377 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)4378 : Mips::CVT_W_S,4379 FirstReg, SecondReg, IDLoc, STI);4380 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);4381 TOut.emitNop(IDLoc, STI);4382 return false;4383 }4384 4385 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)4386 : Mips::TRUNC_W_S,4387 FirstReg, SecondReg, IDLoc, STI);4388 4389 return false;4390}4391 4392bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,4393 MCStreamer &Out, const MCSubtargetInfo *STI) {4394 if (hasMips32r6() || hasMips64r6()) {4395 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");4396 }4397 4398 const MCOperand &DstRegOp = Inst.getOperand(0);4399 assert(DstRegOp.isReg() && "expected register operand kind");4400 const MCOperand &SrcRegOp = Inst.getOperand(1);4401 assert(SrcRegOp.isReg() && "expected register operand kind");4402 const MCOperand &OffsetImmOp = Inst.getOperand(2);4403 assert(OffsetImmOp.isImm() && "expected immediate operand kind");4404 4405 MipsTargetStreamer &TOut = getTargetStreamer();4406 MCRegister DstReg = DstRegOp.getReg();4407 MCRegister SrcReg = SrcRegOp.getReg();4408 int64_t OffsetValue = OffsetImmOp.getImm();4409 4410 // NOTE: We always need AT for ULHU, as it is always used as the source4411 // register for one of the LBu's.4412 warnIfNoMacro(IDLoc);4413 MCRegister ATReg = getATReg(IDLoc);4414 if (!ATReg)4415 return true;4416 4417 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));4418 if (IsLargeOffset) {4419 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,4420 IDLoc, Out, STI))4421 return true;4422 }4423 4424 int64_t FirstOffset = IsLargeOffset ? 0 : OffsetValue;4425 int64_t SecondOffset = IsLargeOffset ? 1 : (OffsetValue + 1);4426 if (isLittle())4427 std::swap(FirstOffset, SecondOffset);4428 4429 MCRegister FirstLbuDstReg = IsLargeOffset ? DstReg : ATReg;4430 MCRegister SecondLbuDstReg = IsLargeOffset ? ATReg : DstReg;4431 4432 MCRegister LbuSrcReg = IsLargeOffset ? ATReg : SrcReg;4433 MCRegister SllReg = IsLargeOffset ? DstReg : ATReg;4434 4435 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,4436 FirstOffset, IDLoc, STI);4437 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondOffset, IDLoc, STI);4438 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);4439 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);4440 4441 return false;4442}4443 4444bool MipsAsmParser::expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,4445 const MCSubtargetInfo *STI) {4446 if (hasMips32r6() || hasMips64r6()) {4447 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");4448 }4449 4450 const MCOperand &DstRegOp = Inst.getOperand(0);4451 assert(DstRegOp.isReg() && "expected register operand kind");4452 const MCOperand &SrcRegOp = Inst.getOperand(1);4453 assert(SrcRegOp.isReg() && "expected register operand kind");4454 const MCOperand &OffsetImmOp = Inst.getOperand(2);4455 assert(OffsetImmOp.isImm() && "expected immediate operand kind");4456 4457 MipsTargetStreamer &TOut = getTargetStreamer();4458 MCRegister DstReg = DstRegOp.getReg();4459 MCRegister SrcReg = SrcRegOp.getReg();4460 int64_t OffsetValue = OffsetImmOp.getImm();4461 4462 warnIfNoMacro(IDLoc);4463 MCRegister ATReg = getATReg(IDLoc);4464 if (!ATReg)4465 return true;4466 4467 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));4468 if (IsLargeOffset) {4469 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,4470 IDLoc, Out, STI))4471 return true;4472 }4473 4474 int64_t FirstOffset = IsLargeOffset ? 1 : (OffsetValue + 1);4475 int64_t SecondOffset = IsLargeOffset ? 0 : OffsetValue;4476 if (isLittle())4477 std::swap(FirstOffset, SecondOffset);4478 4479 if (IsLargeOffset) {4480 TOut.emitRRI(Mips::SB, DstReg, ATReg, FirstOffset, IDLoc, STI);4481 TOut.emitRRI(Mips::SRL, DstReg, DstReg, 8, IDLoc, STI);4482 TOut.emitRRI(Mips::SB, DstReg, ATReg, SecondOffset, IDLoc, STI);4483 TOut.emitRRI(Mips::LBu, ATReg, ATReg, 0, IDLoc, STI);4484 TOut.emitRRI(Mips::SLL, DstReg, DstReg, 8, IDLoc, STI);4485 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);4486 } else {4487 TOut.emitRRI(Mips::SB, DstReg, SrcReg, FirstOffset, IDLoc, STI);4488 TOut.emitRRI(Mips::SRL, ATReg, DstReg, 8, IDLoc, STI);4489 TOut.emitRRI(Mips::SB, ATReg, SrcReg, SecondOffset, IDLoc, STI);4490 }4491 4492 return false;4493}4494 4495bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,4496 const MCSubtargetInfo *STI) {4497 if (hasMips32r6() || hasMips64r6()) {4498 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");4499 }4500 4501 const MCOperand &DstRegOp = Inst.getOperand(0);4502 assert(DstRegOp.isReg() && "expected register operand kind");4503 const MCOperand &SrcRegOp = Inst.getOperand(1);4504 assert(SrcRegOp.isReg() && "expected register operand kind");4505 const MCOperand &OffsetImmOp = Inst.getOperand(2);4506 assert(OffsetImmOp.isImm() && "expected immediate operand kind");4507 4508 MipsTargetStreamer &TOut = getTargetStreamer();4509 MCRegister DstReg = DstRegOp.getReg();4510 MCRegister SrcReg = SrcRegOp.getReg();4511 int64_t OffsetValue = OffsetImmOp.getImm();4512 4513 // Compute left/right load/store offsets.4514 bool IsLargeOffset = !(isInt<16>(OffsetValue + 3) && isInt<16>(OffsetValue));4515 int64_t LxlOffset = IsLargeOffset ? 0 : OffsetValue;4516 int64_t LxrOffset = IsLargeOffset ? 3 : (OffsetValue + 3);4517 if (isLittle())4518 std::swap(LxlOffset, LxrOffset);4519 4520 bool IsLoadInst = (Inst.getOpcode() == Mips::Ulw);4521 bool DoMove = IsLoadInst && (SrcReg == DstReg) && !IsLargeOffset;4522 MCRegister TmpReg = SrcReg;4523 if (IsLargeOffset || DoMove) {4524 warnIfNoMacro(IDLoc);4525 TmpReg = getATReg(IDLoc);4526 if (!TmpReg)4527 return true;4528 }4529 4530 if (IsLargeOffset) {4531 if (loadImmediate(OffsetValue, TmpReg, SrcReg, !ABI.ArePtrs64bit(), true,4532 IDLoc, Out, STI))4533 return true;4534 }4535 4536 if (DoMove)4537 std::swap(DstReg, TmpReg);4538 4539 unsigned XWL = IsLoadInst ? Mips::LWL : Mips::SWL;4540 unsigned XWR = IsLoadInst ? Mips::LWR : Mips::SWR;4541 TOut.emitRRI(XWL, DstReg, TmpReg, LxlOffset, IDLoc, STI);4542 TOut.emitRRI(XWR, DstReg, TmpReg, LxrOffset, IDLoc, STI);4543 4544 if (DoMove)4545 TOut.emitRRR(Mips::OR, TmpReg, DstReg, Mips::ZERO, IDLoc, STI);4546 4547 return false;4548}4549 4550bool MipsAsmParser::expandSge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,4551 const MCSubtargetInfo *STI) {4552 MipsTargetStreamer &TOut = getTargetStreamer();4553 4554 assert(Inst.getNumOperands() == 3 && "Invalid operand count");4555 assert(Inst.getOperand(0).isReg() &&4556 Inst.getOperand(1).isReg() &&4557 Inst.getOperand(2).isReg() && "Invalid instruction operand.");4558 4559 MCRegister DstReg = Inst.getOperand(0).getReg();4560 MCRegister SrcReg = Inst.getOperand(1).getReg();4561 MCRegister OpReg = Inst.getOperand(2).getReg();4562 unsigned OpCode;4563 4564 warnIfNoMacro(IDLoc);4565 4566 switch (Inst.getOpcode()) {4567 case Mips::SGE:4568 OpCode = Mips::SLT;4569 break;4570 case Mips::SGEU:4571 OpCode = Mips::SLTu;4572 break;4573 default:4574 llvm_unreachable("unexpected 'sge' opcode");4575 }4576 4577 // $SrcReg >= $OpReg is equal to (not ($SrcReg < $OpReg))4578 TOut.emitRRR(OpCode, DstReg, SrcReg, OpReg, IDLoc, STI);4579 TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI);4580 4581 return false;4582}4583 4584bool MipsAsmParser::expandSgeImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,4585 const MCSubtargetInfo *STI) {4586 MipsTargetStreamer &TOut = getTargetStreamer();4587 4588 assert(Inst.getNumOperands() == 3 && "Invalid operand count");4589 assert(Inst.getOperand(0).isReg() &&4590 Inst.getOperand(1).isReg() &&4591 Inst.getOperand(2).isImm() && "Invalid instruction operand.");4592 4593 MCRegister DstReg = Inst.getOperand(0).getReg();4594 MCRegister SrcReg = Inst.getOperand(1).getReg();4595 int64_t ImmValue = Inst.getOperand(2).getImm();4596 unsigned OpRegCode, OpImmCode;4597 4598 warnIfNoMacro(IDLoc);4599 4600 switch (Inst.getOpcode()) {4601 case Mips::SGEImm:4602 case Mips::SGEImm64:4603 OpRegCode = Mips::SLT;4604 OpImmCode = Mips::SLTi;4605 break;4606 case Mips::SGEUImm:4607 case Mips::SGEUImm64:4608 OpRegCode = Mips::SLTu;4609 OpImmCode = Mips::SLTiu;4610 break;4611 default:4612 llvm_unreachable("unexpected 'sge' opcode with immediate");4613 }4614 4615 // $SrcReg >= Imm is equal to (not ($SrcReg < Imm))4616 if (isInt<16>(ImmValue)) {4617 // Use immediate version of STL.4618 TOut.emitRRI(OpImmCode, DstReg, SrcReg, ImmValue, IDLoc, STI);4619 TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI);4620 } else {4621 MCRegister ImmReg = DstReg;4622 if (DstReg == SrcReg) {4623 MCRegister ATReg = getATReg(Inst.getLoc());4624 if (!ATReg)4625 return true;4626 ImmReg = ATReg;4627 }4628 4629 if (loadImmediate(ImmValue, ImmReg, MCRegister(), isInt<32>(ImmValue),4630 false, IDLoc, Out, STI))4631 return true;4632 4633 TOut.emitRRR(OpRegCode, DstReg, SrcReg, ImmReg, IDLoc, STI);4634 TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI);4635 }4636 4637 return false;4638}4639 4640bool MipsAsmParser::expandSgtImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,4641 const MCSubtargetInfo *STI) {4642 MipsTargetStreamer &TOut = getTargetStreamer();4643 4644 assert(Inst.getNumOperands() == 3 && "Invalid operand count");4645 assert(Inst.getOperand(0).isReg() &&4646 Inst.getOperand(1).isReg() &&4647 Inst.getOperand(2).isImm() && "Invalid instruction operand.");4648 4649 MCRegister DstReg = Inst.getOperand(0).getReg();4650 MCRegister SrcReg = Inst.getOperand(1).getReg();4651 MCRegister ImmReg = DstReg;4652 int64_t ImmValue = Inst.getOperand(2).getImm();4653 unsigned OpCode;4654 4655 warnIfNoMacro(IDLoc);4656 4657 switch (Inst.getOpcode()) {4658 case Mips::SGTImm:4659 case Mips::SGTImm64:4660 OpCode = Mips::SLT;4661 break;4662 case Mips::SGTUImm:4663 case Mips::SGTUImm64:4664 OpCode = Mips::SLTu;4665 break;4666 default:4667 llvm_unreachable("unexpected 'sgt' opcode with immediate");4668 }4669 4670 if (DstReg == SrcReg) {4671 MCRegister ATReg = getATReg(Inst.getLoc());4672 if (!ATReg)4673 return true;4674 ImmReg = ATReg;4675 }4676 4677 if (loadImmediate(ImmValue, ImmReg, MCRegister(), isInt<32>(ImmValue), false,4678 IDLoc, Out, STI))4679 return true;4680 4681 // $SrcReg > $ImmReg is equal to $ImmReg < $SrcReg4682 TOut.emitRRR(OpCode, DstReg, ImmReg, SrcReg, IDLoc, STI);4683 4684 return false;4685}4686 4687bool MipsAsmParser::expandSle(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,4688 const MCSubtargetInfo *STI) {4689 MipsTargetStreamer &TOut = getTargetStreamer();4690 4691 assert(Inst.getNumOperands() == 3 && "Invalid operand count");4692 assert(Inst.getOperand(0).isReg() &&4693 Inst.getOperand(1).isReg() &&4694 Inst.getOperand(2).isReg() && "Invalid instruction operand.");4695 4696 MCRegister DstReg = Inst.getOperand(0).getReg();4697 MCRegister SrcReg = Inst.getOperand(1).getReg();4698 MCRegister OpReg = Inst.getOperand(2).getReg();4699 unsigned OpCode;4700 4701 warnIfNoMacro(IDLoc);4702 4703 switch (Inst.getOpcode()) {4704 case Mips::SLE:4705 OpCode = Mips::SLT;4706 break;4707 case Mips::SLEU:4708 OpCode = Mips::SLTu;4709 break;4710 default:4711 llvm_unreachable("unexpected 'sge' opcode");4712 }4713 4714 // $SrcReg <= $OpReg is equal to (not ($OpReg < $SrcReg))4715 TOut.emitRRR(OpCode, DstReg, OpReg, SrcReg, IDLoc, STI);4716 TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI);4717 4718 return false;4719}4720 4721bool MipsAsmParser::expandSleImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,4722 const MCSubtargetInfo *STI) {4723 MipsTargetStreamer &TOut = getTargetStreamer();4724 4725 assert(Inst.getNumOperands() == 3 && "Invalid operand count");4726 assert(Inst.getOperand(0).isReg() &&4727 Inst.getOperand(1).isReg() &&4728 Inst.getOperand(2).isImm() && "Invalid instruction operand.");4729 4730 MCRegister DstReg = Inst.getOperand(0).getReg();4731 MCRegister SrcReg = Inst.getOperand(1).getReg();4732 int64_t ImmValue = Inst.getOperand(2).getImm();4733 unsigned OpRegCode;4734 4735 warnIfNoMacro(IDLoc);4736 4737 switch (Inst.getOpcode()) {4738 case Mips::SLEImm:4739 case Mips::SLEImm64:4740 OpRegCode = Mips::SLT;4741 break;4742 case Mips::SLEUImm:4743 case Mips::SLEUImm64:4744 OpRegCode = Mips::SLTu;4745 break;4746 default:4747 llvm_unreachable("unexpected 'sge' opcode with immediate");4748 }4749 4750 // $SrcReg <= Imm is equal to (not (Imm < $SrcReg))4751 MCRegister ImmReg = DstReg;4752 if (DstReg == SrcReg) {4753 MCRegister ATReg = getATReg(Inst.getLoc());4754 if (!ATReg)4755 return true;4756 ImmReg = ATReg;4757 }4758 4759 if (loadImmediate(ImmValue, ImmReg, MCRegister(), isInt<32>(ImmValue), false,4760 IDLoc, Out, STI))4761 return true;4762 4763 TOut.emitRRR(OpRegCode, DstReg, ImmReg, SrcReg, IDLoc, STI);4764 TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI);4765 4766 return false;4767}4768 4769bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,4770 MCStreamer &Out,4771 const MCSubtargetInfo *STI) {4772 MipsTargetStreamer &TOut = getTargetStreamer();4773 4774 assert(Inst.getNumOperands() == 3 && "Invalid operand count");4775 assert(Inst.getOperand(0).isReg() &&4776 Inst.getOperand(1).isReg() &&4777 Inst.getOperand(2).isImm() && "Invalid instruction operand.");4778 4779 MCRegister ATReg;4780 MCRegister FinalDstReg;4781 MCRegister DstReg = Inst.getOperand(0).getReg();4782 MCRegister SrcReg = Inst.getOperand(1).getReg();4783 int64_t ImmValue = Inst.getOperand(2).getImm();4784 4785 bool Is32Bit = isInt<32>(ImmValue) || (!isGP64bit() && isUInt<32>(ImmValue));4786 4787 unsigned FinalOpcode = Inst.getOpcode();4788 4789 if (DstReg == SrcReg) {4790 ATReg = getATReg(Inst.getLoc());4791 if (!ATReg)4792 return true;4793 FinalDstReg = DstReg;4794 DstReg = ATReg;4795 }4796 4797 if (!loadImmediate(ImmValue, DstReg, MCRegister(), Is32Bit, false,4798 Inst.getLoc(), Out, STI)) {4799 switch (FinalOpcode) {4800 default:4801 llvm_unreachable("unimplemented expansion");4802 case Mips::ADDi:4803 FinalOpcode = Mips::ADD;4804 break;4805 case Mips::ADDiu:4806 FinalOpcode = Mips::ADDu;4807 break;4808 case Mips::ANDi:4809 FinalOpcode = Mips::AND;4810 break;4811 case Mips::NORImm:4812 FinalOpcode = Mips::NOR;4813 break;4814 case Mips::ORi:4815 FinalOpcode = Mips::OR;4816 break;4817 case Mips::SLTi:4818 FinalOpcode = Mips::SLT;4819 break;4820 case Mips::SLTiu:4821 FinalOpcode = Mips::SLTu;4822 break;4823 case Mips::XORi:4824 FinalOpcode = Mips::XOR;4825 break;4826 case Mips::ADDi_MM:4827 FinalOpcode = Mips::ADD_MM;4828 break;4829 case Mips::ADDiu_MM:4830 FinalOpcode = Mips::ADDu_MM;4831 break;4832 case Mips::ANDi_MM:4833 FinalOpcode = Mips::AND_MM;4834 break;4835 case Mips::ORi_MM:4836 FinalOpcode = Mips::OR_MM;4837 break;4838 case Mips::SLTi_MM:4839 FinalOpcode = Mips::SLT_MM;4840 break;4841 case Mips::SLTiu_MM:4842 FinalOpcode = Mips::SLTu_MM;4843 break;4844 case Mips::XORi_MM:4845 FinalOpcode = Mips::XOR_MM;4846 break;4847 case Mips::ANDi64:4848 FinalOpcode = Mips::AND64;4849 break;4850 case Mips::NORImm64:4851 FinalOpcode = Mips::NOR64;4852 break;4853 case Mips::ORi64:4854 FinalOpcode = Mips::OR64;4855 break;4856 case Mips::SLTImm64:4857 FinalOpcode = Mips::SLT64;4858 break;4859 case Mips::SLTUImm64:4860 FinalOpcode = Mips::SLTu64;4861 break;4862 case Mips::XORi64:4863 FinalOpcode = Mips::XOR64;4864 break;4865 }4866 4867 if (!FinalDstReg)4868 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);4869 else4870 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);4871 return false;4872 }4873 return true;4874}4875 4876bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,4877 const MCSubtargetInfo *STI) {4878 MipsTargetStreamer &TOut = getTargetStreamer();4879 MCRegister ATReg;4880 MCRegister DReg = Inst.getOperand(0).getReg();4881 MCRegister SReg = Inst.getOperand(1).getReg();4882 MCRegister TReg = Inst.getOperand(2).getReg();4883 MCRegister TmpReg = DReg;4884 4885 unsigned FirstShift = Mips::NOP;4886 unsigned SecondShift = Mips::NOP;4887 4888 if (hasMips32r2()) {4889 if (DReg == SReg) {4890 TmpReg = getATReg(Inst.getLoc());4891 if (!TmpReg)4892 return true;4893 }4894 4895 if (Inst.getOpcode() == Mips::ROL) {4896 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);4897 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);4898 return false;4899 }4900 4901 if (Inst.getOpcode() == Mips::ROR) {4902 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);4903 return false;4904 }4905 4906 return true;4907 }4908 4909 if (hasMips32()) {4910 switch (Inst.getOpcode()) {4911 default:4912 llvm_unreachable("unexpected instruction opcode");4913 case Mips::ROL:4914 FirstShift = Mips::SRLV;4915 SecondShift = Mips::SLLV;4916 break;4917 case Mips::ROR:4918 FirstShift = Mips::SLLV;4919 SecondShift = Mips::SRLV;4920 break;4921 }4922 4923 ATReg = getATReg(Inst.getLoc());4924 if (!ATReg)4925 return true;4926 4927 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);4928 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);4929 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);4930 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);4931 4932 return false;4933 }4934 4935 return true;4936}4937 4938bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,4939 MCStreamer &Out,4940 const MCSubtargetInfo *STI) {4941 MipsTargetStreamer &TOut = getTargetStreamer();4942 MCRegister ATReg;4943 MCRegister DReg = Inst.getOperand(0).getReg();4944 MCRegister SReg = Inst.getOperand(1).getReg();4945 int64_t ImmValue = Inst.getOperand(2).getImm();4946 4947 unsigned FirstShift = Mips::NOP;4948 unsigned SecondShift = Mips::NOP;4949 4950 if (hasMips32r2()) {4951 if (Inst.getOpcode() == Mips::ROLImm) {4952 uint64_t MaxShift = 32;4953 uint64_t ShiftValue = ImmValue;4954 if (ImmValue != 0)4955 ShiftValue = MaxShift - ImmValue;4956 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);4957 return false;4958 }4959 4960 if (Inst.getOpcode() == Mips::RORImm) {4961 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);4962 return false;4963 }4964 4965 return true;4966 }4967 4968 if (hasMips32()) {4969 if (ImmValue == 0) {4970 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);4971 return false;4972 }4973 4974 switch (Inst.getOpcode()) {4975 default:4976 llvm_unreachable("unexpected instruction opcode");4977 case Mips::ROLImm:4978 FirstShift = Mips::SLL;4979 SecondShift = Mips::SRL;4980 break;4981 case Mips::RORImm:4982 FirstShift = Mips::SRL;4983 SecondShift = Mips::SLL;4984 break;4985 }4986 4987 ATReg = getATReg(Inst.getLoc());4988 if (!ATReg)4989 return true;4990 4991 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);4992 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);4993 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);4994 4995 return false;4996 }4997 4998 return true;4999}5000 5001bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,5002 const MCSubtargetInfo *STI) {5003 MipsTargetStreamer &TOut = getTargetStreamer();5004 MCRegister ATReg;5005 MCRegister DReg = Inst.getOperand(0).getReg();5006 MCRegister SReg = Inst.getOperand(1).getReg();5007 MCRegister TReg = Inst.getOperand(2).getReg();5008 MCRegister TmpReg = DReg;5009 5010 unsigned FirstShift = Mips::NOP;5011 unsigned SecondShift = Mips::NOP;5012 5013 if (hasMips64r2()) {5014 if (TmpReg == SReg) {5015 TmpReg = getATReg(Inst.getLoc());5016 if (!TmpReg)5017 return true;5018 }5019 5020 if (Inst.getOpcode() == Mips::DROL) {5021 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);5022 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);5023 return false;5024 }5025 5026 if (Inst.getOpcode() == Mips::DROR) {5027 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);5028 return false;5029 }5030 5031 return true;5032 }5033 5034 if (hasMips64()) {5035 switch (Inst.getOpcode()) {5036 default:5037 llvm_unreachable("unexpected instruction opcode");5038 case Mips::DROL:5039 FirstShift = Mips::DSRLV;5040 SecondShift = Mips::DSLLV;5041 break;5042 case Mips::DROR:5043 FirstShift = Mips::DSLLV;5044 SecondShift = Mips::DSRLV;5045 break;5046 }5047 5048 ATReg = getATReg(Inst.getLoc());5049 if (!ATReg)5050 return true;5051 5052 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);5053 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);5054 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);5055 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);5056 5057 return false;5058 }5059 5060 return true;5061}5062 5063bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,5064 MCStreamer &Out,5065 const MCSubtargetInfo *STI) {5066 MipsTargetStreamer &TOut = getTargetStreamer();5067 MCRegister ATReg;5068 MCRegister DReg = Inst.getOperand(0).getReg();5069 MCRegister SReg = Inst.getOperand(1).getReg();5070 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;5071 5072 unsigned FirstShift = Mips::NOP;5073 unsigned SecondShift = Mips::NOP;5074 5075 MCInst TmpInst;5076 5077 if (hasMips64r2()) {5078 unsigned FinalOpcode = Mips::NOP;5079 if (ImmValue == 0)5080 FinalOpcode = Mips::DROTR;5081 else if (ImmValue % 32 == 0)5082 FinalOpcode = Mips::DROTR32;5083 else if ((ImmValue >= 1) && (ImmValue <= 32)) {5084 if (Inst.getOpcode() == Mips::DROLImm)5085 FinalOpcode = Mips::DROTR32;5086 else5087 FinalOpcode = Mips::DROTR;5088 } else if (ImmValue >= 33) {5089 if (Inst.getOpcode() == Mips::DROLImm)5090 FinalOpcode = Mips::DROTR;5091 else5092 FinalOpcode = Mips::DROTR32;5093 }5094 5095 uint64_t ShiftValue = ImmValue % 32;5096 if (Inst.getOpcode() == Mips::DROLImm)5097 ShiftValue = (32 - ImmValue % 32) % 32;5098 5099 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);5100 5101 return false;5102 }5103 5104 if (hasMips64()) {5105 if (ImmValue == 0) {5106 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);5107 return false;5108 }5109 5110 switch (Inst.getOpcode()) {5111 default:5112 llvm_unreachable("unexpected instruction opcode");5113 case Mips::DROLImm:5114 if ((ImmValue >= 1) && (ImmValue <= 31)) {5115 FirstShift = Mips::DSLL;5116 SecondShift = Mips::DSRL32;5117 }5118 if (ImmValue == 32) {5119 FirstShift = Mips::DSLL32;5120 SecondShift = Mips::DSRL32;5121 }5122 if ((ImmValue >= 33) && (ImmValue <= 63)) {5123 FirstShift = Mips::DSLL32;5124 SecondShift = Mips::DSRL;5125 }5126 break;5127 case Mips::DRORImm:5128 if ((ImmValue >= 1) && (ImmValue <= 31)) {5129 FirstShift = Mips::DSRL;5130 SecondShift = Mips::DSLL32;5131 }5132 if (ImmValue == 32) {5133 FirstShift = Mips::DSRL32;5134 SecondShift = Mips::DSLL32;5135 }5136 if ((ImmValue >= 33) && (ImmValue <= 63)) {5137 FirstShift = Mips::DSRL32;5138 SecondShift = Mips::DSLL;5139 }5140 break;5141 }5142 5143 ATReg = getATReg(Inst.getLoc());5144 if (!ATReg)5145 return true;5146 5147 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);5148 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,5149 Inst.getLoc(), STI);5150 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);5151 5152 return false;5153 }5154 5155 return true;5156}5157 5158bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,5159 const MCSubtargetInfo *STI) {5160 MipsTargetStreamer &TOut = getTargetStreamer();5161 MCRegister FirstRegOp = Inst.getOperand(0).getReg();5162 MCRegister SecondRegOp = Inst.getOperand(1).getReg();5163 5164 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);5165 if (FirstRegOp != SecondRegOp)5166 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);5167 else5168 TOut.emitEmptyDelaySlot(false, IDLoc, STI);5169 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);5170 5171 return false;5172}5173 5174bool MipsAsmParser::expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,5175 const MCSubtargetInfo *STI) {5176 MipsTargetStreamer &TOut = getTargetStreamer();5177 MCRegister ATReg;5178 MCRegister DstReg = Inst.getOperand(0).getReg();5179 MCRegister SrcReg = Inst.getOperand(1).getReg();5180 int32_t ImmValue = Inst.getOperand(2).getImm();5181 5182 ATReg = getATReg(IDLoc);5183 if (!ATReg)5184 return true;5185 5186 loadImmediate(ImmValue, ATReg, MCRegister(), true, false, IDLoc, Out, STI);5187 5188 TOut.emitRR(Inst.getOpcode() == Mips::MULImmMacro ? Mips::MULT : Mips::DMULT,5189 SrcReg, ATReg, IDLoc, STI);5190 5191 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);5192 5193 return false;5194}5195 5196bool MipsAsmParser::expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,5197 const MCSubtargetInfo *STI) {5198 MipsTargetStreamer &TOut = getTargetStreamer();5199 MCRegister ATReg;5200 MCRegister DstReg = Inst.getOperand(0).getReg();5201 MCRegister SrcReg = Inst.getOperand(1).getReg();5202 MCRegister TmpReg = Inst.getOperand(2).getReg();5203 5204 ATReg = getATReg(Inst.getLoc());5205 if (!ATReg)5206 return true;5207 5208 TOut.emitRR(Inst.getOpcode() == Mips::MULOMacro ? Mips::MULT : Mips::DMULT,5209 SrcReg, TmpReg, IDLoc, STI);5210 5211 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);5212 5213 TOut.emitRRI(Inst.getOpcode() == Mips::MULOMacro ? Mips::SRA : Mips::DSRA32,5214 DstReg, DstReg, 0x1F, IDLoc, STI);5215 5216 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);5217 5218 if (useTraps()) {5219 TOut.emitRRI(Mips::TNE, DstReg, ATReg, 6, IDLoc, STI);5220 } else {5221 MCContext &Context = TOut.getContext();5222 MCSymbol * BrTarget = Context.createTempSymbol();5223 MCOperand LabelOp =5224 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));5225 5226 TOut.emitRRX(Mips::BEQ, DstReg, ATReg, LabelOp, IDLoc, STI);5227 if (AssemblerOptions.back()->isReorder())5228 TOut.emitNop(IDLoc, STI);5229 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);5230 5231 TOut.getStreamer().emitLabel(BrTarget);5232 }5233 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);5234 5235 return false;5236}5237 5238bool MipsAsmParser::expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,5239 const MCSubtargetInfo *STI) {5240 MipsTargetStreamer &TOut = getTargetStreamer();5241 MCRegister ATReg;5242 MCRegister DstReg = Inst.getOperand(0).getReg();5243 MCRegister SrcReg = Inst.getOperand(1).getReg();5244 MCRegister TmpReg = Inst.getOperand(2).getReg();5245 5246 ATReg = getATReg(IDLoc);5247 if (!ATReg)5248 return true;5249 5250 TOut.emitRR(Inst.getOpcode() == Mips::MULOUMacro ? Mips::MULTu : Mips::DMULTu,5251 SrcReg, TmpReg, IDLoc, STI);5252 5253 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);5254 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);5255 if (useTraps()) {5256 TOut.emitRRI(Mips::TNE, ATReg, Mips::ZERO, 6, IDLoc, STI);5257 } else {5258 MCContext &Context = TOut.getContext();5259 MCSymbol * BrTarget = Context.createTempSymbol();5260 MCOperand LabelOp =5261 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));5262 5263 TOut.emitRRX(Mips::BEQ, ATReg, Mips::ZERO, LabelOp, IDLoc, STI);5264 if (AssemblerOptions.back()->isReorder())5265 TOut.emitNop(IDLoc, STI);5266 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);5267 5268 TOut.getStreamer().emitLabel(BrTarget);5269 }5270 5271 return false;5272}5273 5274bool MipsAsmParser::expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,5275 const MCSubtargetInfo *STI) {5276 MipsTargetStreamer &TOut = getTargetStreamer();5277 MCRegister DstReg = Inst.getOperand(0).getReg();5278 MCRegister SrcReg = Inst.getOperand(1).getReg();5279 MCRegister TmpReg = Inst.getOperand(2).getReg();5280 5281 TOut.emitRR(Mips::DMULTu, SrcReg, TmpReg, IDLoc, STI);5282 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);5283 5284 return false;5285}5286 5287// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);5288// lw $<reg+1>>, offset+4($reg2)'5289// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);5290// sw $<reg+1>>, offset+4($reg2)'5291// for O32.5292bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc,5293 MCStreamer &Out,5294 const MCSubtargetInfo *STI,5295 bool IsLoad) {5296 if (!isABI_O32())5297 return true;5298 5299 warnIfNoMacro(IDLoc);5300 5301 MipsTargetStreamer &TOut = getTargetStreamer();5302 unsigned Opcode = IsLoad ? Mips::LW : Mips::SW;5303 MCRegister FirstReg = Inst.getOperand(0).getReg();5304 MCRegister SecondReg = nextReg(FirstReg);5305 MCRegister BaseReg = Inst.getOperand(1).getReg();5306 if (!SecondReg)5307 return true;5308 5309 warnIfRegIndexIsAT(FirstReg, IDLoc);5310 5311 assert(Inst.getOperand(2).isImm() &&5312 "Offset for load macro is not immediate!");5313 5314 MCOperand &FirstOffset = Inst.getOperand(2);5315 signed NextOffset = FirstOffset.getImm() + 4;5316 MCOperand SecondOffset = MCOperand::createImm(NextOffset);5317 5318 if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))5319 return true;5320 5321 // For loads, clobber the base register with the second load instead of the5322 // first if the BaseReg == FirstReg.5323 if (FirstReg != BaseReg || !IsLoad) {5324 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);5325 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);5326 } else {5327 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);5328 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);5329 }5330 5331 return false;5332}5333 5334 5335// Expand 's.d $<reg> offset($reg2)' to 'swc1 $<reg+1>, offset($reg2);5336// swc1 $<reg>, offset+4($reg2)'5337// or if little endian to 'swc1 $<reg>, offset($reg2);5338// swc1 $<reg+1>, offset+4($reg2)'5339// for Mips1.5340bool MipsAsmParser::expandStoreDM1Macro(MCInst &Inst, SMLoc IDLoc,5341 MCStreamer &Out,5342 const MCSubtargetInfo *STI) {5343 if (!isABI_O32())5344 return true;5345 5346 warnIfNoMacro(IDLoc);5347 5348 MipsTargetStreamer &TOut = getTargetStreamer();5349 unsigned Opcode = Mips::SWC1;5350 MCRegister FirstReg = Inst.getOperand(0).getReg();5351 MCRegister SecondReg = nextReg(FirstReg);5352 MCRegister BaseReg = Inst.getOperand(1).getReg();5353 if (!SecondReg)5354 return true;5355 5356 warnIfRegIndexIsAT(FirstReg, IDLoc);5357 5358 assert(Inst.getOperand(2).isImm() &&5359 "Offset for macro is not immediate!");5360 5361 MCOperand &FirstOffset = Inst.getOperand(2);5362 signed NextOffset = FirstOffset.getImm() + 4;5363 MCOperand SecondOffset = MCOperand::createImm(NextOffset);5364 5365 if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))5366 return true;5367 5368 if (!IsLittleEndian)5369 std::swap(FirstReg, SecondReg);5370 5371 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);5372 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);5373 5374 return false;5375}5376 5377bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,5378 const MCSubtargetInfo *STI) {5379 MipsTargetStreamer &TOut = getTargetStreamer();5380 5381 assert(Inst.getNumOperands() == 3 && "Invalid operand count");5382 assert(Inst.getOperand(0).isReg() &&5383 Inst.getOperand(1).isReg() &&5384 Inst.getOperand(2).isReg() && "Invalid instruction operand.");5385 5386 MCRegister DstReg = Inst.getOperand(0).getReg();5387 MCRegister SrcReg = Inst.getOperand(1).getReg();5388 MCRegister OpReg = Inst.getOperand(2).getReg();5389 5390 warnIfNoMacro(IDLoc);5391 5392 if (SrcReg != Mips::ZERO && OpReg != Mips::ZERO) {5393 TOut.emitRRR(Mips::XOR, DstReg, SrcReg, OpReg, IDLoc, STI);5394 TOut.emitRRI(Mips::SLTiu, DstReg, DstReg, 1, IDLoc, STI);5395 return false;5396 }5397 5398 MCRegister Reg = SrcReg == Mips::ZERO ? OpReg : SrcReg;5399 TOut.emitRRI(Mips::SLTiu, DstReg, Reg, 1, IDLoc, STI);5400 return false;5401}5402 5403bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,5404 const MCSubtargetInfo *STI) {5405 MipsTargetStreamer &TOut = getTargetStreamer();5406 5407 assert(Inst.getNumOperands() == 3 && "Invalid operand count");5408 assert(Inst.getOperand(0).isReg() &&5409 Inst.getOperand(1).isReg() &&5410 Inst.getOperand(2).isImm() && "Invalid instruction operand.");5411 5412 MCRegister DstReg = Inst.getOperand(0).getReg();5413 MCRegister SrcReg = Inst.getOperand(1).getReg();5414 int64_t Imm = Inst.getOperand(2).getImm();5415 5416 warnIfNoMacro(IDLoc);5417 5418 if (Imm == 0) {5419 TOut.emitRRI(Mips::SLTiu, DstReg, SrcReg, 1, IDLoc, STI);5420 return false;5421 }5422 5423 if (SrcReg == Mips::ZERO) {5424 Warning(IDLoc, "comparison is always false");5425 TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu,5426 DstReg, SrcReg, SrcReg, IDLoc, STI);5427 return false;5428 }5429 5430 unsigned Opc;5431 if (Imm > -0x8000 && Imm < 0) {5432 Imm = -Imm;5433 Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;5434 } else {5435 Opc = Mips::XORi;5436 }5437 5438 if (!isUInt<16>(Imm)) {5439 MCRegister ATReg = getATReg(IDLoc);5440 if (!ATReg)5441 return true;5442 5443 if (loadImmediate(Imm, ATReg, MCRegister(), true, isGP64bit(), IDLoc, Out,5444 STI))5445 return true;5446 5447 TOut.emitRRR(Mips::XOR, DstReg, SrcReg, ATReg, IDLoc, STI);5448 TOut.emitRRI(Mips::SLTiu, DstReg, DstReg, 1, IDLoc, STI);5449 return false;5450 }5451 5452 TOut.emitRRI(Opc, DstReg, SrcReg, Imm, IDLoc, STI);5453 TOut.emitRRI(Mips::SLTiu, DstReg, DstReg, 1, IDLoc, STI);5454 return false;5455}5456 5457bool MipsAsmParser::expandSne(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,5458 const MCSubtargetInfo *STI) {5459 5460 MipsTargetStreamer &TOut = getTargetStreamer();5461 5462 assert(Inst.getNumOperands() == 3 && "Invalid operand count");5463 assert(Inst.getOperand(0).isReg() &&5464 Inst.getOperand(1).isReg() &&5465 Inst.getOperand(2).isReg() && "Invalid instruction operand.");5466 5467 MCRegister DstReg = Inst.getOperand(0).getReg();5468 MCRegister SrcReg = Inst.getOperand(1).getReg();5469 MCRegister OpReg = Inst.getOperand(2).getReg();5470 5471 warnIfNoMacro(IDLoc);5472 5473 if (SrcReg != Mips::ZERO && OpReg != Mips::ZERO) {5474 TOut.emitRRR(Mips::XOR, DstReg, SrcReg, OpReg, IDLoc, STI);5475 TOut.emitRRR(Mips::SLTu, DstReg, Mips::ZERO, DstReg, IDLoc, STI);5476 return false;5477 }5478 5479 MCRegister Reg = SrcReg == Mips::ZERO ? OpReg : SrcReg;5480 TOut.emitRRR(Mips::SLTu, DstReg, Mips::ZERO, Reg, IDLoc, STI);5481 return false;5482}5483 5484bool MipsAsmParser::expandSneI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,5485 const MCSubtargetInfo *STI) {5486 MipsTargetStreamer &TOut = getTargetStreamer();5487 5488 assert(Inst.getNumOperands() == 3 && "Invalid operand count");5489 assert(Inst.getOperand(0).isReg() &&5490 Inst.getOperand(1).isReg() &&5491 Inst.getOperand(2).isImm() && "Invalid instruction operand.");5492 5493 MCRegister DstReg = Inst.getOperand(0).getReg();5494 MCRegister SrcReg = Inst.getOperand(1).getReg();5495 int64_t ImmValue = Inst.getOperand(2).getImm();5496 5497 warnIfNoMacro(IDLoc);5498 5499 if (ImmValue == 0) {5500 TOut.emitRRR(Mips::SLTu, DstReg, Mips::ZERO, SrcReg, IDLoc, STI);5501 return false;5502 }5503 5504 if (SrcReg == Mips::ZERO) {5505 Warning(IDLoc, "comparison is always true");5506 if (loadImmediate(1, DstReg, MCRegister(), true, false, IDLoc, Out, STI))5507 return true;5508 return false;5509 }5510 5511 unsigned Opc;5512 if (ImmValue > -0x8000 && ImmValue < 0) {5513 ImmValue = -ImmValue;5514 Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;5515 } else {5516 Opc = Mips::XORi;5517 }5518 5519 if (isUInt<16>(ImmValue)) {5520 TOut.emitRRI(Opc, DstReg, SrcReg, ImmValue, IDLoc, STI);5521 TOut.emitRRR(Mips::SLTu, DstReg, Mips::ZERO, DstReg, IDLoc, STI);5522 return false;5523 }5524 5525 MCRegister ATReg = getATReg(IDLoc);5526 if (!ATReg)5527 return true;5528 5529 if (loadImmediate(ImmValue, ATReg, MCRegister(), isInt<32>(ImmValue), false,5530 IDLoc, Out, STI))5531 return true;5532 5533 TOut.emitRRR(Mips::XOR, DstReg, SrcReg, ATReg, IDLoc, STI);5534 TOut.emitRRR(Mips::SLTu, DstReg, Mips::ZERO, DstReg, IDLoc, STI);5535 return false;5536}5537 5538// Map the DSP accumulator and control register to the corresponding gpr5539// operand. Unlike the other alias, the m(f|t)t(lo|hi|acx) instructions5540// do not map the DSP registers contigously to gpr registers.5541static unsigned getRegisterForMxtrDSP(MCInst &Inst, bool IsMFDSP) {5542 switch (Inst.getOpcode()) {5543 case Mips::MFTLO:5544 case Mips::MTTLO:5545 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg().id()) {5546 case Mips::AC0:5547 return Mips::ZERO;5548 case Mips::AC1:5549 return Mips::A0;5550 case Mips::AC2:5551 return Mips::T0;5552 case Mips::AC3:5553 return Mips::T4;5554 default:5555 llvm_unreachable("Unknown register for 'mttr' alias!");5556 }5557 case Mips::MFTHI:5558 case Mips::MTTHI:5559 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg().id()) {5560 case Mips::AC0:5561 return Mips::AT;5562 case Mips::AC1:5563 return Mips::A1;5564 case Mips::AC2:5565 return Mips::T1;5566 case Mips::AC3:5567 return Mips::T5;5568 default:5569 llvm_unreachable("Unknown register for 'mttr' alias!");5570 }5571 case Mips::MFTACX:5572 case Mips::MTTACX:5573 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg().id()) {5574 case Mips::AC0:5575 return Mips::V0;5576 case Mips::AC1:5577 return Mips::A2;5578 case Mips::AC2:5579 return Mips::T2;5580 case Mips::AC3:5581 return Mips::T6;5582 default:5583 llvm_unreachable("Unknown register for 'mttr' alias!");5584 }5585 case Mips::MFTDSP:5586 case Mips::MTTDSP:5587 return Mips::S0;5588 default:5589 llvm_unreachable("Unknown instruction for 'mttr' dsp alias!");5590 }5591}5592 5593// Map the floating point register operand to the corresponding register5594// operand.5595static unsigned getRegisterForMxtrFP(MCInst &Inst, bool IsMFTC1) {5596 switch (Inst.getOperand(IsMFTC1 ? 1 : 0).getReg().id()) {5597 case Mips::F0: return Mips::ZERO;5598 case Mips::F1: return Mips::AT;5599 case Mips::F2: return Mips::V0;5600 case Mips::F3: return Mips::V1;5601 case Mips::F4: return Mips::A0;5602 case Mips::F5: return Mips::A1;5603 case Mips::F6: return Mips::A2;5604 case Mips::F7: return Mips::A3;5605 case Mips::F8: return Mips::T0;5606 case Mips::F9: return Mips::T1;5607 case Mips::F10: return Mips::T2;5608 case Mips::F11: return Mips::T3;5609 case Mips::F12: return Mips::T4;5610 case Mips::F13: return Mips::T5;5611 case Mips::F14: return Mips::T6;5612 case Mips::F15: return Mips::T7;5613 case Mips::F16: return Mips::S0;5614 case Mips::F17: return Mips::S1;5615 case Mips::F18: return Mips::S2;5616 case Mips::F19: return Mips::S3;5617 case Mips::F20: return Mips::S4;5618 case Mips::F21: return Mips::S5;5619 case Mips::F22: return Mips::S6;5620 case Mips::F23: return Mips::S7;5621 case Mips::F24: return Mips::T8;5622 case Mips::F25: return Mips::T9;5623 case Mips::F26: return Mips::K0;5624 case Mips::F27: return Mips::K1;5625 case Mips::F28: return Mips::GP;5626 case Mips::F29: return Mips::SP;5627 case Mips::F30: return Mips::FP;5628 case Mips::F31: return Mips::RA;5629 default: llvm_unreachable("Unknown register for mttc1 alias!");5630 }5631}5632 5633// Map the coprocessor operand the corresponding gpr register operand.5634static unsigned getRegisterForMxtrC0(MCInst &Inst, bool IsMFTC0) {5635 switch (Inst.getOperand(IsMFTC0 ? 1 : 0).getReg().id()) {5636 case Mips::COP00: return Mips::ZERO;5637 case Mips::COP01: return Mips::AT;5638 case Mips::COP02: return Mips::V0;5639 case Mips::COP03: return Mips::V1;5640 case Mips::COP04: return Mips::A0;5641 case Mips::COP05: return Mips::A1;5642 case Mips::COP06: return Mips::A2;5643 case Mips::COP07: return Mips::A3;5644 case Mips::COP08: return Mips::T0;5645 case Mips::COP09: return Mips::T1;5646 case Mips::COP010: return Mips::T2;5647 case Mips::COP011: return Mips::T3;5648 case Mips::COP012: return Mips::T4;5649 case Mips::COP013: return Mips::T5;5650 case Mips::COP014: return Mips::T6;5651 case Mips::COP015: return Mips::T7;5652 case Mips::COP016: return Mips::S0;5653 case Mips::COP017: return Mips::S1;5654 case Mips::COP018: return Mips::S2;5655 case Mips::COP019: return Mips::S3;5656 case Mips::COP020: return Mips::S4;5657 case Mips::COP021: return Mips::S5;5658 case Mips::COP022: return Mips::S6;5659 case Mips::COP023: return Mips::S7;5660 case Mips::COP024: return Mips::T8;5661 case Mips::COP025: return Mips::T9;5662 case Mips::COP026: return Mips::K0;5663 case Mips::COP027: return Mips::K1;5664 case Mips::COP028: return Mips::GP;5665 case Mips::COP029: return Mips::SP;5666 case Mips::COP030: return Mips::FP;5667 case Mips::COP031: return Mips::RA;5668 default: llvm_unreachable("Unknown register for mttc0 alias!");5669 }5670}5671 5672/// Expand an alias of 'mftr' or 'mttr' into the full instruction, by producing5673/// an mftr or mttr with the correctly mapped gpr register, u, sel and h bits.5674bool MipsAsmParser::expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,5675 const MCSubtargetInfo *STI) {5676 MipsTargetStreamer &TOut = getTargetStreamer();5677 MCRegister rd;5678 unsigned u = 1;5679 unsigned sel = 0;5680 unsigned h = 0;5681 bool IsMFTR = false;5682 switch (Inst.getOpcode()) {5683 case Mips::MFTC0:5684 IsMFTR = true;5685 [[fallthrough]];5686 case Mips::MTTC0:5687 u = 0;5688 rd = getRegisterForMxtrC0(Inst, IsMFTR);5689 sel = Inst.getOperand(2).getImm();5690 break;5691 case Mips::MFTGPR:5692 IsMFTR = true;5693 [[fallthrough]];5694 case Mips::MTTGPR:5695 rd = Inst.getOperand(IsMFTR ? 1 : 0).getReg();5696 break;5697 case Mips::MFTLO:5698 case Mips::MFTHI:5699 case Mips::MFTACX:5700 case Mips::MFTDSP:5701 IsMFTR = true;5702 [[fallthrough]];5703 case Mips::MTTLO:5704 case Mips::MTTHI:5705 case Mips::MTTACX:5706 case Mips::MTTDSP:5707 rd = getRegisterForMxtrDSP(Inst, IsMFTR);5708 sel = 1;5709 break;5710 case Mips::MFTHC1:5711 h = 1;5712 [[fallthrough]];5713 case Mips::MFTC1:5714 IsMFTR = true;5715 rd = getRegisterForMxtrFP(Inst, IsMFTR);5716 sel = 2;5717 break;5718 case Mips::MTTHC1:5719 h = 1;5720 [[fallthrough]];5721 case Mips::MTTC1:5722 rd = getRegisterForMxtrFP(Inst, IsMFTR);5723 sel = 2;5724 break;5725 case Mips::CFTC1:5726 IsMFTR = true;5727 [[fallthrough]];5728 case Mips::CTTC1:5729 rd = getRegisterForMxtrFP(Inst, IsMFTR);5730 sel = 3;5731 break;5732 }5733 MCRegister Op0 = IsMFTR ? Inst.getOperand(0).getReg() : MCRegister(rd);5734 MCRegister Op1 =5735 IsMFTR ? MCRegister(rd)5736 : (Inst.getOpcode() != Mips::MTTDSP ? Inst.getOperand(1).getReg()5737 : Inst.getOperand(0).getReg());5738 5739 TOut.emitRRIII(IsMFTR ? Mips::MFTR : Mips::MTTR, Op0, Op1, u, sel, h, IDLoc,5740 STI);5741 return false;5742}5743 5744bool MipsAsmParser::expandSaaAddr(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,5745 const MCSubtargetInfo *STI) {5746 assert(Inst.getNumOperands() == 3 && "expected three operands");5747 assert(Inst.getOperand(0).isReg() && "expected register operand kind");5748 assert(Inst.getOperand(1).isReg() && "expected register operand kind");5749 5750 warnIfNoMacro(IDLoc);5751 5752 MipsTargetStreamer &TOut = getTargetStreamer();5753 unsigned Opcode = Inst.getOpcode() == Mips::SaaAddr ? Mips::SAA : Mips::SAAD;5754 MCRegister RtReg = Inst.getOperand(0).getReg();5755 MCRegister BaseReg = Inst.getOperand(1).getReg();5756 const MCOperand &BaseOp = Inst.getOperand(2);5757 5758 if (BaseOp.isImm()) {5759 int64_t ImmValue = BaseOp.getImm();5760 if (ImmValue == 0) {5761 TOut.emitRR(Opcode, RtReg, BaseReg, IDLoc, STI);5762 return false;5763 }5764 }5765 5766 MCRegister ATReg = getATReg(IDLoc);5767 if (!ATReg)5768 return true;5769 5770 if (expandLoadAddress(ATReg, BaseReg, BaseOp, !isGP64bit(), IDLoc, Out, STI))5771 return true;5772 5773 TOut.emitRR(Opcode, RtReg, ATReg, IDLoc, STI);5774 return false;5775}5776 5777unsigned5778MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,5779 const OperandVector &Operands) {5780 switch (Inst.getOpcode()) {5781 default:5782 return Match_Success;5783 case Mips::DATI:5784 case Mips::DAHI:5785 if (static_cast<MipsOperand &>(*Operands[1])5786 .isValidForTie(static_cast<MipsOperand &>(*Operands[2])))5787 return Match_Success;5788 return Match_RequiresSameSrcAndDst;5789 }5790}5791 5792unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {5793 switch (Inst.getOpcode()) {5794 // As described by the MIPSR6 spec, daui must not use the zero operand for5795 // its source operand.5796 case Mips::DAUI:5797 if (Inst.getOperand(1).getReg() == Mips::ZERO ||5798 Inst.getOperand(1).getReg() == Mips::ZERO_64)5799 return Match_RequiresNoZeroRegister;5800 return Match_Success;5801 // As described by the Mips32r2 spec, the registers Rd and Rs for5802 // jalr.hb must be different.5803 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction5804 // and registers Rd and Base for microMIPS lwp instruction5805 case Mips::JALR_HB:5806 case Mips::JALR_HB64:5807 case Mips::JALRC_HB_MMR6:5808 case Mips::JALRC_MMR6:5809 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())5810 return Match_RequiresDifferentSrcAndDst;5811 return Match_Success;5812 case Mips::LWP_MM:5813 if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())5814 return Match_RequiresDifferentSrcAndDst;5815 return Match_Success;5816 case Mips::SYNC:5817 if (Inst.getOperand(0).getImm() != 0 && !hasMips32())5818 return Match_NonZeroOperandForSync;5819 return Match_Success;5820 case Mips::MFC0:5821 case Mips::MTC0:5822 case Mips::MTC2:5823 case Mips::MFC2:5824 if (Inst.getOperand(2).getImm() != 0 && !hasMips32())5825 return Match_NonZeroOperandForMTCX;5826 return Match_Success;5827 // As described the MIPSR6 spec, the compact branches that compare registers5828 // must:5829 // a) Not use the zero register.5830 // b) Not use the same register twice.5831 // c) rs < rt for bnec, beqc.5832 // NB: For this case, the encoding will swap the operands as their5833 // ordering doesn't matter. GAS performs this transformation too.5834 // Hence, that constraint does not have to be enforced.5835 //5836 // The compact branches that branch iff the signed addition of two registers5837 // would overflow must have rs >= rt. That can be handled like beqc/bnec with5838 // operand swapping. They do not have restriction of using the zero register.5839 case Mips::BLEZC: case Mips::BLEZC_MMR6:5840 case Mips::BGEZC: case Mips::BGEZC_MMR6:5841 case Mips::BGTZC: case Mips::BGTZC_MMR6:5842 case Mips::BLTZC: case Mips::BLTZC_MMR6:5843 case Mips::BEQZC: case Mips::BEQZC_MMR6:5844 case Mips::BNEZC: case Mips::BNEZC_MMR6:5845 case Mips::BLEZC64:5846 case Mips::BGEZC64:5847 case Mips::BGTZC64:5848 case Mips::BLTZC64:5849 case Mips::BEQZC64:5850 case Mips::BNEZC64:5851 if (Inst.getOperand(0).getReg() == Mips::ZERO ||5852 Inst.getOperand(0).getReg() == Mips::ZERO_64)5853 return Match_RequiresNoZeroRegister;5854 return Match_Success;5855 case Mips::BGEC: case Mips::BGEC_MMR6:5856 case Mips::BLTC: case Mips::BLTC_MMR6:5857 case Mips::BGEUC: case Mips::BGEUC_MMR6:5858 case Mips::BLTUC: case Mips::BLTUC_MMR6:5859 case Mips::BEQC: case Mips::BEQC_MMR6:5860 case Mips::BNEC: case Mips::BNEC_MMR6:5861 case Mips::BGEC64:5862 case Mips::BLTC64:5863 case Mips::BGEUC64:5864 case Mips::BLTUC64:5865 case Mips::BEQC64:5866 case Mips::BNEC64:5867 if (Inst.getOperand(0).getReg() == Mips::ZERO ||5868 Inst.getOperand(0).getReg() == Mips::ZERO_64)5869 return Match_RequiresNoZeroRegister;5870 if (Inst.getOperand(1).getReg() == Mips::ZERO ||5871 Inst.getOperand(1).getReg() == Mips::ZERO_64)5872 return Match_RequiresNoZeroRegister;5873 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())5874 return Match_RequiresDifferentOperands;5875 return Match_Success;5876 case Mips::DINS: {5877 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&5878 "Operands must be immediates for dins!");5879 const signed Pos = Inst.getOperand(2).getImm();5880 const signed Size = Inst.getOperand(3).getImm();5881 if ((0 > (Pos + Size)) || ((Pos + Size) > 32))5882 return Match_RequiresPosSizeRange0_32;5883 return Match_Success;5884 }5885 case Mips::DINSM:5886 case Mips::DINSU: {5887 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&5888 "Operands must be immediates for dinsm/dinsu!");5889 const signed Pos = Inst.getOperand(2).getImm();5890 const signed Size = Inst.getOperand(3).getImm();5891 if ((32 >= (Pos + Size)) || ((Pos + Size) > 64))5892 return Match_RequiresPosSizeRange33_64;5893 return Match_Success;5894 }5895 case Mips::DEXT: {5896 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&5897 "Operands must be immediates for DEXTM!");5898 const signed Pos = Inst.getOperand(2).getImm();5899 const signed Size = Inst.getOperand(3).getImm();5900 if ((1 > (Pos + Size)) || ((Pos + Size) > 63))5901 return Match_RequiresPosSizeUImm6;5902 return Match_Success;5903 }5904 case Mips::DEXTM:5905 case Mips::DEXTU: {5906 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&5907 "Operands must be immediates for dextm/dextu!");5908 const signed Pos = Inst.getOperand(2).getImm();5909 const signed Size = Inst.getOperand(3).getImm();5910 if ((32 > (Pos + Size)) || ((Pos + Size) > 64))5911 return Match_RequiresPosSizeRange33_64;5912 return Match_Success;5913 }5914 case Mips::CRC32B: case Mips::CRC32CB:5915 case Mips::CRC32H: case Mips::CRC32CH:5916 case Mips::CRC32W: case Mips::CRC32CW:5917 case Mips::CRC32D: case Mips::CRC32CD:5918 if (Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg())5919 return Match_RequiresSameSrcAndDst;5920 return Match_Success;5921 }5922 5923 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags;5924 if ((TSFlags & MipsII::HasFCCRegOperand) &&5925 (Inst.getOperand(0).getReg() != Mips::FCC0) && !hasEightFccRegisters())5926 return Match_NoFCCRegisterForCurrentISA;5927 5928 return Match_Success;5929 5930}5931 5932static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,5933 uint64_t ErrorInfo) {5934 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {5935 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();5936 if (ErrorLoc == SMLoc())5937 return Loc;5938 return ErrorLoc;5939 }5940 return Loc;5941}5942 5943bool MipsAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,5944 OperandVector &Operands,5945 MCStreamer &Out,5946 uint64_t &ErrorInfo,5947 bool MatchingInlineAsm) {5948 MCInst Inst;5949 unsigned MatchResult =5950 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);5951 5952 switch (MatchResult) {5953 case Match_Success:5954 if (processInstruction(Inst, IDLoc, Out, STI))5955 return true;5956 return false;5957 case Match_MissingFeature:5958 Error(IDLoc, "instruction requires a CPU feature not currently enabled");5959 return true;5960 case Match_InvalidTiedOperand:5961 Error(IDLoc, "operand must match destination register");5962 return true;5963 case Match_InvalidOperand: {5964 SMLoc ErrorLoc = IDLoc;5965 if (ErrorInfo != ~0ULL) {5966 if (ErrorInfo >= Operands.size())5967 return Error(IDLoc, "too few operands for instruction");5968 5969 ErrorLoc = Operands[ErrorInfo]->getStartLoc();5970 if (ErrorLoc == SMLoc())5971 ErrorLoc = IDLoc;5972 }5973 5974 return Error(ErrorLoc, "invalid operand for instruction");5975 }5976 case Match_NonZeroOperandForSync:5977 return Error(IDLoc,5978 "s-type must be zero or unspecified for pre-MIPS32 ISAs");5979 case Match_NonZeroOperandForMTCX:5980 return Error(IDLoc, "selector must be zero for pre-MIPS32 ISAs");5981 case Match_MnemonicFail:5982 return Error(IDLoc, "invalid instruction");5983 case Match_RequiresDifferentSrcAndDst:5984 return Error(IDLoc, "source and destination must be different");5985 case Match_RequiresDifferentOperands:5986 return Error(IDLoc, "registers must be different");5987 case Match_RequiresNoZeroRegister:5988 return Error(IDLoc, "invalid operand ($zero) for instruction");5989 case Match_RequiresSameSrcAndDst:5990 return Error(IDLoc, "source and destination must match");5991 case Match_NoFCCRegisterForCurrentISA:5992 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),5993 "non-zero fcc register doesn't exist in current ISA level");5994 case Match_Immz:5995 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");5996 case Match_UImm1_0:5997 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),5998 "expected 1-bit unsigned immediate");5999 case Match_UImm2_0:6000 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6001 "expected 2-bit unsigned immediate");6002 case Match_UImm2_1:6003 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6004 "expected immediate in range 1 .. 4");6005 case Match_UImm3_0:6006 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6007 "expected 3-bit unsigned immediate");6008 case Match_UImm4_0:6009 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6010 "expected 4-bit unsigned immediate");6011 case Match_SImm4_0:6012 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6013 "expected 4-bit signed immediate");6014 case Match_UImm5_0:6015 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6016 "expected 5-bit unsigned immediate");6017 case Match_SImm5_0:6018 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6019 "expected 5-bit signed immediate");6020 case Match_UImm5_1:6021 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6022 "expected immediate in range 1 .. 32");6023 case Match_UImm5_32:6024 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6025 "expected immediate in range 32 .. 63");6026 case Match_UImm5_33:6027 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6028 "expected immediate in range 33 .. 64");6029 case Match_UImm5_0_Report_UImm6:6030 // This is used on UImm5 operands that have a corresponding UImm5_326031 // operand to avoid confusing the user.6032 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6033 "expected 6-bit unsigned immediate");6034 case Match_UImm5_Lsl2:6035 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6036 "expected both 7-bit unsigned immediate and multiple of 4");6037 case Match_UImmRange2_64:6038 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6039 "expected immediate in range 2 .. 64");6040 case Match_UImm6_0:6041 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6042 "expected 6-bit unsigned immediate");6043 case Match_UImm6_Lsl2:6044 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6045 "expected both 8-bit unsigned immediate and multiple of 4");6046 case Match_SImm6_0:6047 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6048 "expected 6-bit signed immediate");6049 case Match_UImm7_0:6050 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6051 "expected 7-bit unsigned immediate");6052 case Match_UImm7_N1:6053 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6054 "expected immediate in range -1 .. 126");6055 case Match_SImm7_Lsl2:6056 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6057 "expected both 9-bit signed immediate and multiple of 4");6058 case Match_UImm8_0:6059 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6060 "expected 8-bit unsigned immediate");6061 case Match_UImm10_0:6062 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6063 "expected 10-bit unsigned immediate");6064 case Match_SImm10_0:6065 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6066 "expected 10-bit signed immediate");6067 case Match_SImm11_0:6068 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6069 "expected 11-bit signed immediate");6070 case Match_UImm16:6071 case Match_UImm16_Relaxed:6072 case Match_UImm16_AltRelaxed:6073 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6074 "expected 16-bit unsigned immediate");6075 case Match_SImm16:6076 case Match_SImm16_Relaxed:6077 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6078 "expected 16-bit signed immediate");6079 case Match_SImm19_Lsl2:6080 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6081 "expected both 19-bit signed immediate and multiple of 4");6082 case Match_UImm20_0:6083 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6084 "expected 20-bit unsigned immediate");6085 case Match_UImm26_0:6086 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6087 "expected 26-bit unsigned immediate");6088 case Match_SImm32:6089 case Match_SImm32_Relaxed:6090 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6091 "expected 32-bit signed immediate");6092 case Match_UImm32_Coerced:6093 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6094 "expected 32-bit immediate");6095 case Match_MemSImm9:6096 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6097 "expected memory with 9-bit signed offset");6098 case Match_MemSImm10:6099 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6100 "expected memory with 10-bit signed offset");6101 case Match_MemSImm10Lsl1:6102 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6103 "expected memory with 11-bit signed offset and multiple of 2");6104 case Match_MemSImm10Lsl2:6105 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6106 "expected memory with 12-bit signed offset and multiple of 4");6107 case Match_MemSImm10Lsl3:6108 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6109 "expected memory with 13-bit signed offset and multiple of 8");6110 case Match_MemSImm11:6111 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6112 "expected memory with 11-bit signed offset");6113 case Match_MemSImm12:6114 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6115 "expected memory with 12-bit signed offset");6116 case Match_MemSImm16:6117 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6118 "expected memory with 16-bit signed offset");6119 case Match_MemSImmPtr:6120 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),6121 "expected memory with 32-bit signed offset");6122 case Match_RequiresPosSizeRange0_32: {6123 SMLoc ErrorStart = Operands[3]->getStartLoc();6124 SMLoc ErrorEnd = Operands[4]->getEndLoc();6125 return Error(ErrorStart, "size plus position are not in the range 0 .. 32",6126 SMRange(ErrorStart, ErrorEnd));6127 }6128 case Match_RequiresPosSizeUImm6: {6129 SMLoc ErrorStart = Operands[3]->getStartLoc();6130 SMLoc ErrorEnd = Operands[4]->getEndLoc();6131 return Error(ErrorStart, "size plus position are not in the range 1 .. 63",6132 SMRange(ErrorStart, ErrorEnd));6133 }6134 case Match_RequiresPosSizeRange33_64: {6135 SMLoc ErrorStart = Operands[3]->getStartLoc();6136 SMLoc ErrorEnd = Operands[4]->getEndLoc();6137 return Error(ErrorStart, "size plus position are not in the range 33 .. 64",6138 SMRange(ErrorStart, ErrorEnd));6139 }6140 }6141 6142 llvm_unreachable("Implement any new match types added!");6143}6144 6145void MipsAsmParser::warnIfRegIndexIsAT(MCRegister RegIndex, SMLoc Loc) {6146 if (RegIndex && AssemblerOptions.back()->getATRegIndex() == RegIndex)6147 Warning(Loc, "used $at (currently $" + Twine(RegIndex.id()) +6148 ") without \".set noat\"");6149}6150 6151void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {6152 if (!AssemblerOptions.back()->isMacro())6153 Warning(Loc, "macro instruction expanded into multiple instructions");6154}6155 6156void MipsAsmParser::ConvertXWPOperands(MCInst &Inst,6157 const OperandVector &Operands) {6158 assert(6159 (Inst.getOpcode() == Mips::LWP_MM || Inst.getOpcode() == Mips::SWP_MM) &&6160 "Unexpected instruction!");6161 ((MipsOperand &)*Operands[1]).addGPR32ZeroAsmRegOperands(Inst, 1);6162 MCRegister NextReg = nextReg(((MipsOperand &)*Operands[1]).getGPR32Reg());6163 Inst.addOperand(MCOperand::createReg(NextReg));6164 ((MipsOperand &)*Operands[2]).addMemOperands(Inst, 2);6165}6166 6167void6168MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,6169 SMRange Range, bool ShowColors) {6170 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,6171 Range, SMFixIt(Range, FixMsg),6172 ShowColors);6173}6174 6175int MipsAsmParser::matchCPURegisterName(StringRef Name) {6176 int CC;6177 6178 CC = StringSwitch<unsigned>(Name)6179 .Case("zero", 0)6180 .Cases({"at", "AT"}, 1)6181 .Case("a0", 4)6182 .Case("a1", 5)6183 .Case("a2", 6)6184 .Case("a3", 7)6185 .Case("v0", 2)6186 .Case("v1", 3)6187 .Case("s0", 16)6188 .Case("s1", 17)6189 .Case("s2", 18)6190 .Case("s3", 19)6191 .Case("s4", 20)6192 .Case("s5", 21)6193 .Case("s6", 22)6194 .Case("s7", 23)6195 .Case("k0", 26)6196 .Case("k1", 27)6197 .Case("gp", 28)6198 .Case("sp", 29)6199 .Case("fp", 30)6200 .Case("s8", 30)6201 .Case("ra", 31)6202 .Case("t0", 8)6203 .Case("t1", 9)6204 .Case("t2", 10)6205 .Case("t3", 11)6206 .Case("t4", 12)6207 .Case("t5", 13)6208 .Case("t6", 14)6209 .Case("t7", 15)6210 .Case("t8", 24)6211 .Case("t9", 25)6212 .Default(-1);6213 6214 if (!(isABI_N32() || isABI_N64()))6215 return CC;6216 6217 if (12 <= CC && CC <= 15) {6218 // Name is one of t4-t76219 AsmToken RegTok = getLexer().peekTok();6220 SMRange RegRange = RegTok.getLocRange();6221 6222 StringRef FixedName = StringSwitch<StringRef>(Name)6223 .Case("t4", "t0")6224 .Case("t5", "t1")6225 .Case("t6", "t2")6226 .Case("t7", "t3")6227 .Default("");6228 assert(FixedName != "" && "Register name is not one of t4-t7.");6229 6230 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",6231 "Did you mean $" + FixedName + "?", RegRange);6232 }6233 6234 // Although SGI documentation just cuts out t0-t3 for n32/n64,6235 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t76236 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.6237 if (8 <= CC && CC <= 11)6238 CC += 4;6239 6240 if (CC == -1)6241 CC = StringSwitch<unsigned>(Name)6242 .Case("a4", 8)6243 .Case("a5", 9)6244 .Case("a6", 10)6245 .Case("a7", 11)6246 .Case("kt0", 26)6247 .Case("kt1", 27)6248 .Default(-1);6249 6250 return CC;6251}6252 6253int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {6254 int CC;6255 6256 CC = StringSwitch<unsigned>(Name)6257 .Case("hwr_cpunum", 0)6258 .Case("hwr_synci_step", 1)6259 .Case("hwr_cc", 2)6260 .Case("hwr_ccres", 3)6261 .Case("hwr_ulr", 29)6262 .Default(-1);6263 6264 return CC;6265}6266 6267int MipsAsmParser::matchFPURegisterName(StringRef Name) {6268 if (Name[0] == 'f') {6269 StringRef NumString = Name.substr(1);6270 unsigned IntVal;6271 if (NumString.getAsInteger(10, IntVal))6272 return -1; // This is not an integer.6273 if (IntVal > 31) // Maximum index for fpu register.6274 return -1;6275 return IntVal;6276 }6277 return -1;6278}6279 6280int MipsAsmParser::matchFCCRegisterName(StringRef Name) {6281 if (Name.starts_with("fcc")) {6282 StringRef NumString = Name.substr(3);6283 unsigned IntVal;6284 if (NumString.getAsInteger(10, IntVal))6285 return -1; // This is not an integer.6286 if (IntVal > 7) // There are only 8 fcc registers.6287 return -1;6288 return IntVal;6289 }6290 return -1;6291}6292 6293int MipsAsmParser::matchACRegisterName(StringRef Name) {6294 if (Name.starts_with("ac")) {6295 StringRef NumString = Name.substr(2);6296 unsigned IntVal;6297 if (NumString.getAsInteger(10, IntVal))6298 return -1; // This is not an integer.6299 if (IntVal > 3) // There are only 3 acc registers.6300 return -1;6301 return IntVal;6302 }6303 return -1;6304}6305 6306int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {6307 unsigned IntVal;6308 6309 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))6310 return -1;6311 6312 if (IntVal > 31)6313 return -1;6314 6315 return IntVal;6316}6317 6318int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {6319 int CC;6320 6321 CC = StringSwitch<unsigned>(Name)6322 .Case("msair", 0)6323 .Case("msacsr", 1)6324 .Case("msaaccess", 2)6325 .Case("msasave", 3)6326 .Case("msamodify", 4)6327 .Case("msarequest", 5)6328 .Case("msamap", 6)6329 .Case("msaunmap", 7)6330 .Default(-1);6331 6332 return CC;6333}6334 6335bool MipsAsmParser::canUseATReg() {6336 return AssemblerOptions.back()->getATRegIndex() != 0;6337}6338 6339MCRegister MipsAsmParser::getATReg(SMLoc Loc) {6340 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();6341 if (ATIndex == 0) {6342 reportParseError(Loc,6343 "pseudo-instruction requires $at, which is not available");6344 return 0;6345 }6346 MCRegister AT = getReg(6347 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);6348 return AT;6349}6350 6351MCRegister MipsAsmParser::getReg(int RC, int RegNo) {6352 return getContext().getRegisterInfo()->getRegClass(RC).getRegister(RegNo);6353}6354 6355// Parse an expression with optional relocation operator prefixes (e.g. %lo).6356// Some weird expressions allowed by gas are not supported for simplicity,6357// e.g. "%lo foo", "(%lo(foo))", "%lo(foo)+1".6358const MCExpr *MipsAsmParser::parseRelocExpr() {6359 auto getOp = [](StringRef Op) {6360 return StringSwitch<Mips::Specifier>(Op)6361 .Case("call16", Mips::S_GOT_CALL)6362 .Case("call_hi", Mips::S_CALL_HI16)6363 .Case("call_lo", Mips::S_CALL_LO16)6364 .Case("dtprel_hi", Mips::S_DTPREL_HI)6365 .Case("dtprel_lo", Mips::S_DTPREL_LO)6366 .Case("got", Mips::S_GOT)6367 .Case("got_disp", Mips::S_GOT_DISP)6368 .Case("got_hi", Mips::S_GOT_HI16)6369 .Case("got_lo", Mips::S_GOT_LO16)6370 .Case("got_ofst", Mips::S_GOT_OFST)6371 .Case("got_page", Mips::S_GOT_PAGE)6372 .Case("gottprel", Mips::S_GOTTPREL)6373 .Case("gp_rel", Mips::S_GPREL)6374 .Case("hi", Mips::S_HI)6375 .Case("higher", Mips::S_HIGHER)6376 .Case("highest", Mips::S_HIGHEST)6377 .Case("lo", Mips::S_LO)6378 .Case("neg", Mips::S_NEG)6379 .Case("pcrel_hi", Mips::S_PCREL_HI16)6380 .Case("pcrel_lo", Mips::S_PCREL_LO16)6381 .Case("tlsgd", Mips::S_TLSGD)6382 .Case("tlsldm", Mips::S_TLSLDM)6383 .Case("tprel_hi", Mips::S_TPREL_HI)6384 .Case("tprel_lo", Mips::S_TPREL_LO)6385 .Default(Mips::S_None);6386 };6387 6388 MCAsmParser &Parser = getParser();6389 StringRef Name;6390 const MCExpr *Res = nullptr;6391 SmallVector<Mips::Specifier, 0> Ops;6392 while (parseOptionalToken(AsmToken::Percent)) {6393 if (Parser.parseIdentifier(Name) ||6394 Parser.parseToken(AsmToken::LParen, "expected '('"))6395 return nullptr;6396 auto Op = getOp(Name);6397 if (Op == Mips::S_None) {6398 Error(Parser.getTok().getLoc(), "invalid relocation operator");6399 return nullptr;6400 }6401 Ops.push_back(Op);6402 }6403 if (Parser.parseExpression(Res))6404 return nullptr;6405 while (Ops.size()) {6406 if (Parser.parseToken(AsmToken::RParen, "expected ')'"))6407 return nullptr;6408 Res = MCSpecifierExpr::create(Res, Ops.pop_back_val(), getContext());6409 }6410 return Res;6411}6412 6413bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {6414 MCAsmParser &Parser = getParser();6415 LLVM_DEBUG(dbgs() << "parseOperand\n");6416 6417 // Check if the current operand has a custom associated parser, if so, try to6418 // custom parse the operand, or fallback to the general approach.6419 // Setting the third parameter to true tells the parser to keep parsing even6420 // if the operands are not supported with the current feature set. In this6421 // case, the instruction matcher will output a "instruction requires a CPU6422 // feature not currently enabled" error. If this were false, the parser would6423 // stop here and output a less useful "invalid operand" error.6424 ParseStatus Res = MatchOperandParserImpl(Operands, Mnemonic, true);6425 if (Res.isSuccess())6426 return false;6427 // If there wasn't a custom match, try the generic matcher below. Otherwise,6428 // there was a match, but an error occurred, in which case, just return that6429 // the operand parsing failed.6430 if (Res.isFailure())6431 return true;6432 6433 LLVM_DEBUG(dbgs() << ".. Generic Parser\n");6434 6435 switch (getLexer().getKind()) {6436 case AsmToken::Dollar: {6437 // Parse the register.6438 SMLoc S = Parser.getTok().getLoc();6439 6440 // Almost all registers have been parsed by custom parsers. There is only6441 // one exception to this. $zero (and it's alias $0) will reach this point6442 // for div, divu, and similar instructions because it is not an operand6443 // to the instruction definition but an explicit register. Special case6444 // this situation for now.6445 if (!parseAnyRegister(Operands).isNoMatch())6446 return false;6447 6448 // Maybe it is a symbol reference.6449 StringRef Identifier;6450 if (Parser.parseIdentifier(Identifier))6451 return true;6452 6453 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);6454 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);6455 // Otherwise create a symbol reference.6456 const MCExpr *SymRef = MCSymbolRefExpr::create(Sym, getContext());6457 6458 Operands.push_back(MipsOperand::CreateImm(SymRef, S, E, *this));6459 return false;6460 }6461 default: {6462 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.6463 const MCExpr *Expr = parseRelocExpr();6464 if (!Expr)6465 return true;6466 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);6467 Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));6468 return false;6469 }6470 } // switch(getLexer().getKind())6471 return true;6472}6473 6474bool MipsAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,6475 SMLoc &EndLoc) {6476 return !tryParseRegister(Reg, StartLoc, EndLoc).isSuccess();6477}6478 6479ParseStatus MipsAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,6480 SMLoc &EndLoc) {6481 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;6482 ParseStatus Res = parseAnyRegister(Operands);6483 if (Res.isSuccess()) {6484 assert(Operands.size() == 1);6485 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());6486 StartLoc = Operand.getStartLoc();6487 EndLoc = Operand.getEndLoc();6488 6489 // AFAIK, we only support numeric registers and named GPR's in CFI6490 // directives.6491 // Don't worry about eating tokens before failing. Using an unrecognised6492 // register is a parse error.6493 if (Operand.isGPRAsmReg()) {6494 // Resolve to GPR32 or GPR64 appropriately.6495 Reg = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();6496 }6497 6498 return (Reg == (unsigned)-1) ? ParseStatus::NoMatch : ParseStatus::Success;6499 }6500 6501 assert(Operands.size() == 0);6502 return (Reg == (unsigned)-1) ? ParseStatus::NoMatch : ParseStatus::Success;6503}6504 6505ParseStatus MipsAsmParser::parseMemOperand(OperandVector &Operands) {6506 MCAsmParser &Parser = getParser();6507 LLVM_DEBUG(dbgs() << "parseMemOperand\n");6508 const MCExpr *IdVal = nullptr;6509 SMLoc S;6510 bool isParenExpr = false;6511 ParseStatus Res = ParseStatus::NoMatch;6512 // First operand is the offset.6513 S = Parser.getTok().getLoc();6514 6515 if (getLexer().getKind() == AsmToken::LParen) {6516 Parser.Lex();6517 isParenExpr = true;6518 }6519 6520 if (getLexer().getKind() != AsmToken::Dollar) {6521 IdVal = parseRelocExpr();6522 if (!IdVal)6523 return ParseStatus::Failure;6524 if (isParenExpr && Parser.parseRParen())6525 return ParseStatus::Failure;6526 6527 const AsmToken &Tok = Parser.getTok(); // Get the next token.6528 if (Tok.isNot(AsmToken::LParen)) {6529 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);6530 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {6531 SMLoc E =6532 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);6533 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));6534 return ParseStatus::Success;6535 }6536 if (Tok.is(AsmToken::EndOfStatement)) {6537 SMLoc E =6538 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);6539 6540 // Zero register assumed, add a memory operand with ZERO as its base.6541 // "Base" will be managed by k_Memory.6542 auto Base = MipsOperand::createGPRReg(6543 0, "0", getContext().getRegisterInfo(), S, E, *this);6544 Operands.push_back(6545 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));6546 return ParseStatus::Success;6547 }6548 MCBinaryExpr::Opcode Opcode;6549 // GAS and LLVM treat comparison operators different. GAS will generate -16550 // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is6551 // highly unlikely to be found in a memory offset expression, we don't6552 // handle them.6553 switch (Tok.getKind()) {6554 case AsmToken::Plus:6555 Opcode = MCBinaryExpr::Add;6556 Parser.Lex();6557 break;6558 case AsmToken::Minus:6559 Opcode = MCBinaryExpr::Sub;6560 Parser.Lex();6561 break;6562 case AsmToken::Star:6563 Opcode = MCBinaryExpr::Mul;6564 Parser.Lex();6565 break;6566 case AsmToken::Pipe:6567 Opcode = MCBinaryExpr::Or;6568 Parser.Lex();6569 break;6570 case AsmToken::Amp:6571 Opcode = MCBinaryExpr::And;6572 Parser.Lex();6573 break;6574 case AsmToken::LessLess:6575 Opcode = MCBinaryExpr::Shl;6576 Parser.Lex();6577 break;6578 case AsmToken::GreaterGreater:6579 Opcode = MCBinaryExpr::LShr;6580 Parser.Lex();6581 break;6582 case AsmToken::Caret:6583 Opcode = MCBinaryExpr::Xor;6584 Parser.Lex();6585 break;6586 case AsmToken::Slash:6587 Opcode = MCBinaryExpr::Div;6588 Parser.Lex();6589 break;6590 case AsmToken::Percent:6591 Opcode = MCBinaryExpr::Mod;6592 Parser.Lex();6593 break;6594 default:6595 return Error(Parser.getTok().getLoc(), "'(' or expression expected");6596 }6597 const MCExpr * NextExpr;6598 if (getParser().parseExpression(NextExpr))6599 return ParseStatus::Failure;6600 IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext());6601 }6602 6603 Parser.Lex(); // Eat the '(' token.6604 }6605 6606 Res = parseAnyRegister(Operands);6607 if (!Res.isSuccess())6608 return Res;6609 6610 if (Parser.getTok().isNot(AsmToken::RParen))6611 return Error(Parser.getTok().getLoc(), "')' expected");6612 6613 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);6614 6615 Parser.Lex(); // Eat the ')' token.6616 6617 if (!IdVal)6618 IdVal = MCConstantExpr::create(0, getContext());6619 6620 // Replace the register operand with the memory operand.6621 std::unique_ptr<MipsOperand> op(6622 static_cast<MipsOperand *>(Operands.back().release()));6623 // Remove the register from the operands.6624 // "op" will be managed by k_Memory.6625 Operands.pop_back();6626 // Add the memory operand.6627 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {6628 int64_t Imm;6629 if (IdVal->evaluateAsAbsolute(Imm))6630 IdVal = MCConstantExpr::create(Imm, getContext());6631 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)6632 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),6633 getContext());6634 }6635 6636 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));6637 return ParseStatus::Success;6638}6639 6640bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {6641 MCAsmParser &Parser = getParser();6642 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());6643 if (!Sym)6644 return false;6645 6646 SMLoc S = Parser.getTok().getLoc();6647 if (Sym->isVariable()) {6648 const MCExpr *Expr = Sym->getVariableValue();6649 if (Expr->getKind() == MCExpr::SymbolRef) {6650 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);6651 StringRef DefSymbol = Ref->getSymbol().getName();6652 if (DefSymbol.starts_with("$")) {6653 ParseStatus Res =6654 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);6655 if (Res.isSuccess()) {6656 Parser.Lex();6657 return true;6658 }6659 if (Res.isFailure())6660 llvm_unreachable("Should never fail");6661 }6662 }6663 } else if (Sym->isUndefined()) {6664 // If symbol is unset, it might be created in the `parseSetAssignment`6665 // routine as an alias for a numeric register name.6666 // Lookup in the aliases list.6667 auto Entry = RegisterSets.find(Sym->getName());6668 if (Entry != RegisterSets.end()) {6669 ParseStatus Res =6670 matchAnyRegisterWithoutDollar(Operands, Entry->getValue(), S);6671 if (Res.isSuccess()) {6672 Parser.Lex();6673 return true;6674 }6675 }6676 }6677 6678 return false;6679}6680 6681ParseStatus MipsAsmParser::matchAnyRegisterNameWithoutDollar(6682 OperandVector &Operands, StringRef Identifier, SMLoc S) {6683 int Index = matchCPURegisterName(Identifier);6684 if (Index != -1) {6685 Operands.push_back(MipsOperand::createGPRReg(6686 Index, Identifier, getContext().getRegisterInfo(), S,6687 getLexer().getLoc(), *this));6688 return ParseStatus::Success;6689 }6690 6691 Index = matchHWRegsRegisterName(Identifier);6692 if (Index != -1) {6693 Operands.push_back(MipsOperand::createHWRegsReg(6694 Index, Identifier, getContext().getRegisterInfo(), S,6695 getLexer().getLoc(), *this));6696 return ParseStatus::Success;6697 }6698 6699 Index = matchFPURegisterName(Identifier);6700 if (Index != -1) {6701 Operands.push_back(MipsOperand::createFGRReg(6702 Index, Identifier, getContext().getRegisterInfo(), S,6703 getLexer().getLoc(), *this));6704 return ParseStatus::Success;6705 }6706 6707 Index = matchFCCRegisterName(Identifier);6708 if (Index != -1) {6709 Operands.push_back(MipsOperand::createFCCReg(6710 Index, Identifier, getContext().getRegisterInfo(), S,6711 getLexer().getLoc(), *this));6712 return ParseStatus::Success;6713 }6714 6715 Index = matchACRegisterName(Identifier);6716 if (Index != -1) {6717 Operands.push_back(MipsOperand::createACCReg(6718 Index, Identifier, getContext().getRegisterInfo(), S,6719 getLexer().getLoc(), *this));6720 return ParseStatus::Success;6721 }6722 6723 Index = matchMSA128RegisterName(Identifier);6724 if (Index != -1) {6725 Operands.push_back(MipsOperand::createMSA128Reg(6726 Index, Identifier, getContext().getRegisterInfo(), S,6727 getLexer().getLoc(), *this));6728 return ParseStatus::Success;6729 }6730 6731 Index = matchMSA128CtrlRegisterName(Identifier);6732 if (Index != -1) {6733 Operands.push_back(MipsOperand::createMSACtrlReg(6734 Index, Identifier, getContext().getRegisterInfo(), S,6735 getLexer().getLoc(), *this));6736 return ParseStatus::Success;6737 }6738 6739 return ParseStatus::NoMatch;6740}6741 6742ParseStatus6743MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands,6744 const AsmToken &Token, SMLoc S) {6745 if (Token.is(AsmToken::Identifier)) {6746 LLVM_DEBUG(dbgs() << ".. identifier\n");6747 StringRef Identifier = Token.getIdentifier();6748 return matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);6749 }6750 if (Token.is(AsmToken::Integer)) {6751 LLVM_DEBUG(dbgs() << ".. integer\n");6752 int64_t RegNum = Token.getIntVal();6753 if (RegNum < 0 || RegNum > 31) {6754 // Show the error, but treat invalid register6755 // number as a normal one to continue parsing6756 // and catch other possible errors.6757 Error(getLexer().getLoc(), "invalid register number");6758 }6759 Operands.push_back(MipsOperand::createNumericReg(6760 RegNum, Token.getString(), getContext().getRegisterInfo(), S,6761 Token.getLoc(), *this));6762 return ParseStatus::Success;6763 }6764 6765 LLVM_DEBUG(dbgs() << Token.getKind() << "\n");6766 6767 return ParseStatus::NoMatch;6768}6769 6770ParseStatus6771MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {6772 auto Token = getLexer().peekTok(false);6773 return matchAnyRegisterWithoutDollar(Operands, Token, S);6774}6775 6776ParseStatus MipsAsmParser::parseAnyRegister(OperandVector &Operands) {6777 MCAsmParser &Parser = getParser();6778 LLVM_DEBUG(dbgs() << "parseAnyRegister\n");6779 6780 auto Token = Parser.getTok();6781 6782 SMLoc S = Token.getLoc();6783 6784 if (Token.isNot(AsmToken::Dollar)) {6785 LLVM_DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");6786 if (Token.is(AsmToken::Identifier)) {6787 if (searchSymbolAlias(Operands))6788 return ParseStatus::Success;6789 }6790 LLVM_DEBUG(dbgs() << ".. !symalias -> NoMatch\n");6791 return ParseStatus::NoMatch;6792 }6793 LLVM_DEBUG(dbgs() << ".. $\n");6794 6795 ParseStatus Res = matchAnyRegisterWithoutDollar(Operands, S);6796 if (Res.isSuccess()) {6797 Parser.Lex(); // $6798 Parser.Lex(); // identifier6799 }6800 return Res;6801}6802 6803ParseStatus MipsAsmParser::parseJumpTarget(OperandVector &Operands) {6804 MCAsmParser &Parser = getParser();6805 LLVM_DEBUG(dbgs() << "parseJumpTarget\n");6806 6807 SMLoc S = getLexer().getLoc();6808 6809 // Registers are a valid target and have priority over symbols.6810 ParseStatus Res = parseAnyRegister(Operands);6811 if (!Res.isNoMatch())6812 return Res;6813 6814 // Integers and expressions are acceptable6815 const MCExpr *Expr = nullptr;6816 if (Parser.parseExpression(Expr)) {6817 // We have no way of knowing if a symbol was consumed so we must ParseFail6818 return ParseStatus::Failure;6819 }6820 Operands.push_back(6821 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));6822 return ParseStatus::Success;6823}6824 6825ParseStatus MipsAsmParser::parseInvNum(OperandVector &Operands) {6826 MCAsmParser &Parser = getParser();6827 const MCExpr *IdVal;6828 // If the first token is '$' we may have register operand. We have to reject6829 // cases where it is not a register. Complicating the matter is that6830 // register names are not reserved across all ABIs.6831 // Peek past the dollar to see if it's a register name for this ABI.6832 SMLoc S = Parser.getTok().getLoc();6833 if (Parser.getTok().is(AsmToken::Dollar)) {6834 return matchCPURegisterName(Parser.getLexer().peekTok().getString()) == -16835 ? ParseStatus::Failure6836 : ParseStatus::NoMatch;6837 }6838 if (getParser().parseExpression(IdVal))6839 return ParseStatus::Failure;6840 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);6841 if (!MCE)6842 return ParseStatus::NoMatch;6843 int64_t Val = MCE->getValue();6844 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);6845 Operands.push_back(MipsOperand::CreateImm(6846 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));6847 return ParseStatus::Success;6848}6849 6850ParseStatus MipsAsmParser::parseRegisterList(OperandVector &Operands) {6851 MCAsmParser &Parser = getParser();6852 SmallVector<MCRegister, 10> Regs;6853 MCRegister Reg;6854 MCRegister PrevReg;6855 bool RegRange = false;6856 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;6857 6858 if (Parser.getTok().isNot(AsmToken::Dollar))6859 return ParseStatus::Failure;6860 6861 SMLoc S = Parser.getTok().getLoc();6862 while (parseAnyRegister(TmpOperands).isSuccess()) {6863 SMLoc E = getLexer().getLoc();6864 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*TmpOperands.back());6865 Reg = isGP64bit() ? RegOpnd.getGPR64Reg() : RegOpnd.getGPR32Reg();6866 if (RegRange) {6867 // Remove last register operand because registers from register range6868 // should be inserted first.6869 if ((isGP64bit() && Reg == Mips::RA_64) ||6870 (!isGP64bit() && Reg == Mips::RA)) {6871 Regs.push_back(Reg);6872 } else {6873 MCRegister TmpReg = PrevReg + 1;6874 while (TmpReg <= Reg) {6875 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||6876 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&6877 isGP64bit()))6878 return Error(E, "invalid register operand");6879 6880 PrevReg = TmpReg;6881 Regs.push_back(TmpReg);6882 TmpReg = TmpReg.id() + 1;6883 }6884 }6885 6886 RegRange = false;6887 } else {6888 if (!PrevReg.isValid() &&6889 ((isGP64bit() && (Reg != Mips::S0_64) && (Reg != Mips::RA_64)) ||6890 (!isGP64bit() && (Reg != Mips::S0) && (Reg != Mips::RA))))6891 return Error(E, "$16 or $31 expected");6892 if (!(((Reg == Mips::FP || Reg == Mips::RA ||6893 (Reg >= Mips::S0 && Reg <= Mips::S7)) &&6894 !isGP64bit()) ||6895 ((Reg == Mips::FP_64 || Reg == Mips::RA_64 ||6896 (Reg >= Mips::S0_64 && Reg <= Mips::S7_64)) &&6897 isGP64bit())))6898 return Error(E, "invalid register operand");6899 if (PrevReg.isValid() && (Reg != PrevReg + 1) &&6900 ((Reg != Mips::FP && Reg != Mips::RA && !isGP64bit()) ||6901 (Reg != Mips::FP_64 && Reg != Mips::RA_64 && isGP64bit())))6902 return Error(E, "consecutive register numbers expected");6903 6904 Regs.push_back(Reg);6905 }6906 6907 if (Parser.getTok().is(AsmToken::Minus))6908 RegRange = true;6909 6910 if (!Parser.getTok().isNot(AsmToken::Minus) &&6911 !Parser.getTok().isNot(AsmToken::Comma))6912 return Error(E, "',' or '-' expected");6913 6914 Lex(); // Consume comma or minus6915 if (Parser.getTok().isNot(AsmToken::Dollar))6916 break;6917 6918 PrevReg = Reg;6919 }6920 6921 SMLoc E = Parser.getTok().getLoc();6922 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));6923 parseMemOperand(Operands);6924 return ParseStatus::Success;6925}6926 6927/// Sometimes (i.e. load/stores) the operand may be followed immediately by6928/// either this.6929/// ::= '(', register, ')'6930/// handle it before we iterate so we don't get tripped up by the lack of6931/// a comma.6932bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {6933 MCAsmParser &Parser = getParser();6934 if (getLexer().is(AsmToken::LParen)) {6935 Operands.push_back(6936 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));6937 Parser.Lex();6938 if (parseOperand(Operands, Name)) {6939 SMLoc Loc = getLexer().getLoc();6940 return Error(Loc, "unexpected token in argument list");6941 }6942 if (Parser.getTok().isNot(AsmToken::RParen)) {6943 SMLoc Loc = getLexer().getLoc();6944 return Error(Loc, "unexpected token, expected ')'");6945 }6946 Operands.push_back(6947 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));6948 Parser.Lex();6949 }6950 return false;6951}6952 6953/// Sometimes (i.e. in MSA) the operand may be followed immediately by6954/// either one of these.6955/// ::= '[', register, ']'6956/// ::= '[', integer, ']'6957/// handle it before we iterate so we don't get tripped up by the lack of6958/// a comma.6959bool MipsAsmParser::parseBracketSuffix(StringRef Name,6960 OperandVector &Operands) {6961 MCAsmParser &Parser = getParser();6962 if (getLexer().is(AsmToken::LBrac)) {6963 Operands.push_back(6964 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));6965 Parser.Lex();6966 if (parseOperand(Operands, Name)) {6967 SMLoc Loc = getLexer().getLoc();6968 return Error(Loc, "unexpected token in argument list");6969 }6970 if (Parser.getTok().isNot(AsmToken::RBrac)) {6971 SMLoc Loc = getLexer().getLoc();6972 return Error(Loc, "unexpected token, expected ']'");6973 }6974 Operands.push_back(6975 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));6976 Parser.Lex();6977 }6978 return false;6979}6980 6981static std::string MipsMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS,6982 unsigned VariantID = 0);6983 6984bool MipsAsmParser::areEqualRegs(const MCParsedAsmOperand &Op1,6985 const MCParsedAsmOperand &Op2) const {6986 // This target-overriden function exists to maintain current behaviour for6987 // e.g.6988 // dahi $3, $3, 0x56786989 // as tested in test/MC/Mips/mips64r6/valid.s.6990 // FIXME: Should this test actually fail with an error? If so, then remove6991 // this overloaded method.6992 if (!Op1.isReg() || !Op2.isReg())6993 return true;6994 return Op1.getReg() == Op2.getReg();6995}6996 6997bool MipsAsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Name,6998 SMLoc NameLoc, OperandVector &Operands) {6999 MCAsmParser &Parser = getParser();7000 LLVM_DEBUG(dbgs() << "parseInstruction\n");7001 7002 // We have reached first instruction, module directive are now forbidden.7003 getTargetStreamer().forbidModuleDirective();7004 7005 // Check if we have valid mnemonic7006 if (!mnemonicIsValid(Name, 0)) {7007 FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());7008 std::string Suggestion = MipsMnemonicSpellCheck(Name, FBS);7009 return Error(NameLoc, "unknown instruction" + Suggestion);7010 }7011 // First operand in MCInst is instruction mnemonic.7012 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));7013 7014 // Read the remaining operands.7015 if (getLexer().isNot(AsmToken::EndOfStatement)) {7016 // Read the first operand.7017 if (parseOperand(Operands, Name)) {7018 SMLoc Loc = getLexer().getLoc();7019 return Error(Loc, "unexpected token in argument list");7020 }7021 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))7022 return true;7023 // AFAIK, parenthesis suffixes are never on the first operand7024 7025 while (getLexer().is(AsmToken::Comma)) {7026 Parser.Lex(); // Eat the comma.7027 // Parse and remember the operand.7028 if (parseOperand(Operands, Name)) {7029 SMLoc Loc = getLexer().getLoc();7030 return Error(Loc, "unexpected token in argument list");7031 }7032 // Parse bracket and parenthesis suffixes before we iterate7033 if (getLexer().is(AsmToken::LBrac)) {7034 if (parseBracketSuffix(Name, Operands))7035 return true;7036 } else if (getLexer().is(AsmToken::LParen) &&7037 parseParenSuffix(Name, Operands))7038 return true;7039 }7040 }7041 if (getLexer().isNot(AsmToken::EndOfStatement)) {7042 SMLoc Loc = getLexer().getLoc();7043 return Error(Loc, "unexpected token in argument list");7044 }7045 Parser.Lex(); // Consume the EndOfStatement.7046 return false;7047}7048 7049// FIXME: Given that these have the same name, these should both be7050// consistent on affecting the Parser.7051bool MipsAsmParser::reportParseError(const Twine &ErrorMsg) {7052 SMLoc Loc = getLexer().getLoc();7053 return Error(Loc, ErrorMsg);7054}7055 7056bool MipsAsmParser::reportParseError(SMLoc Loc, const Twine &ErrorMsg) {7057 return Error(Loc, ErrorMsg);7058}7059 7060bool MipsAsmParser::parseSetNoAtDirective() {7061 MCAsmParser &Parser = getParser();7062 // Line should look like: ".set noat".7063 7064 // Set the $at register to $0.7065 AssemblerOptions.back()->setATRegIndex(0);7066 7067 Parser.Lex(); // Eat "noat".7068 7069 // If this is not the end of the statement, report an error.7070 if (getLexer().isNot(AsmToken::EndOfStatement)) {7071 reportParseError("unexpected token, expected end of statement");7072 return false;7073 }7074 7075 getTargetStreamer().emitDirectiveSetNoAt();7076 Parser.Lex(); // Consume the EndOfStatement.7077 return false;7078}7079 7080bool MipsAsmParser::parseSetAtDirective() {7081 // Line can be: ".set at", which sets $at to $17082 // or ".set at=$reg", which sets $at to $reg.7083 MCAsmParser &Parser = getParser();7084 Parser.Lex(); // Eat "at".7085 7086 if (getLexer().is(AsmToken::EndOfStatement)) {7087 // No register was specified, so we set $at to $1.7088 AssemblerOptions.back()->setATRegIndex(1);7089 7090 getTargetStreamer().emitDirectiveSetAt();7091 Parser.Lex(); // Consume the EndOfStatement.7092 return false;7093 }7094 7095 if (getLexer().isNot(AsmToken::Equal)) {7096 reportParseError("unexpected token, expected equals sign");7097 return false;7098 }7099 Parser.Lex(); // Eat "=".7100 7101 if (getLexer().isNot(AsmToken::Dollar)) {7102 if (getLexer().is(AsmToken::EndOfStatement)) {7103 reportParseError("no register specified");7104 return false;7105 } else {7106 reportParseError("unexpected token, expected dollar sign '$'");7107 return false;7108 }7109 }7110 Parser.Lex(); // Eat "$".7111 7112 // Find out what "reg" is.7113 unsigned AtRegNo;7114 const AsmToken &Reg = Parser.getTok();7115 if (Reg.is(AsmToken::Identifier)) {7116 AtRegNo = matchCPURegisterName(Reg.getIdentifier());7117 } else if (Reg.is(AsmToken::Integer)) {7118 AtRegNo = Reg.getIntVal();7119 } else {7120 reportParseError("unexpected token, expected identifier or integer");7121 return false;7122 }7123 7124 // Check if $reg is a valid register. If it is, set $at to $reg.7125 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {7126 reportParseError("invalid register");7127 return false;7128 }7129 Parser.Lex(); // Eat "reg".7130 7131 // If this is not the end of the statement, report an error.7132 if (getLexer().isNot(AsmToken::EndOfStatement)) {7133 reportParseError("unexpected token, expected end of statement");7134 return false;7135 }7136 7137 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);7138 7139 Parser.Lex(); // Consume the EndOfStatement.7140 return false;7141}7142 7143bool MipsAsmParser::parseSetReorderDirective() {7144 MCAsmParser &Parser = getParser();7145 Parser.Lex();7146 // If this is not the end of the statement, report an error.7147 if (getLexer().isNot(AsmToken::EndOfStatement)) {7148 reportParseError("unexpected token, expected end of statement");7149 return false;7150 }7151 AssemblerOptions.back()->setReorder();7152 getTargetStreamer().emitDirectiveSetReorder();7153 Parser.Lex(); // Consume the EndOfStatement.7154 return false;7155}7156 7157bool MipsAsmParser::parseSetNoReorderDirective() {7158 MCAsmParser &Parser = getParser();7159 Parser.Lex();7160 // If this is not the end of the statement, report an error.7161 if (getLexer().isNot(AsmToken::EndOfStatement)) {7162 reportParseError("unexpected token, expected end of statement");7163 return false;7164 }7165 AssemblerOptions.back()->setNoReorder();7166 getTargetStreamer().emitDirectiveSetNoReorder();7167 Parser.Lex(); // Consume the EndOfStatement.7168 return false;7169}7170 7171bool MipsAsmParser::parseSetMacroDirective() {7172 MCAsmParser &Parser = getParser();7173 Parser.Lex();7174 // If this is not the end of the statement, report an error.7175 if (getLexer().isNot(AsmToken::EndOfStatement)) {7176 reportParseError("unexpected token, expected end of statement");7177 return false;7178 }7179 AssemblerOptions.back()->setMacro();7180 getTargetStreamer().emitDirectiveSetMacro();7181 Parser.Lex(); // Consume the EndOfStatement.7182 return false;7183}7184 7185bool MipsAsmParser::parseSetNoMacroDirective() {7186 MCAsmParser &Parser = getParser();7187 Parser.Lex();7188 // If this is not the end of the statement, report an error.7189 if (getLexer().isNot(AsmToken::EndOfStatement)) {7190 reportParseError("unexpected token, expected end of statement");7191 return false;7192 }7193 if (AssemblerOptions.back()->isReorder()) {7194 reportParseError("`noreorder' must be set before `nomacro'");7195 return false;7196 }7197 AssemblerOptions.back()->setNoMacro();7198 getTargetStreamer().emitDirectiveSetNoMacro();7199 Parser.Lex(); // Consume the EndOfStatement.7200 return false;7201}7202 7203bool MipsAsmParser::parseSetMsaDirective() {7204 MCAsmParser &Parser = getParser();7205 Parser.Lex();7206 7207 // If this is not the end of the statement, report an error.7208 if (getLexer().isNot(AsmToken::EndOfStatement))7209 return reportParseError("unexpected token, expected end of statement");7210 7211 setFeatureBits(Mips::FeatureMSA, "msa");7212 getTargetStreamer().emitDirectiveSetMsa();7213 return false;7214}7215 7216bool MipsAsmParser::parseSetNoMsaDirective() {7217 MCAsmParser &Parser = getParser();7218 Parser.Lex();7219 7220 // If this is not the end of the statement, report an error.7221 if (getLexer().isNot(AsmToken::EndOfStatement))7222 return reportParseError("unexpected token, expected end of statement");7223 7224 clearFeatureBits(Mips::FeatureMSA, "msa");7225 getTargetStreamer().emitDirectiveSetNoMsa();7226 return false;7227}7228 7229bool MipsAsmParser::parseSetNoDspDirective() {7230 MCAsmParser &Parser = getParser();7231 Parser.Lex(); // Eat "nodsp".7232 7233 // If this is not the end of the statement, report an error.7234 if (getLexer().isNot(AsmToken::EndOfStatement)) {7235 reportParseError("unexpected token, expected end of statement");7236 return false;7237 }7238 7239 clearFeatureBits(Mips::FeatureDSP, "dsp");7240 getTargetStreamer().emitDirectiveSetNoDsp();7241 return false;7242}7243 7244bool MipsAsmParser::parseSetNoMips3DDirective() {7245 MCAsmParser &Parser = getParser();7246 Parser.Lex(); // Eat "nomips3d".7247 7248 // If this is not the end of the statement, report an error.7249 if (getLexer().isNot(AsmToken::EndOfStatement)) {7250 reportParseError("unexpected token, expected end of statement");7251 return false;7252 }7253 7254 clearFeatureBits(Mips::FeatureMips3D, "mips3d");7255 getTargetStreamer().emitDirectiveSetNoMips3D();7256 return false;7257}7258 7259bool MipsAsmParser::parseSetMips16Directive() {7260 MCAsmParser &Parser = getParser();7261 Parser.Lex(); // Eat "mips16".7262 7263 // If this is not the end of the statement, report an error.7264 if (getLexer().isNot(AsmToken::EndOfStatement)) {7265 reportParseError("unexpected token, expected end of statement");7266 return false;7267 }7268 7269 setFeatureBits(Mips::FeatureMips16, "mips16");7270 getTargetStreamer().emitDirectiveSetMips16();7271 Parser.Lex(); // Consume the EndOfStatement.7272 return false;7273}7274 7275bool MipsAsmParser::parseSetNoMips16Directive() {7276 MCAsmParser &Parser = getParser();7277 Parser.Lex(); // Eat "nomips16".7278 7279 // If this is not the end of the statement, report an error.7280 if (getLexer().isNot(AsmToken::EndOfStatement)) {7281 reportParseError("unexpected token, expected end of statement");7282 return false;7283 }7284 7285 clearFeatureBits(Mips::FeatureMips16, "mips16");7286 getTargetStreamer().emitDirectiveSetNoMips16();7287 Parser.Lex(); // Consume the EndOfStatement.7288 return false;7289}7290 7291bool MipsAsmParser::parseSetFpDirective() {7292 MCAsmParser &Parser = getParser();7293 MipsABIFlagsSection::FpABIKind FpAbiVal;7294 // Line can be: .set fp=327295 // .set fp=xx7296 // .set fp=647297 Parser.Lex(); // Eat fp token7298 AsmToken Tok = Parser.getTok();7299 if (Tok.isNot(AsmToken::Equal)) {7300 reportParseError("unexpected token, expected equals sign '='");7301 return false;7302 }7303 Parser.Lex(); // Eat '=' token.7304 Tok = Parser.getTok();7305 7306 if (!parseFpABIValue(FpAbiVal, ".set"))7307 return false;7308 7309 if (getLexer().isNot(AsmToken::EndOfStatement)) {7310 reportParseError("unexpected token, expected end of statement");7311 return false;7312 }7313 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);7314 Parser.Lex(); // Consume the EndOfStatement.7315 return false;7316}7317 7318bool MipsAsmParser::parseSetOddSPRegDirective() {7319 MCAsmParser &Parser = getParser();7320 7321 Parser.Lex(); // Eat "oddspreg".7322 if (getLexer().isNot(AsmToken::EndOfStatement)) {7323 reportParseError("unexpected token, expected end of statement");7324 return false;7325 }7326 7327 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");7328 getTargetStreamer().emitDirectiveSetOddSPReg();7329 return false;7330}7331 7332bool MipsAsmParser::parseSetNoOddSPRegDirective() {7333 MCAsmParser &Parser = getParser();7334 7335 Parser.Lex(); // Eat "nooddspreg".7336 if (getLexer().isNot(AsmToken::EndOfStatement)) {7337 reportParseError("unexpected token, expected end of statement");7338 return false;7339 }7340 7341 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");7342 getTargetStreamer().emitDirectiveSetNoOddSPReg();7343 return false;7344}7345 7346bool MipsAsmParser::parseSetMtDirective() {7347 MCAsmParser &Parser = getParser();7348 Parser.Lex(); // Eat "mt".7349 7350 // If this is not the end of the statement, report an error.7351 if (getLexer().isNot(AsmToken::EndOfStatement)) {7352 reportParseError("unexpected token, expected end of statement");7353 return false;7354 }7355 7356 setFeatureBits(Mips::FeatureMT, "mt");7357 getTargetStreamer().emitDirectiveSetMt();7358 Parser.Lex(); // Consume the EndOfStatement.7359 return false;7360}7361 7362bool MipsAsmParser::parseSetNoMtDirective() {7363 MCAsmParser &Parser = getParser();7364 Parser.Lex(); // Eat "nomt".7365 7366 // If this is not the end of the statement, report an error.7367 if (getLexer().isNot(AsmToken::EndOfStatement)) {7368 reportParseError("unexpected token, expected end of statement");7369 return false;7370 }7371 7372 clearFeatureBits(Mips::FeatureMT, "mt");7373 7374 getTargetStreamer().emitDirectiveSetNoMt();7375 Parser.Lex(); // Consume the EndOfStatement.7376 return false;7377}7378 7379bool MipsAsmParser::parseSetNoCRCDirective() {7380 MCAsmParser &Parser = getParser();7381 Parser.Lex(); // Eat "nocrc".7382 7383 // If this is not the end of the statement, report an error.7384 if (getLexer().isNot(AsmToken::EndOfStatement)) {7385 reportParseError("unexpected token, expected end of statement");7386 return false;7387 }7388 7389 clearFeatureBits(Mips::FeatureCRC, "crc");7390 7391 getTargetStreamer().emitDirectiveSetNoCRC();7392 Parser.Lex(); // Consume the EndOfStatement.7393 return false;7394}7395 7396bool MipsAsmParser::parseSetNoVirtDirective() {7397 MCAsmParser &Parser = getParser();7398 Parser.Lex(); // Eat "novirt".7399 7400 // If this is not the end of the statement, report an error.7401 if (getLexer().isNot(AsmToken::EndOfStatement)) {7402 reportParseError("unexpected token, expected end of statement");7403 return false;7404 }7405 7406 clearFeatureBits(Mips::FeatureVirt, "virt");7407 7408 getTargetStreamer().emitDirectiveSetNoVirt();7409 Parser.Lex(); // Consume the EndOfStatement.7410 return false;7411}7412 7413bool MipsAsmParser::parseSetNoGINVDirective() {7414 MCAsmParser &Parser = getParser();7415 Parser.Lex(); // Eat "noginv".7416 7417 // If this is not the end of the statement, report an error.7418 if (getLexer().isNot(AsmToken::EndOfStatement)) {7419 reportParseError("unexpected token, expected end of statement");7420 return false;7421 }7422 7423 clearFeatureBits(Mips::FeatureGINV, "ginv");7424 7425 getTargetStreamer().emitDirectiveSetNoGINV();7426 Parser.Lex(); // Consume the EndOfStatement.7427 return false;7428}7429 7430bool MipsAsmParser::parseSetPopDirective() {7431 MCAsmParser &Parser = getParser();7432 SMLoc Loc = getLexer().getLoc();7433 7434 Parser.Lex();7435 if (getLexer().isNot(AsmToken::EndOfStatement))7436 return reportParseError("unexpected token, expected end of statement");7437 7438 // Always keep an element on the options "stack" to prevent the user7439 // from changing the initial options. This is how we remember them.7440 if (AssemblerOptions.size() == 2)7441 return reportParseError(Loc, ".set pop with no .set push");7442 7443 MCSubtargetInfo &STI = copySTI();7444 AssemblerOptions.pop_back();7445 setAvailableFeatures(7446 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));7447 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());7448 7449 getTargetStreamer().emitDirectiveSetPop();7450 return false;7451}7452 7453bool MipsAsmParser::parseSetPushDirective() {7454 MCAsmParser &Parser = getParser();7455 Parser.Lex();7456 if (getLexer().isNot(AsmToken::EndOfStatement))7457 return reportParseError("unexpected token, expected end of statement");7458 7459 // Create a copy of the current assembler options environment and push it.7460 AssemblerOptions.push_back(7461 std::make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));7462 7463 getTargetStreamer().emitDirectiveSetPush();7464 return false;7465}7466 7467bool MipsAsmParser::parseSetSoftFloatDirective() {7468 MCAsmParser &Parser = getParser();7469 Parser.Lex();7470 if (getLexer().isNot(AsmToken::EndOfStatement))7471 return reportParseError("unexpected token, expected end of statement");7472 7473 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");7474 getTargetStreamer().emitDirectiveSetSoftFloat();7475 return false;7476}7477 7478bool MipsAsmParser::parseSetHardFloatDirective() {7479 MCAsmParser &Parser = getParser();7480 Parser.Lex();7481 if (getLexer().isNot(AsmToken::EndOfStatement))7482 return reportParseError("unexpected token, expected end of statement");7483 7484 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");7485 getTargetStreamer().emitDirectiveSetHardFloat();7486 return false;7487}7488 7489bool MipsAsmParser::parseSetAssignment() {7490 StringRef Name;7491 MCAsmParser &Parser = getParser();7492 7493 if (Parser.parseIdentifier(Name))7494 return reportParseError("expected identifier after .set");7495 7496 if (getLexer().isNot(AsmToken::Comma))7497 return reportParseError("unexpected token, expected comma");7498 Lex(); // Eat comma7499 7500 if (getLexer().is(AsmToken::Dollar) &&7501 getLexer().peekTok().is(AsmToken::Integer)) {7502 // Parse assignment of a numeric register:7503 // .set r1,$17504 Parser.Lex(); // Eat $.7505 RegisterSets[Name] = Parser.getTok();7506 Parser.Lex(); // Eat identifier.7507 getContext().getOrCreateSymbol(Name);7508 return false;7509 }7510 7511 MCSymbol *Sym;7512 const MCExpr *Value;7513 if (MCParserUtils::parseAssignmentExpression(Name, /* allow_redef */ true,7514 Parser, Sym, Value))7515 return true;7516 getStreamer().emitAssignment(Sym, Value);7517 7518 return false;7519}7520 7521bool MipsAsmParser::parseSetMips0Directive() {7522 MCAsmParser &Parser = getParser();7523 Parser.Lex();7524 if (getLexer().isNot(AsmToken::EndOfStatement))7525 return reportParseError("unexpected token, expected end of statement");7526 7527 // Reset assembler options to their initial values.7528 MCSubtargetInfo &STI = copySTI();7529 setAvailableFeatures(7530 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));7531 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());7532 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());7533 7534 getTargetStreamer().emitDirectiveSetMips0();7535 return false;7536}7537 7538bool MipsAsmParser::parseSetArchDirective() {7539 MCAsmParser &Parser = getParser();7540 Parser.Lex();7541 if (getLexer().isNot(AsmToken::Equal))7542 return reportParseError("unexpected token, expected equals sign");7543 7544 Parser.Lex();7545 StringRef Arch = getParser().parseStringToEndOfStatement().trim();7546 if (Arch.empty())7547 return reportParseError("expected arch identifier");7548 7549 StringRef ArchFeatureName =7550 StringSwitch<StringRef>(Arch)7551 .Case("mips1", "mips1")7552 .Case("mips2", "mips2")7553 .Case("mips3", "mips3")7554 .Case("mips4", "mips4")7555 .Case("mips5", "mips5")7556 .Case("mips32", "mips32")7557 .Case("mips32r2", "mips32r2")7558 .Case("mips32r3", "mips32r3")7559 .Case("mips32r5", "mips32r5")7560 .Case("mips32r6", "mips32r6")7561 .Case("mips64", "mips64")7562 .Case("mips64r2", "mips64r2")7563 .Case("mips64r3", "mips64r3")7564 .Case("mips64r5", "mips64r5")7565 .Case("mips64r6", "mips64r6")7566 .Case("octeon", "cnmips")7567 .Case("octeon+", "cnmipsp")7568 .Case("r4000", "mips3") // This is an implementation of Mips3.7569 .Default("");7570 7571 if (ArchFeatureName.empty())7572 return reportParseError("unsupported architecture");7573 7574 if (ArchFeatureName == "mips64r6" && inMicroMipsMode())7575 return reportParseError("mips64r6 does not support microMIPS");7576 7577 selectArch(ArchFeatureName);7578 getTargetStreamer().emitDirectiveSetArch(Arch);7579 return false;7580}7581 7582bool MipsAsmParser::parseSetFeature(uint64_t Feature) {7583 MCAsmParser &Parser = getParser();7584 Parser.Lex();7585 if (getLexer().isNot(AsmToken::EndOfStatement))7586 return reportParseError("unexpected token, expected end of statement");7587 7588 switch (Feature) {7589 default:7590 llvm_unreachable("Unimplemented feature");7591 case Mips::FeatureMips3D:7592 setFeatureBits(Mips::FeatureMips3D, "mips3d");7593 getTargetStreamer().emitDirectiveSetMips3D();7594 break;7595 case Mips::FeatureDSP:7596 setFeatureBits(Mips::FeatureDSP, "dsp");7597 getTargetStreamer().emitDirectiveSetDsp();7598 break;7599 case Mips::FeatureDSPR2:7600 setFeatureBits(Mips::FeatureDSPR2, "dspr2");7601 getTargetStreamer().emitDirectiveSetDspr2();7602 break;7603 case Mips::FeatureMicroMips:7604 setFeatureBits(Mips::FeatureMicroMips, "micromips");7605 getTargetStreamer().emitDirectiveSetMicroMips();7606 break;7607 case Mips::FeatureMips1:7608 selectArch("mips1");7609 getTargetStreamer().emitDirectiveSetMips1();7610 break;7611 case Mips::FeatureMips2:7612 selectArch("mips2");7613 getTargetStreamer().emitDirectiveSetMips2();7614 break;7615 case Mips::FeatureMips3:7616 selectArch("mips3");7617 getTargetStreamer().emitDirectiveSetMips3();7618 break;7619 case Mips::FeatureMips4:7620 selectArch("mips4");7621 getTargetStreamer().emitDirectiveSetMips4();7622 break;7623 case Mips::FeatureMips5:7624 selectArch("mips5");7625 getTargetStreamer().emitDirectiveSetMips5();7626 break;7627 case Mips::FeatureMips32:7628 selectArch("mips32");7629 getTargetStreamer().emitDirectiveSetMips32();7630 break;7631 case Mips::FeatureMips32r2:7632 selectArch("mips32r2");7633 getTargetStreamer().emitDirectiveSetMips32R2();7634 break;7635 case Mips::FeatureMips32r3:7636 selectArch("mips32r3");7637 getTargetStreamer().emitDirectiveSetMips32R3();7638 break;7639 case Mips::FeatureMips32r5:7640 selectArch("mips32r5");7641 getTargetStreamer().emitDirectiveSetMips32R5();7642 break;7643 case Mips::FeatureMips32r6:7644 selectArch("mips32r6");7645 getTargetStreamer().emitDirectiveSetMips32R6();7646 break;7647 case Mips::FeatureMips64:7648 selectArch("mips64");7649 getTargetStreamer().emitDirectiveSetMips64();7650 break;7651 case Mips::FeatureMips64r2:7652 selectArch("mips64r2");7653 getTargetStreamer().emitDirectiveSetMips64R2();7654 break;7655 case Mips::FeatureMips64r3:7656 selectArch("mips64r3");7657 getTargetStreamer().emitDirectiveSetMips64R3();7658 break;7659 case Mips::FeatureMips64r5:7660 selectArch("mips64r5");7661 getTargetStreamer().emitDirectiveSetMips64R5();7662 break;7663 case Mips::FeatureMips64r6:7664 selectArch("mips64r6");7665 getTargetStreamer().emitDirectiveSetMips64R6();7666 break;7667 case Mips::FeatureCRC:7668 setFeatureBits(Mips::FeatureCRC, "crc");7669 getTargetStreamer().emitDirectiveSetCRC();7670 break;7671 case Mips::FeatureVirt:7672 setFeatureBits(Mips::FeatureVirt, "virt");7673 getTargetStreamer().emitDirectiveSetVirt();7674 break;7675 case Mips::FeatureGINV:7676 setFeatureBits(Mips::FeatureGINV, "ginv");7677 getTargetStreamer().emitDirectiveSetGINV();7678 break;7679 }7680 return false;7681}7682 7683bool MipsAsmParser::eatComma(StringRef ErrorStr) {7684 MCAsmParser &Parser = getParser();7685 if (getLexer().isNot(AsmToken::Comma)) {7686 SMLoc Loc = getLexer().getLoc();7687 return Error(Loc, ErrorStr);7688 }7689 7690 Parser.Lex(); // Eat the comma.7691 return true;7692}7693 7694// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.7695// In this class, it is only used for .cprestore.7696// FIXME: Only keep track of IsPicEnabled in one place, instead of in both7697// MipsTargetELFStreamer and MipsAsmParser.7698bool MipsAsmParser::isPicAndNotNxxAbi() {7699 return inPicMode() && !(isABI_N32() || isABI_N64());7700}7701 7702bool MipsAsmParser::parseDirectiveCpAdd(SMLoc Loc) {7703 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;7704 ParseStatus Res = parseAnyRegister(Reg);7705 if (Res.isNoMatch() || Res.isFailure()) {7706 reportParseError("expected register");7707 return false;7708 }7709 7710 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);7711 if (!RegOpnd.isGPRAsmReg()) {7712 reportParseError(RegOpnd.getStartLoc(), "invalid register");7713 return false;7714 }7715 7716 // If this is not the end of the statement, report an error.7717 if (getLexer().isNot(AsmToken::EndOfStatement)) {7718 reportParseError("unexpected token, expected end of statement");7719 return false;7720 }7721 getParser().Lex(); // Consume the EndOfStatement.7722 7723 getTargetStreamer().emitDirectiveCpAdd(RegOpnd.getGPR32Reg());7724 return false;7725}7726 7727bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {7728 if (AssemblerOptions.back()->isReorder())7729 Warning(Loc, ".cpload should be inside a noreorder section");7730 7731 if (inMips16Mode()) {7732 reportParseError(".cpload is not supported in Mips16 mode");7733 return false;7734 }7735 7736 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;7737 ParseStatus Res = parseAnyRegister(Reg);7738 if (Res.isNoMatch() || Res.isFailure()) {7739 reportParseError("expected register containing function address");7740 return false;7741 }7742 7743 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);7744 if (!RegOpnd.isGPRAsmReg()) {7745 reportParseError(RegOpnd.getStartLoc(), "invalid register");7746 return false;7747 }7748 7749 // If this is not the end of the statement, report an error.7750 if (getLexer().isNot(AsmToken::EndOfStatement)) {7751 reportParseError("unexpected token, expected end of statement");7752 return false;7753 }7754 7755 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());7756 return false;7757}7758 7759bool MipsAsmParser::parseDirectiveCpLocal(SMLoc Loc) {7760 if (!isABI_N32() && !isABI_N64()) {7761 reportParseError(".cplocal is allowed only in N32 or N64 mode");7762 return false;7763 }7764 7765 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;7766 ParseStatus Res = parseAnyRegister(Reg);7767 if (Res.isNoMatch() || Res.isFailure()) {7768 reportParseError("expected register containing global pointer");7769 return false;7770 }7771 7772 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);7773 if (!RegOpnd.isGPRAsmReg()) {7774 reportParseError(RegOpnd.getStartLoc(), "invalid register");7775 return false;7776 }7777 7778 // If this is not the end of the statement, report an error.7779 if (getLexer().isNot(AsmToken::EndOfStatement)) {7780 reportParseError("unexpected token, expected end of statement");7781 return false;7782 }7783 getParser().Lex(); // Consume the EndOfStatement.7784 7785 MCRegister NewReg = RegOpnd.getGPR32Reg();7786 if (IsPicEnabled)7787 GPReg = NewReg;7788 7789 getTargetStreamer().emitDirectiveCpLocal(NewReg);7790 return false;7791}7792 7793bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {7794 MCAsmParser &Parser = getParser();7795 7796 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it7797 // is used in non-PIC mode.7798 7799 if (inMips16Mode()) {7800 reportParseError(".cprestore is not supported in Mips16 mode");7801 return false;7802 }7803 7804 // Get the stack offset value.7805 const MCExpr *StackOffset;7806 int64_t StackOffsetVal;7807 if (Parser.parseExpression(StackOffset)) {7808 reportParseError("expected stack offset value");7809 return false;7810 }7811 7812 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {7813 reportParseError("stack offset is not an absolute expression");7814 return false;7815 }7816 7817 if (StackOffsetVal < 0) {7818 Warning(Loc, ".cprestore with negative stack offset has no effect");7819 IsCpRestoreSet = false;7820 } else {7821 IsCpRestoreSet = true;7822 CpRestoreOffset = StackOffsetVal;7823 }7824 7825 // If this is not the end of the statement, report an error.7826 if (getLexer().isNot(AsmToken::EndOfStatement)) {7827 reportParseError("unexpected token, expected end of statement");7828 return false;7829 }7830 7831 if (!getTargetStreamer().emitDirectiveCpRestore(7832 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))7833 return true;7834 Parser.Lex(); // Consume the EndOfStatement.7835 return false;7836}7837 7838bool MipsAsmParser::parseDirectiveCPSetup() {7839 MCAsmParser &Parser = getParser();7840 unsigned Save;7841 bool SaveIsReg = true;7842 7843 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;7844 ParseStatus Res = parseAnyRegister(TmpReg);7845 if (Res.isNoMatch()) {7846 reportParseError("expected register containing function address");7847 return false;7848 }7849 7850 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);7851 if (!FuncRegOpnd.isGPRAsmReg()) {7852 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");7853 return false;7854 }7855 7856 MCRegister FuncReg = FuncRegOpnd.getGPR32Reg();7857 TmpReg.clear();7858 7859 if (!eatComma("unexpected token, expected comma"))7860 return true;7861 7862 Res = parseAnyRegister(TmpReg);7863 if (Res.isNoMatch()) {7864 const MCExpr *OffsetExpr;7865 int64_t OffsetVal;7866 SMLoc ExprLoc = getLexer().getLoc();7867 7868 if (Parser.parseExpression(OffsetExpr) ||7869 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {7870 reportParseError(ExprLoc, "expected save register or stack offset");7871 return false;7872 }7873 7874 Save = OffsetVal;7875 SaveIsReg = false;7876 } else {7877 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);7878 if (!SaveOpnd.isGPRAsmReg()) {7879 reportParseError(SaveOpnd.getStartLoc(), "invalid register");7880 return false;7881 }7882 Save = SaveOpnd.getGPR32Reg().id();7883 }7884 7885 if (!eatComma("unexpected token, expected comma"))7886 return true;7887 7888 const MCExpr *Expr;7889 if (Parser.parseExpression(Expr)) {7890 reportParseError("expected expression");7891 return false;7892 }7893 7894 if (Expr->getKind() != MCExpr::SymbolRef) {7895 reportParseError("expected symbol");7896 return false;7897 }7898 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);7899 7900 CpSaveLocation = Save;7901 CpSaveLocationIsRegister = SaveIsReg;7902 7903 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),7904 SaveIsReg);7905 return false;7906}7907 7908bool MipsAsmParser::parseDirectiveCPReturn() {7909 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,7910 CpSaveLocationIsRegister);7911 return false;7912}7913 7914bool MipsAsmParser::parseDirectiveNaN() {7915 MCAsmParser &Parser = getParser();7916 if (getLexer().isNot(AsmToken::EndOfStatement)) {7917 const AsmToken &Tok = Parser.getTok();7918 7919 if (Tok.getString() == "2008") {7920 Parser.Lex();7921 getTargetStreamer().emitDirectiveNaN2008();7922 return false;7923 } else if (Tok.getString() == "legacy") {7924 Parser.Lex();7925 getTargetStreamer().emitDirectiveNaNLegacy();7926 return false;7927 }7928 }7929 // If we don't recognize the option passed to the .nan7930 // directive (e.g. no option or unknown option), emit an error.7931 reportParseError("invalid option in .nan directive");7932 return false;7933}7934 7935bool MipsAsmParser::parseDirectiveSet() {7936 const AsmToken &Tok = getParser().getTok();7937 StringRef IdVal = Tok.getString();7938 SMLoc Loc = Tok.getLoc();7939 7940 if (IdVal == "noat")7941 return parseSetNoAtDirective();7942 if (IdVal == "at")7943 return parseSetAtDirective();7944 if (IdVal == "arch")7945 return parseSetArchDirective();7946 if (IdVal == "bopt") {7947 Warning(Loc, "'bopt' feature is unsupported");7948 getParser().Lex();7949 return false;7950 }7951 if (IdVal == "nobopt") {7952 // We're already running in nobopt mode, so nothing to do.7953 getParser().Lex();7954 return false;7955 }7956 if (IdVal == "fp")7957 return parseSetFpDirective();7958 if (IdVal == "oddspreg")7959 return parseSetOddSPRegDirective();7960 if (IdVal == "nooddspreg")7961 return parseSetNoOddSPRegDirective();7962 if (IdVal == "pop")7963 return parseSetPopDirective();7964 if (IdVal == "push")7965 return parseSetPushDirective();7966 if (IdVal == "reorder")7967 return parseSetReorderDirective();7968 if (IdVal == "noreorder")7969 return parseSetNoReorderDirective();7970 if (IdVal == "macro")7971 return parseSetMacroDirective();7972 if (IdVal == "nomacro")7973 return parseSetNoMacroDirective();7974 if (IdVal == "mips16")7975 return parseSetMips16Directive();7976 if (IdVal == "nomips16")7977 return parseSetNoMips16Directive();7978 if (IdVal == "nomicromips") {7979 clearFeatureBits(Mips::FeatureMicroMips, "micromips");7980 getTargetStreamer().emitDirectiveSetNoMicroMips();7981 getParser().eatToEndOfStatement();7982 return false;7983 }7984 if (IdVal == "micromips") {7985 if (hasMips64r6()) {7986 Error(Loc, ".set micromips directive is not supported with MIPS64R6");7987 return false;7988 }7989 return parseSetFeature(Mips::FeatureMicroMips);7990 }7991 if (IdVal == "mips0")7992 return parseSetMips0Directive();7993 if (IdVal == "mips1")7994 return parseSetFeature(Mips::FeatureMips1);7995 if (IdVal == "mips2")7996 return parseSetFeature(Mips::FeatureMips2);7997 if (IdVal == "mips3")7998 return parseSetFeature(Mips::FeatureMips3);7999 if (IdVal == "mips4")8000 return parseSetFeature(Mips::FeatureMips4);8001 if (IdVal == "mips5")8002 return parseSetFeature(Mips::FeatureMips5);8003 if (IdVal == "mips32")8004 return parseSetFeature(Mips::FeatureMips32);8005 if (IdVal == "mips32r2")8006 return parseSetFeature(Mips::FeatureMips32r2);8007 if (IdVal == "mips32r3")8008 return parseSetFeature(Mips::FeatureMips32r3);8009 if (IdVal == "mips32r5")8010 return parseSetFeature(Mips::FeatureMips32r5);8011 if (IdVal == "mips32r6")8012 return parseSetFeature(Mips::FeatureMips32r6);8013 if (IdVal == "mips64")8014 return parseSetFeature(Mips::FeatureMips64);8015 if (IdVal == "mips64r2")8016 return parseSetFeature(Mips::FeatureMips64r2);8017 if (IdVal == "mips64r3")8018 return parseSetFeature(Mips::FeatureMips64r3);8019 if (IdVal == "mips64r5")8020 return parseSetFeature(Mips::FeatureMips64r5);8021 if (IdVal == "mips64r6") {8022 if (inMicroMipsMode()) {8023 Error(Loc, "MIPS64R6 is not supported with microMIPS");8024 return false;8025 }8026 return parseSetFeature(Mips::FeatureMips64r6);8027 }8028 if (IdVal == "dsp")8029 return parseSetFeature(Mips::FeatureDSP);8030 if (IdVal == "dspr2")8031 return parseSetFeature(Mips::FeatureDSPR2);8032 if (IdVal == "nodsp")8033 return parseSetNoDspDirective();8034 if (IdVal == "mips3d")8035 return parseSetFeature(Mips::FeatureMips3D);8036 if (IdVal == "nomips3d")8037 return parseSetNoMips3DDirective();8038 if (IdVal == "msa")8039 return parseSetMsaDirective();8040 if (IdVal == "nomsa")8041 return parseSetNoMsaDirective();8042 if (IdVal == "mt")8043 return parseSetMtDirective();8044 if (IdVal == "nomt")8045 return parseSetNoMtDirective();8046 if (IdVal == "softfloat")8047 return parseSetSoftFloatDirective();8048 if (IdVal == "hardfloat")8049 return parseSetHardFloatDirective();8050 if (IdVal == "crc")8051 return parseSetFeature(Mips::FeatureCRC);8052 if (IdVal == "nocrc")8053 return parseSetNoCRCDirective();8054 if (IdVal == "virt")8055 return parseSetFeature(Mips::FeatureVirt);8056 if (IdVal == "novirt")8057 return parseSetNoVirtDirective();8058 if (IdVal == "ginv")8059 return parseSetFeature(Mips::FeatureGINV);8060 if (IdVal == "noginv")8061 return parseSetNoGINVDirective();8062 8063 // It is just an identifier, look for an assignment.8064 return parseSetAssignment();8065}8066 8067/// parseDirectiveGpWord8068/// ::= .gpword local_sym8069bool MipsAsmParser::parseDirectiveGpWord() {8070 const MCExpr *Value;8071 if (getParser().parseExpression(Value))8072 return true;8073 getTargetStreamer().emitGPRel32Value(Value);8074 return parseEOL();8075}8076 8077/// parseDirectiveGpDWord8078/// ::= .gpdword local_sym8079bool MipsAsmParser::parseDirectiveGpDWord() {8080 const MCExpr *Value;8081 if (getParser().parseExpression(Value))8082 return true;8083 getTargetStreamer().emitGPRel64Value(Value);8084 return parseEOL();8085}8086 8087/// parseDirectiveDtpRelWord8088/// ::= .dtprelword tls_sym8089bool MipsAsmParser::parseDirectiveDtpRelWord() {8090 const MCExpr *Value;8091 if (getParser().parseExpression(Value))8092 return true;8093 getTargetStreamer().emitDTPRel32Value(Value);8094 return parseEOL();8095}8096 8097/// parseDirectiveDtpRelDWord8098/// ::= .dtpreldword tls_sym8099bool MipsAsmParser::parseDirectiveDtpRelDWord() {8100 const MCExpr *Value;8101 if (getParser().parseExpression(Value))8102 return true;8103 getTargetStreamer().emitDTPRel64Value(Value);8104 return parseEOL();8105}8106 8107/// parseDirectiveTpRelWord8108/// ::= .tprelword tls_sym8109bool MipsAsmParser::parseDirectiveTpRelWord() {8110 const MCExpr *Value;8111 if (getParser().parseExpression(Value))8112 return true;8113 getTargetStreamer().emitTPRel32Value(Value);8114 return parseEOL();8115}8116 8117/// parseDirectiveTpRelDWord8118/// ::= .tpreldword tls_sym8119bool MipsAsmParser::parseDirectiveTpRelDWord() {8120 const MCExpr *Value;8121 if (getParser().parseExpression(Value))8122 return true;8123 getTargetStreamer().emitTPRel64Value(Value);8124 return parseEOL();8125}8126 8127bool MipsAsmParser::parseDirectiveOption() {8128 MCAsmParser &Parser = getParser();8129 // Get the option token.8130 AsmToken Tok = Parser.getTok();8131 // At the moment only identifiers are supported.8132 if (Tok.isNot(AsmToken::Identifier)) {8133 return Error(Parser.getTok().getLoc(),8134 "unexpected token, expected identifier");8135 }8136 8137 StringRef Option = Tok.getIdentifier();8138 8139 if (Option == "pic0") {8140 // MipsAsmParser needs to know if the current PIC mode changes.8141 IsPicEnabled = false;8142 8143 getTargetStreamer().emitDirectiveOptionPic0();8144 Parser.Lex();8145 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {8146 return Error(Parser.getTok().getLoc(),8147 "unexpected token, expected end of statement");8148 }8149 return false;8150 }8151 8152 if (Option == "pic2") {8153 // MipsAsmParser needs to know if the current PIC mode changes.8154 IsPicEnabled = true;8155 8156 getTargetStreamer().emitDirectiveOptionPic2();8157 Parser.Lex();8158 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {8159 return Error(Parser.getTok().getLoc(),8160 "unexpected token, expected end of statement");8161 }8162 return false;8163 }8164 8165 // Unknown option.8166 Warning(Parser.getTok().getLoc(),8167 "unknown option, expected 'pic0' or 'pic2'");8168 Parser.eatToEndOfStatement();8169 return false;8170}8171 8172/// parseInsnDirective8173/// ::= .insn8174bool MipsAsmParser::parseInsnDirective() {8175 // If this is not the end of the statement, report an error.8176 if (getLexer().isNot(AsmToken::EndOfStatement)) {8177 reportParseError("unexpected token, expected end of statement");8178 return false;8179 }8180 8181 // The actual label marking happens in8182 // MipsELFStreamer::createPendingLabelRelocs().8183 getTargetStreamer().emitDirectiveInsn();8184 8185 getParser().Lex(); // Eat EndOfStatement token.8186 return false;8187}8188 8189/// parseRSectionDirective8190/// ::= .rdata8191bool MipsAsmParser::parseRSectionDirective(StringRef Section) {8192 // If this is not the end of the statement, report an error.8193 if (getLexer().isNot(AsmToken::EndOfStatement)) {8194 reportParseError("unexpected token, expected end of statement");8195 return false;8196 }8197 8198 MCSection *ELFSection = getContext().getELFSection(8199 Section, ELF::SHT_PROGBITS, ELF::SHF_ALLOC);8200 getParser().getStreamer().switchSection(ELFSection);8201 8202 getParser().Lex(); // Eat EndOfStatement token.8203 return false;8204}8205 8206/// parseSSectionDirective8207/// ::= .sbss8208/// ::= .sdata8209bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {8210 // If this is not the end of the statement, report an error.8211 if (getLexer().isNot(AsmToken::EndOfStatement)) {8212 reportParseError("unexpected token, expected end of statement");8213 return false;8214 }8215 8216 MCSection *ELFSection = getContext().getELFSection(8217 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);8218 getParser().getStreamer().switchSection(ELFSection);8219 8220 getParser().Lex(); // Eat EndOfStatement token.8221 return false;8222}8223 8224/// parseDirectiveModule8225/// ::= .module oddspreg8226/// ::= .module nooddspreg8227/// ::= .module fp=value8228/// ::= .module softfloat8229/// ::= .module hardfloat8230/// ::= .module mt8231/// ::= .module crc8232/// ::= .module nocrc8233/// ::= .module virt8234/// ::= .module novirt8235/// ::= .module ginv8236/// ::= .module noginv8237bool MipsAsmParser::parseDirectiveModule() {8238 MCAsmParser &Parser = getParser();8239 AsmLexer &Lexer = getLexer();8240 SMLoc L = Lexer.getLoc();8241 8242 if (!getTargetStreamer().isModuleDirectiveAllowed()) {8243 // TODO : get a better message.8244 reportParseError(".module directive must appear before any code");8245 return false;8246 }8247 8248 StringRef Option;8249 if (Parser.parseIdentifier(Option)) {8250 reportParseError("expected .module option identifier");8251 return false;8252 }8253 8254 if (Option == "oddspreg") {8255 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");8256 8257 // Synchronize the abiflags information with the FeatureBits information we8258 // changed above.8259 getTargetStreamer().updateABIInfo(*this);8260 8261 // If printing assembly, use the recently updated abiflags information.8262 // If generating ELF, don't do anything (the .MIPS.abiflags section gets8263 // emitted at the end).8264 getTargetStreamer().emitDirectiveModuleOddSPReg();8265 8266 // If this is not the end of the statement, report an error.8267 if (getLexer().isNot(AsmToken::EndOfStatement)) {8268 reportParseError("unexpected token, expected end of statement");8269 return false;8270 }8271 8272 return false; // parseDirectiveModule has finished successfully.8273 } else if (Option == "nooddspreg") {8274 if (!isABI_O32()) {8275 return Error(L, "'.module nooddspreg' requires the O32 ABI");8276 }8277 8278 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");8279 8280 // Synchronize the abiflags information with the FeatureBits information we8281 // changed above.8282 getTargetStreamer().updateABIInfo(*this);8283 8284 // If printing assembly, use the recently updated abiflags information.8285 // If generating ELF, don't do anything (the .MIPS.abiflags section gets8286 // emitted at the end).8287 getTargetStreamer().emitDirectiveModuleOddSPReg();8288 8289 // If this is not the end of the statement, report an error.8290 if (getLexer().isNot(AsmToken::EndOfStatement)) {8291 reportParseError("unexpected token, expected end of statement");8292 return false;8293 }8294 8295 return false; // parseDirectiveModule has finished successfully.8296 } else if (Option == "fp") {8297 return parseDirectiveModuleFP();8298 } else if (Option == "softfloat") {8299 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");8300 8301 // Synchronize the ABI Flags information with the FeatureBits information we8302 // updated above.8303 getTargetStreamer().updateABIInfo(*this);8304 8305 // If printing assembly, use the recently updated ABI Flags information.8306 // If generating ELF, don't do anything (the .MIPS.abiflags section gets8307 // emitted later).8308 getTargetStreamer().emitDirectiveModuleSoftFloat();8309 8310 // If this is not the end of the statement, report an error.8311 if (getLexer().isNot(AsmToken::EndOfStatement)) {8312 reportParseError("unexpected token, expected end of statement");8313 return false;8314 }8315 8316 return false; // parseDirectiveModule has finished successfully.8317 } else if (Option == "hardfloat") {8318 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");8319 8320 // Synchronize the ABI Flags information with the FeatureBits information we8321 // updated above.8322 getTargetStreamer().updateABIInfo(*this);8323 8324 // If printing assembly, use the recently updated ABI Flags information.8325 // If generating ELF, don't do anything (the .MIPS.abiflags section gets8326 // emitted later).8327 getTargetStreamer().emitDirectiveModuleHardFloat();8328 8329 // If this is not the end of the statement, report an error.8330 if (getLexer().isNot(AsmToken::EndOfStatement)) {8331 reportParseError("unexpected token, expected end of statement");8332 return false;8333 }8334 8335 return false; // parseDirectiveModule has finished successfully.8336 } else if (Option == "mt") {8337 setModuleFeatureBits(Mips::FeatureMT, "mt");8338 8339 // Synchronize the ABI Flags information with the FeatureBits information we8340 // updated above.8341 getTargetStreamer().updateABIInfo(*this);8342 8343 // If printing assembly, use the recently updated ABI Flags information.8344 // If generating ELF, don't do anything (the .MIPS.abiflags section gets8345 // emitted later).8346 getTargetStreamer().emitDirectiveModuleMT();8347 8348 // If this is not the end of the statement, report an error.8349 if (getLexer().isNot(AsmToken::EndOfStatement)) {8350 reportParseError("unexpected token, expected end of statement");8351 return false;8352 }8353 8354 return false; // parseDirectiveModule has finished successfully.8355 } else if (Option == "crc") {8356 setModuleFeatureBits(Mips::FeatureCRC, "crc");8357 8358 // Synchronize the ABI Flags information with the FeatureBits information we8359 // updated above.8360 getTargetStreamer().updateABIInfo(*this);8361 8362 // If printing assembly, use the recently updated ABI Flags information.8363 // If generating ELF, don't do anything (the .MIPS.abiflags section gets8364 // emitted later).8365 getTargetStreamer().emitDirectiveModuleCRC();8366 8367 // If this is not the end of the statement, report an error.8368 if (getLexer().isNot(AsmToken::EndOfStatement)) {8369 reportParseError("unexpected token, expected end of statement");8370 return false;8371 }8372 8373 return false; // parseDirectiveModule has finished successfully.8374 } else if (Option == "nocrc") {8375 clearModuleFeatureBits(Mips::FeatureCRC, "crc");8376 8377 // Synchronize the ABI Flags information with the FeatureBits information we8378 // updated above.8379 getTargetStreamer().updateABIInfo(*this);8380 8381 // If printing assembly, use the recently updated ABI Flags information.8382 // If generating ELF, don't do anything (the .MIPS.abiflags section gets8383 // emitted later).8384 getTargetStreamer().emitDirectiveModuleNoCRC();8385 8386 // If this is not the end of the statement, report an error.8387 if (getLexer().isNot(AsmToken::EndOfStatement)) {8388 reportParseError("unexpected token, expected end of statement");8389 return false;8390 }8391 8392 return false; // parseDirectiveModule has finished successfully.8393 } else if (Option == "virt") {8394 setModuleFeatureBits(Mips::FeatureVirt, "virt");8395 8396 // Synchronize the ABI Flags information with the FeatureBits information we8397 // updated above.8398 getTargetStreamer().updateABIInfo(*this);8399 8400 // If printing assembly, use the recently updated ABI Flags information.8401 // If generating ELF, don't do anything (the .MIPS.abiflags section gets8402 // emitted later).8403 getTargetStreamer().emitDirectiveModuleVirt();8404 8405 // If this is not the end of the statement, report an error.8406 if (getLexer().isNot(AsmToken::EndOfStatement)) {8407 reportParseError("unexpected token, expected end of statement");8408 return false;8409 }8410 8411 return false; // parseDirectiveModule has finished successfully.8412 } else if (Option == "novirt") {8413 clearModuleFeatureBits(Mips::FeatureVirt, "virt");8414 8415 // Synchronize the ABI Flags information with the FeatureBits information we8416 // updated above.8417 getTargetStreamer().updateABIInfo(*this);8418 8419 // If printing assembly, use the recently updated ABI Flags information.8420 // If generating ELF, don't do anything (the .MIPS.abiflags section gets8421 // emitted later).8422 getTargetStreamer().emitDirectiveModuleNoVirt();8423 8424 // If this is not the end of the statement, report an error.8425 if (getLexer().isNot(AsmToken::EndOfStatement)) {8426 reportParseError("unexpected token, expected end of statement");8427 return false;8428 }8429 8430 return false; // parseDirectiveModule has finished successfully.8431 } else if (Option == "ginv") {8432 setModuleFeatureBits(Mips::FeatureGINV, "ginv");8433 8434 // Synchronize the ABI Flags information with the FeatureBits information we8435 // updated above.8436 getTargetStreamer().updateABIInfo(*this);8437 8438 // If printing assembly, use the recently updated ABI Flags information.8439 // If generating ELF, don't do anything (the .MIPS.abiflags section gets8440 // emitted later).8441 getTargetStreamer().emitDirectiveModuleGINV();8442 8443 // If this is not the end of the statement, report an error.8444 if (getLexer().isNot(AsmToken::EndOfStatement)) {8445 reportParseError("unexpected token, expected end of statement");8446 return false;8447 }8448 8449 return false; // parseDirectiveModule has finished successfully.8450 } else if (Option == "noginv") {8451 clearModuleFeatureBits(Mips::FeatureGINV, "ginv");8452 8453 // Synchronize the ABI Flags information with the FeatureBits information we8454 // updated above.8455 getTargetStreamer().updateABIInfo(*this);8456 8457 // If printing assembly, use the recently updated ABI Flags information.8458 // If generating ELF, don't do anything (the .MIPS.abiflags section gets8459 // emitted later).8460 getTargetStreamer().emitDirectiveModuleNoGINV();8461 8462 // If this is not the end of the statement, report an error.8463 if (getLexer().isNot(AsmToken::EndOfStatement)) {8464 reportParseError("unexpected token, expected end of statement");8465 return false;8466 }8467 8468 return false; // parseDirectiveModule has finished successfully.8469 } else {8470 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");8471 }8472}8473 8474/// parseDirectiveModuleFP8475/// ::= =328476/// ::= =xx8477/// ::= =648478bool MipsAsmParser::parseDirectiveModuleFP() {8479 MCAsmParser &Parser = getParser();8480 AsmLexer &Lexer = getLexer();8481 8482 if (Lexer.isNot(AsmToken::Equal)) {8483 reportParseError("unexpected token, expected equals sign '='");8484 return false;8485 }8486 Parser.Lex(); // Eat '=' token.8487 8488 MipsABIFlagsSection::FpABIKind FpABI;8489 if (!parseFpABIValue(FpABI, ".module"))8490 return false;8491 8492 if (getLexer().isNot(AsmToken::EndOfStatement)) {8493 reportParseError("unexpected token, expected end of statement");8494 return false;8495 }8496 8497 // Synchronize the abiflags information with the FeatureBits information we8498 // changed above.8499 getTargetStreamer().updateABIInfo(*this);8500 8501 // If printing assembly, use the recently updated abiflags information.8502 // If generating ELF, don't do anything (the .MIPS.abiflags section gets8503 // emitted at the end).8504 getTargetStreamer().emitDirectiveModuleFP();8505 8506 Parser.Lex(); // Consume the EndOfStatement.8507 return false;8508}8509 8510bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,8511 StringRef Directive) {8512 MCAsmParser &Parser = getParser();8513 AsmLexer &Lexer = getLexer();8514 bool ModuleLevelOptions = Directive == ".module";8515 8516 if (Lexer.is(AsmToken::Identifier)) {8517 StringRef Value = Parser.getTok().getString();8518 Parser.Lex();8519 8520 if (Value != "xx") {8521 reportParseError("unsupported value, expected 'xx', '32' or '64'");8522 return false;8523 }8524 8525 if (!isABI_O32()) {8526 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");8527 return false;8528 }8529 8530 FpABI = MipsABIFlagsSection::FpABIKind::XX;8531 if (ModuleLevelOptions) {8532 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");8533 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");8534 } else {8535 setFeatureBits(Mips::FeatureFPXX, "fpxx");8536 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");8537 }8538 return true;8539 }8540 8541 if (Lexer.is(AsmToken::Integer)) {8542 unsigned Value = Parser.getTok().getIntVal();8543 Parser.Lex();8544 8545 if (Value != 32 && Value != 64) {8546 reportParseError("unsupported value, expected 'xx', '32' or '64'");8547 return false;8548 }8549 8550 if (Value == 32) {8551 if (!isABI_O32()) {8552 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");8553 return false;8554 }8555 8556 FpABI = MipsABIFlagsSection::FpABIKind::S32;8557 if (ModuleLevelOptions) {8558 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");8559 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");8560 } else {8561 clearFeatureBits(Mips::FeatureFPXX, "fpxx");8562 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");8563 }8564 } else {8565 FpABI = MipsABIFlagsSection::FpABIKind::S64;8566 if (ModuleLevelOptions) {8567 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");8568 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");8569 } else {8570 clearFeatureBits(Mips::FeatureFPXX, "fpxx");8571 setFeatureBits(Mips::FeatureFP64Bit, "fp64");8572 }8573 }8574 8575 return true;8576 }8577 8578 return false;8579}8580 8581bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {8582 // This returns false if this function recognizes the directive8583 // regardless of whether it is successfully handles or reports an8584 // error. Otherwise it returns true to give the generic parser a8585 // chance at recognizing it.8586 8587 MCAsmParser &Parser = getParser();8588 StringRef IDVal = DirectiveID.getString();8589 8590 if (IDVal == ".cpadd") {8591 parseDirectiveCpAdd(DirectiveID.getLoc());8592 return false;8593 }8594 if (IDVal == ".cpload") {8595 parseDirectiveCpLoad(DirectiveID.getLoc());8596 return false;8597 }8598 if (IDVal == ".cprestore") {8599 parseDirectiveCpRestore(DirectiveID.getLoc());8600 return false;8601 }8602 if (IDVal == ".cplocal") {8603 parseDirectiveCpLocal(DirectiveID.getLoc());8604 return false;8605 }8606 if (IDVal == ".ent") {8607 StringRef SymbolName;8608 8609 if (Parser.parseIdentifier(SymbolName)) {8610 reportParseError("expected identifier after .ent");8611 return false;8612 }8613 8614 // There's an undocumented extension that allows an integer to8615 // follow the name of the procedure which AFAICS is ignored by GAS.8616 // Example: .ent foo,28617 if (getLexer().isNot(AsmToken::EndOfStatement)) {8618 if (getLexer().isNot(AsmToken::Comma)) {8619 // Even though we accept this undocumented extension for compatibility8620 // reasons, the additional integer argument does not actually change8621 // the behaviour of the '.ent' directive, so we would like to discourage8622 // its use. We do this by not referring to the extended version in8623 // error messages which are not directly related to its use.8624 reportParseError("unexpected token, expected end of statement");8625 return false;8626 }8627 Parser.Lex(); // Eat the comma.8628 const MCExpr *DummyNumber;8629 int64_t DummyNumberVal;8630 // If the user was explicitly trying to use the extended version,8631 // we still give helpful extension-related error messages.8632 if (Parser.parseExpression(DummyNumber)) {8633 reportParseError("expected number after comma");8634 return false;8635 }8636 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {8637 reportParseError("expected an absolute expression after comma");8638 return false;8639 }8640 }8641 8642 // If this is not the end of the statement, report an error.8643 if (getLexer().isNot(AsmToken::EndOfStatement)) {8644 reportParseError("unexpected token, expected end of statement");8645 return false;8646 }8647 8648 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);8649 8650 getTargetStreamer().emitDirectiveEnt(*Sym);8651 CurrentFn = Sym;8652 IsCpRestoreSet = false;8653 return false;8654 }8655 8656 if (IDVal == ".end") {8657 StringRef SymbolName;8658 8659 if (Parser.parseIdentifier(SymbolName)) {8660 reportParseError("expected identifier after .end");8661 return false;8662 }8663 8664 if (getLexer().isNot(AsmToken::EndOfStatement)) {8665 reportParseError("unexpected token, expected end of statement");8666 return false;8667 }8668 8669 if (CurrentFn == nullptr) {8670 reportParseError(".end used without .ent");8671 return false;8672 }8673 8674 if ((SymbolName != CurrentFn->getName())) {8675 reportParseError(".end symbol does not match .ent symbol");8676 return false;8677 }8678 8679 getTargetStreamer().emitDirectiveEnd(SymbolName);8680 CurrentFn = nullptr;8681 IsCpRestoreSet = false;8682 return false;8683 }8684 8685 if (IDVal == ".frame") {8686 // .frame $stack_reg, frame_size_in_bytes, $return_reg8687 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;8688 ParseStatus Res = parseAnyRegister(TmpReg);8689 if (Res.isNoMatch() || Res.isFailure()) {8690 reportParseError("expected stack register");8691 return false;8692 }8693 8694 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);8695 if (!StackRegOpnd.isGPRAsmReg()) {8696 reportParseError(StackRegOpnd.getStartLoc(),8697 "expected general purpose register");8698 return false;8699 }8700 MCRegister StackReg = StackRegOpnd.getGPR32Reg();8701 8702 if (Parser.getTok().is(AsmToken::Comma))8703 Parser.Lex();8704 else {8705 reportParseError("unexpected token, expected comma");8706 return false;8707 }8708 8709 // Parse the frame size.8710 const MCExpr *FrameSize;8711 int64_t FrameSizeVal;8712 8713 if (Parser.parseExpression(FrameSize)) {8714 reportParseError("expected frame size value");8715 return false;8716 }8717 8718 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {8719 reportParseError("frame size not an absolute expression");8720 return false;8721 }8722 8723 if (Parser.getTok().is(AsmToken::Comma))8724 Parser.Lex();8725 else {8726 reportParseError("unexpected token, expected comma");8727 return false;8728 }8729 8730 // Parse the return register.8731 TmpReg.clear();8732 Res = parseAnyRegister(TmpReg);8733 if (Res.isNoMatch() || Res.isFailure()) {8734 reportParseError("expected return register");8735 return false;8736 }8737 8738 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);8739 if (!ReturnRegOpnd.isGPRAsmReg()) {8740 reportParseError(ReturnRegOpnd.getStartLoc(),8741 "expected general purpose register");8742 return false;8743 }8744 8745 // If this is not the end of the statement, report an error.8746 if (getLexer().isNot(AsmToken::EndOfStatement)) {8747 reportParseError("unexpected token, expected end of statement");8748 return false;8749 }8750 8751 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,8752 ReturnRegOpnd.getGPR32Reg());8753 IsCpRestoreSet = false;8754 return false;8755 }8756 8757 if (IDVal == ".set") {8758 parseDirectiveSet();8759 return false;8760 }8761 8762 if (IDVal == ".mask" || IDVal == ".fmask") {8763 // .mask bitmask, frame_offset8764 // bitmask: One bit for each register used.8765 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where8766 // first register is expected to be saved.8767 // Examples:8768 // .mask 0x80000000, -48769 // .fmask 0x80000000, -48770 //8771 8772 // Parse the bitmask8773 const MCExpr *BitMask;8774 int64_t BitMaskVal;8775 8776 if (Parser.parseExpression(BitMask)) {8777 reportParseError("expected bitmask value");8778 return false;8779 }8780 8781 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {8782 reportParseError("bitmask not an absolute expression");8783 return false;8784 }8785 8786 if (Parser.getTok().is(AsmToken::Comma))8787 Parser.Lex();8788 else {8789 reportParseError("unexpected token, expected comma");8790 return false;8791 }8792 8793 // Parse the frame_offset8794 const MCExpr *FrameOffset;8795 int64_t FrameOffsetVal;8796 8797 if (Parser.parseExpression(FrameOffset)) {8798 reportParseError("expected frame offset value");8799 return false;8800 }8801 8802 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {8803 reportParseError("frame offset not an absolute expression");8804 return false;8805 }8806 8807 // If this is not the end of the statement, report an error.8808 if (getLexer().isNot(AsmToken::EndOfStatement)) {8809 reportParseError("unexpected token, expected end of statement");8810 return false;8811 }8812 8813 if (IDVal == ".mask")8814 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);8815 else8816 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);8817 return false;8818 }8819 8820 if (IDVal == ".nan")8821 return parseDirectiveNaN();8822 8823 if (IDVal == ".gpword") {8824 parseDirectiveGpWord();8825 return false;8826 }8827 8828 if (IDVal == ".gpdword") {8829 parseDirectiveGpDWord();8830 return false;8831 }8832 8833 if (IDVal == ".dtprelword") {8834 parseDirectiveDtpRelWord();8835 return false;8836 }8837 8838 if (IDVal == ".dtpreldword") {8839 parseDirectiveDtpRelDWord();8840 return false;8841 }8842 8843 if (IDVal == ".tprelword") {8844 parseDirectiveTpRelWord();8845 return false;8846 }8847 8848 if (IDVal == ".tpreldword") {8849 parseDirectiveTpRelDWord();8850 return false;8851 }8852 8853 if (IDVal == ".option") {8854 parseDirectiveOption();8855 return false;8856 }8857 8858 if (IDVal == ".abicalls") {8859 getTargetStreamer().emitDirectiveAbiCalls();8860 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {8861 Error(Parser.getTok().getLoc(),8862 "unexpected token, expected end of statement");8863 }8864 return false;8865 }8866 8867 if (IDVal == ".cpsetup") {8868 parseDirectiveCPSetup();8869 return false;8870 }8871 if (IDVal == ".cpreturn") {8872 parseDirectiveCPReturn();8873 return false;8874 }8875 if (IDVal == ".module") {8876 parseDirectiveModule();8877 return false;8878 }8879 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {8880 parseInternalDirectiveReallowModule();8881 return false;8882 }8883 if (IDVal == ".insn") {8884 parseInsnDirective();8885 return false;8886 }8887 if (IDVal == ".rdata") {8888 parseRSectionDirective(".rodata");8889 return false;8890 }8891 if (IDVal == ".sbss") {8892 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);8893 return false;8894 }8895 if (IDVal == ".sdata") {8896 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);8897 return false;8898 }8899 8900 return true;8901}8902 8903bool MipsAsmParser::parseInternalDirectiveReallowModule() {8904 // If this is not the end of the statement, report an error.8905 if (getLexer().isNot(AsmToken::EndOfStatement)) {8906 reportParseError("unexpected token, expected end of statement");8907 return false;8908 }8909 8910 getTargetStreamer().reallowModuleDirective();8911 8912 getParser().Lex(); // Eat EndOfStatement token.8913 return false;8914}8915 8916extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void8917LLVMInitializeMipsAsmParser() {8918 RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget());8919 RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget());8920 RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target());8921 RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget());8922}8923 8924#define GET_REGISTER_MATCHER8925#define GET_MATCHER_IMPLEMENTATION8926#define GET_MNEMONIC_SPELL_CHECKER8927#include "MipsGenAsmMatcher.inc"8928 8929bool MipsAsmParser::mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {8930 // Find the appropriate table for this asm variant.8931 const MatchEntry *Start, *End;8932 switch (VariantID) {8933 default: llvm_unreachable("invalid variant!");8934 case 0: Start = std::begin(MatchTable0); End = std::end(MatchTable0); break;8935 }8936 // Search the table.8937 auto MnemonicRange = std::equal_range(Start, End, Mnemonic, LessOpcode());8938 return MnemonicRange.first != MnemonicRange.second;8939}8940