LLVM 22.0.0git
MipsAsmParser.cpp
Go to the documentation of this file.
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-exception
6//
7//===----------------------------------------------------------------------===//
8
16#include "llvm/ADT/APFloat.h"
18#include "llvm/ADT/StringRef.h"
20#include "llvm/ADT/Twine.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"
35#include "llvm/MC/MCStreamer.h"
37#include "llvm/MC/MCSymbol.h"
38#include "llvm/MC/MCSymbolELF.h"
39#include "llvm/MC/MCValue.h"
45#include "llvm/Support/Debug.h"
48#include "llvm/Support/SMLoc.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 llvm
69
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 referenced
106 // 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 namespace
120
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::FeatureNaN2008
131};
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;
145 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
146 // nullptr, which indicates that no function is currently
147 // 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_HEADER
169#include "MipsGenAsmMatcher.inc"
170
171 unsigned
172 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,
179 bool MatchingInlineAsm) override;
180
181 /// Parse a register as used in CFI directives
182 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 if
433 /// 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 the
443 // boundaries of accepted values for each RegisterKind
444 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
445 bool validateMSAIndex(int Val, int RegKind);
446
447 // Selects a new architecture by updating the FeatureBits with the necessary
448 // info including implied dependencies.
449 // Internally, it clears all the feature bits related to *any* architecture
450 // and selects the new one using the ToggleFeature functionality of the
451 // MCSubtargetInfo object that handles implied dependencies. The reason we
452 // clear all the arch related bits manually is because ToggleFeature only
453 // clears the features that imply the feature being cleared and not the
454 // features implied by the feature being cleared. This is easier to see
455 // 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_TYPES
520#include "MipsGenAsmMatcher.inc"
521#undef GET_OPERAND_DIAGNOSTIC_TYPES
522 };
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())) {
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 machine
748/// instruction.
749class MipsOperand : public MCParsedAsmOperand {
750public:
751 /// Broad categories of register classes
752 /// 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 and
756 /// isFP64bit())
757 RegKind_FCC = 4, /// FCC
758 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
759 RegKind_MSACtrl = 16, /// MSA control registers
760 RegKind_COP2 = 32, /// COP2
761 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
762 /// context).
763 RegKind_CCR = 128, /// CCR
764 RegKind_HWRegs = 256, /// HWRegs
765 RegKind_COP3 = 512, /// COP3
766 RegKind_COP0 = 1024, /// COP0
767 /// 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_COP0
771 };
772
773private:
774 enum KindTy {
775 k_Immediate, /// An immediate (possibly involving symbol references)
776 k_Memory, /// Base + Offset Memory Address
777 k_RegisterIndex, /// A register index in one or more RegKind.
778 k_Token, /// A simple token
779 k_RegList, /// A physical register list
780 } 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 temporary
802 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 class
811 RegKind Kind; /// Bitfield of the kinds it could possibly be
812 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 {
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 kinds
840 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 current
858 /// 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 current
867 /// 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 current
875 /// 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 current
884 /// 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 current
894 /// 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 current
902 /// 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 current
910 /// 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 current
918 /// 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 all
922 // identical
923 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 the
928 /// 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 the
936 /// 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 the
944 /// 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 the
952 /// 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 the
960 /// 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 the
968 /// 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 the
976 /// 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 the
984 /// 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 the
992 /// 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)
1004 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
1005 Inst.addOperand(MCOperand::createImm(CE->getValue()));
1006 else
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 GPR32
1015 /// Asserts if the wrong number of operands are requested, or the operand
1016 /// is not a k_RegisterIndex compatible with RegKind_GPR
1017 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 GPR64
1059 /// Asserts if the wrong number of operands are requested, or the operand
1060 /// is not a k_RegisterIndex compatible with RegKind_GPR
1061 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;
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;
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, accept
1234 // $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 plus
1364 // offset in case of relocations.
1365 if (Kind != k_Immediate)
1366 return false;
1367 MCValue Res;
1368 bool Success = getImm()->evaluateAsRelocatable(Res, nullptr);
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, accept
1415 // $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 too
1419
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 remains
1466 /// unresolved until an instruction successfully matches
1467 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 MipsOperand
1710
1711} // end anonymous namespace
1712
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/MIPS64r6
1950 // 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 above
1971 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::BBIT032
1980 : 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 get
1999 // processed here, not just the macros that need expansion.
2000 //
2001 // The MIPS backend models most of the divison instructions and macros as
2002 // three operand instructions. The pre-R6 divide instructions however have
2003 // 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 else
2019 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 else
2047 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 argument
2074 // 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 stages
2079 // 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 else
2090 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, symbol
2097 // 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
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 symbol
2115 // reference or immediate we may have to expand instructions.
2116 if (needsExpandMemInst(Inst, MCID)) {
2117 switch (MCID.operands()[MCID.getNumOperands() - 1].OperandType) {
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 } // for
2154 } // if load
2155
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 and
2282 // 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 reorder
2289 // 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 add
2294 // noreorder before instruction and reorder after it. So there
2295 // need exclude this case avoiding two '.set reorder'.
2296 // The format of the first case is:
2297 // .set noreorder
2298 // bnezc
2299 // nop
2300 // .set reorder
2301 if (AssemblerOptions.back()->isReorder() && !FillDelaySlot) {
2302 SetReorderAfterNop = true;
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' to
2310 // wrap the current instruction and the next instruction.
2311 CurForbiddenSlotAttr =
2312 hasForbiddenSlot(MCID) && AssemblerOptions.back()->isReorder();
2313
2314 if (FillDelaySlot || CurForbiddenSlotAttr)
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 noreoder
2332 // bnezc
2333 // add
2334 // .set reorder
2335 if (PrevForbiddenSlotAttr && !SetReorderAfterNop && !FillDelaySlot &&
2336 AssemblerOptions.back()->isReorder()) {
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 noreorder
2351 // bnezc
2352 // nop
2353 // .set noreorder
2354 // j
2355 // nop
2356 // .set reorder
2357 if (FillDelaySlot) {
2358 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst), IDLoc, STI);
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 } else
2376 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())
2390 }
2391}
2392
2393MipsAsmParser::MacroExpanderResultTy
2394MipsAsmParser::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_Fail
2413 : 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_Fail
2426 : MER_Success;
2427 case Mips::B_MM_Pseudo:
2428 case Mips::B_MMR6_Pseudo:
2429 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
2430 : MER_Success;
2431 case Mips::SWM_MM:
2432 case Mips::LWM_MM:
2433 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
2434 : 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_Fail
2481 : 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_Fail
2487 : 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_Fail
2493 : 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_Fail
2499 : MER_Success;
2500 case Mips::PseudoTRUNC_W_S:
2501 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2502 : MER_Success;
2503 case Mips::PseudoTRUNC_W_D32:
2504 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
2505 : MER_Success;
2506 case Mips::PseudoTRUNC_W_D:
2507 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2508 : MER_Success;
2509
2510 case Mips::LoadImmSingleGPR:
2511 return expandLoadSingleImmToGPR(Inst, IDLoc, Out, STI) ? MER_Fail
2512 : MER_Success;
2513 case Mips::LoadImmSingleFGR:
2514 return expandLoadSingleImmToFPR(Inst, IDLoc, Out, STI) ? MER_Fail
2515 : MER_Success;
2516 case Mips::LoadImmDoubleGPR:
2517 return expandLoadDoubleImmToGPR(Inst, IDLoc, Out, STI) ? MER_Fail
2518 : MER_Success;
2519 case Mips::LoadImmDoubleFGR:
2520 return expandLoadDoubleImmToFPR(Inst, true, IDLoc, Out, STI) ? MER_Fail
2521 : MER_Success;
2522 case Mips::LoadImmDoubleFGR_32:
2523 return expandLoadDoubleImmToFPR(Inst, false, IDLoc, Out, STI) ? MER_Fail
2524 : 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_Fail
2581 : 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_Fail
2593 : 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_Fail
2626 : MER_Success;
2627 case Mips::SDC1_M1:
2628 return expandStoreDM1Macro(Inst, IDLoc, Out, STI)
2629 ? MER_Fail
2630 : 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 $rs
2668 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, $rs
2681 if (IsCpRestoreSet && inMicroMipsMode())
2682 JalrInst.setOpcode(Mips::JALRS_MM);
2683 else
2684 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 it
2714/// 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 hardware
2730 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2731 // 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 is
2750 // 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 matches
2762 // traditional assembler behaviour. N32 would normally use addiu for both
2763 // 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's
2794 // 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 the
2804 // 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 be
2829 // 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 as
2834 // 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 zeros
2849 // 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, then
2858 // 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() ==
2955 // For O32, "$"-prefixed symbols are recognized as temporary while
2956 // .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 the
2963 // symbol in the final relocation is external and not modified with a
2964 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16
2965 // 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 =
2971 const MCExpr *CallLoExpr =
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 =
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 addresses
3001 // 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 XGOT
3005 // External GOT: lui $tmp, %got_hi(symbol)($gp)
3006 // addu $tmp, $tmp, $gp
3007 // lw $tmp, %got_lo(symbol)($tmp)
3008 // >addiu $tmp, $tmp, offset
3009 // >addiu $rd, $tmp, $rs
3010 // The addiu's marked with a '>' may be omitted if they are redundant. If
3011 // this happens then the last instruction must use $rd as the result
3012 // register.
3013 const MCExpr *CallHiExpr =
3015 const MCExpr *CallLoExpr = MCSpecifierExpr::create(
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,
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, offset
3043 // >daddu $rd, $tmp, $rs
3044 // The daddiu's marked with a '>' may be omitted if they are redundant. If
3045 // this happens then the last instruction must use $rd as the result
3046 // register.
3048 getContext());
3049 if (Res.getConstant() != 0) {
3050 // Symbols fully resolve with just the %got_disp(symbol) but we
3051 // must still account for any offset to the symbol for
3052 // expressions like symbol+8.
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, offset
3067 // >addiu $rd, $tmp, $rs
3068 // Local GOT: lw $tmp, %got(symbol+offset)($gp)
3069 // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
3070 // >addiu $rd, $tmp, $rs
3071 // The addiu's marked with a '>' may be omitted if they are redundant. If
3072 // this happens then the last instruction must use $rd as the result
3073 // 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 for
3080 // expressions like symbol+8.
3081 GotExpr =
3083 if (Res.getConstant() != 0)
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 =
3104 const auto *LoExpr =
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 optional
3110 // source register is the destination register and for the superscalar
3111 // scheduled form.
3112 //
3113 // If it is not available we exit if the destination is the same as the
3114 // source register.
3115
3116 const auto *HighestExpr =
3118 const auto *HigherExpr =
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, 16
3132 // daddiu $at, $at, %hi(sym)
3133 // dsll $at, $at, 16
3134 // daddiu $at, $at, %lo(sym)
3135 // daddu $rd, $at, $rd
3136 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 we
3153 // 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, 0
3159 // daddu $rd, $rd, $at
3160 // (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 register
3179 // serially:
3180 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3181 // daddiu $rd, $rd, %higher(sym)
3182 // dsll $rd, $rd, 16
3183 // daddiu $rd, $rd, %hi(sym)
3184 // dsll $rd, $rd, 16
3185 // 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 $at
3202 // 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, $rd
3216 // 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 else
3238 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 single
3245// 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.
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 number
3304// of instructions required to synthesize the immediate inline compared to
3305// 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 is
3307// likely to yield a much larger benefit as we have to synthesize a 64bit
3308// 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 =
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 { //!IsPicEnabled
3328 const MCExpr *HiSym = MCSymbolRefExpr::create(Sym, getContext());
3329 const auto *HiExpr =
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 with
3334 // 64-bit addresses).
3335 // FIXME: With -msym32 option, the address expansion for N64 should probably
3336 // use the O32 / N32 case. It's safe to use the 64 address expansion as the
3337 // 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 =
3344 const MCExpr *HigherSym = MCSymbolRefExpr::create(Sym, getContext());
3345 const auto *HigherExpr =
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
3362 // If ImmOp64 is AsmToken::Integer type (all bits set to zero in the
3363 // 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
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 sections
3427 // 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 sections
3557 // 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 microMIPS
3599 // 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 } else
3668 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 } else
3686 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],
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 expansions
3720 // 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 else
3730 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 increment
3738 // 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 relocations
3762 // do not exceed 16-bit.
3763 // d) Use R_MIPS_GOT_PAGE/R_MIPS_GOT_OFST relocations instead
3764 // of R_MIPS_GOT_DISP in appropriate cases to reduce number
3765 // 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(
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(
3789 MCOperand HiOperand = MCOperand::createExpr(
3791
3792 if (ABI.IsN64()) {
3793 MCOperand HighestOperand = MCOperand::createExpr(
3795 MCOperand HigherOperand = MCOperand::createExpr(
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],
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 expansions
3851 // 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 else
3861 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 else
3903 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 compatibility
4050 // with GAS' behaviour. However, they may not generate the most efficient
4051 // 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, it
4081 // 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 accept
4088 // 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) or
4095 // 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) or
4103 // 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 unconditional
4105 // 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) or
4114 // 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 is
4116 // different from 0, so we emit a BNEZ.
4117 //
4118 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
4119 // 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 is
4121 // equal to 0, so we emit a BEQZ.
4122 //
4123 // Because only BLEU and BGEU branch on equality, we can use the
4124 // 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 one
4132 // 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 the
4140 // 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" and
4150 // 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 BLT
4155 // and BLE with BGT), so we change the BNEZ into a BEQZ.
4156 // Because only BGE and BLE branch on equality, we can use the
4157 // AcceptsEquality variable to decide when to emit the BEQZ.
4158 // Note that the order of the SLT arguments doesn't change between
4159 // opposites.
4160 //
4161 // The same applies to the unsigned variants, except that SLTu is used
4162 // 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 $zero
4177// register, or 0 as an immediate. processInstruction() has already done that.
4178//
4179// The destination register can only be $zero when expanding (S)DivIMacro or
4180// 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 else
4206 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 else
4244 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 or
4269 // break, insert the trap/break and exit. This gives a different result to
4270 // GAS. GAS has an inconsistency/missed optimization in that not all cases
4271 // 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 does
4282 // 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 traget
4289 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();
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 =
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 source
4411 // 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 < $SrcReg
4682 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 else
4870 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 else
5087 FinalOpcode = Mips::DROTR;
5088 } else if (ImmValue >= 33) {
5089 if (Inst.getOpcode() == Mips::DROLImm)
5090 FinalOpcode = Mips::DROTR;
5091 else
5092 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 else
5168 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 =
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 =
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 the
5322 // 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 gpr
5539// operand. Unlike the other alias, the m(f|t)t(lo|hi|acx) instructions
5540// 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 register
5594// 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 producing
5673/// 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
5777unsigned
5778MipsAsmParser::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 for
5795 // 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 for
5802 // jalr.hb must be different.
5803 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
5804 // and registers Rd and Base for microMIPS lwp instruction
5805 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 registers
5828 // 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 their
5833 // 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 registers
5837 // would overflow must have rs >= rt. That can be handled like beqc/bnec with
5838 // 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,
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_32
6031 // 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
6167void
6168MipsAsmParser::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-t7
6219 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-t7
6236 // 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;
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 to
6418 // custom parse the operand, or fallback to the general approach.
6419 // Setting the third parameter to true tells the parser to keep parsing even
6420 // if the operands are not supported with the current feature set. In this
6421 // case, the instruction matcher will output a "instruction requires a CPU
6422 // feature not currently enabled" error. If this were false, the parser would
6423 // 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 that
6429 // 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 only
6441 // one exception to this. $zero (and it's alias $0) will reach this point
6442 // for div, divu, and similar instructions because it is not an operand
6443 // to the instruction definition but an explicit register. Special case
6444 // 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) {
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 CFI
6490 // directives.
6491 // Don't worry about eating tokens before failing. Using an unrecognised
6492 // 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 =
6533 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
6534 return ParseStatus::Success;
6535 }
6536 if (Tok.is(AsmToken::EndOfStatement)) {
6537 SMLoc E =
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 -1
6550 // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is
6551 // highly unlikely to be found in a memory offset expression, we don't
6552 // 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;
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
6742ParseStatus
6743MipsAsmParser::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 register
6755 // number as a normal one to continue parsing
6756 // 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
6770ParseStatus
6771MipsAsmParser::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(); // identifier
6799 }
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 acceptable
6815 const MCExpr *Expr = nullptr;
6816 if (Parser.parseExpression(Expr)) {
6817 // We have no way of knowing if a symbol was consumed so we must ParseFail
6818 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 reject
6829 // cases where it is not a register. Complicating the matter is that
6830 // 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()) == -1
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();
6853 MCRegister Reg;
6854 MCRegister PrevReg;
6855 bool RegRange = false;
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 range
6868 // 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 minus
6915 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 by
6928/// either this.
6929/// ::= '(', register, ')'
6930/// handle it before we iterate so we don't get tripped up by the lack of
6931/// 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 by
6954/// either one of these.
6955/// ::= '[', register, ']'
6956/// ::= '[', integer, ']'
6957/// handle it before we iterate so we don't get tripped up by the lack of
6958/// 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 for
6987 // e.g.
6988 // dahi $3, $3, 0x5678
6989 // as tested in test/MC/Mips/mips64r6/valid.s.
6990 // FIXME: Should this test actually fail with an error? If so, then remove
6991 // 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 mnemonic
7006 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 operand
7024
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 iterate
7033 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 be
7050// 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 $1
7082 // 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();
7294 // Line can be: .set fp=32
7295 // .set fp=xx
7296 // .set fp=64
7297 Parser.Lex(); // Eat fp token
7298 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 user
7439 // 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 comma
7499
7500 if (getLexer().is(AsmToken::Dollar) &&
7501 getLexer().peekTok().is(AsmToken::Integer)) {
7502 // Parse assignment of a numeric register:
7503 // .set r1,$1
7504 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 both
7697// MipsTargetELFStreamer and MipsAsmParser.
7698bool MipsAsmParser::isPicAndNotNxxAbi() {
7699 return inPicMode() && !(isABI_N32() || isABI_N64());
7700}
7701
7702bool MipsAsmParser::parseDirectiveCpAdd(SMLoc Loc) {
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
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
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 it
7797 // 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
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 .nan
7930 // 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/// parseDirectiveGpWord
8068/// ::= .gpword local_sym
8069bool MipsAsmParser::parseDirectiveGpWord() {
8070 const MCExpr *Value;
8071 if (getParser().parseExpression(Value))
8072 return true;
8073 getTargetStreamer().emitGPRel32Value(Value);
8074 return parseEOL();
8075}
8076
8077/// parseDirectiveGpDWord
8078/// ::= .gpdword local_sym
8079bool MipsAsmParser::parseDirectiveGpDWord() {
8080 const MCExpr *Value;
8081 if (getParser().parseExpression(Value))
8082 return true;
8083 getTargetStreamer().emitGPRel64Value(Value);
8084 return parseEOL();
8085}
8086
8087/// parseDirectiveDtpRelWord
8088/// ::= .dtprelword tls_sym
8089bool MipsAsmParser::parseDirectiveDtpRelWord() {
8090 const MCExpr *Value;
8091 if (getParser().parseExpression(Value))
8092 return true;
8093 getTargetStreamer().emitDTPRel32Value(Value);
8094 return parseEOL();
8095}
8096
8097/// parseDirectiveDtpRelDWord
8098/// ::= .dtpreldword tls_sym
8099bool MipsAsmParser::parseDirectiveDtpRelDWord() {
8100 const MCExpr *Value;
8101 if (getParser().parseExpression(Value))
8102 return true;
8103 getTargetStreamer().emitDTPRel64Value(Value);
8104 return parseEOL();
8105}
8106
8107/// parseDirectiveTpRelWord
8108/// ::= .tprelword tls_sym
8109bool MipsAsmParser::parseDirectiveTpRelWord() {
8110 const MCExpr *Value;
8111 if (getParser().parseExpression(Value))
8112 return true;
8113 getTargetStreamer().emitTPRel32Value(Value);
8114 return parseEOL();
8115}
8116
8117/// parseDirectiveTpRelDWord
8118/// ::= .tpreldword tls_sym
8119bool 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/// parseInsnDirective
8173/// ::= .insn
8174bool 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 in
8182 // MipsELFStreamer::createPendingLabelRelocs().
8183 getTargetStreamer().emitDirectiveInsn();
8184
8185 getParser().Lex(); // Eat EndOfStatement token.
8186 return false;
8187}
8188
8189/// parseRSectionDirective
8190/// ::= .rdata
8191bool 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(
8200 getParser().getStreamer().switchSection(ELFSection);
8201
8202 getParser().Lex(); // Eat EndOfStatement token.
8203 return false;
8204}
8205
8206/// parseSSectionDirective
8207/// ::= .sbss
8208/// ::= .sdata
8209bool 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(
8218 getParser().getStreamer().switchSection(ELFSection);
8219
8220 getParser().Lex(); // Eat EndOfStatement token.
8221 return false;
8222}
8223
8224/// parseDirectiveModule
8225/// ::= .module oddspreg
8226/// ::= .module nooddspreg
8227/// ::= .module fp=value
8228/// ::= .module softfloat
8229/// ::= .module hardfloat
8230/// ::= .module mt
8231/// ::= .module crc
8232/// ::= .module nocrc
8233/// ::= .module virt
8234/// ::= .module novirt
8235/// ::= .module ginv
8236/// ::= .module noginv
8237bool 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 we
8258 // 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 gets
8263 // 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 we
8281 // 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 gets
8286 // 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 we
8302 // 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 gets
8307 // 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 we
8321 // 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 gets
8326 // 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 we
8340 // 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 gets
8345 // 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 we
8359 // 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 gets
8364 // 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 we
8378 // 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 gets
8383 // 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 we
8397 // 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 gets
8402 // 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 we
8416 // 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 gets
8421 // 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 we
8435 // 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 gets
8440 // 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 we
8454 // 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 gets
8459 // 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/// parseDirectiveModuleFP
8475/// ::= =32
8476/// ::= =xx
8477/// ::= =64
8478bool 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
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 we
8498 // 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 gets
8503 // 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 directive
8583 // regardless of whether it is successfully handles or reports an
8584 // error. Otherwise it returns true to give the generic parser a
8585 // 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 to
8615 // follow the name of the procedure which AFAICS is ignored by GAS.
8616 // Example: .ent foo,2
8617 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8618 if (getLexer().isNot(AsmToken::Comma)) {
8619 // Even though we accept this undocumented extension for compatibility
8620 // reasons, the additional integer argument does not actually change
8621 // the behaviour of the '.ent' directive, so we would like to discourage
8622 // its use. We do this by not referring to the extended version in
8623 // 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_reg
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_offset
8764 // bitmask: One bit for each register used.
8765 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
8766 // first register is expected to be saved.
8767 // Examples:
8768 // .mask 0x80000000, -4
8769 // .fmask 0x80000000, -4
8770 //
8771
8772 // Parse the bitmask
8773 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_offset
8794 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 else
8816 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 void
8923
8924#define GET_REGISTER_MATCHER
8925#define GET_MATCHER_IMPLEMENTATION
8926#define GET_MNEMONIC_SPELL_CHECKER
8927#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}
static const TargetRegisterClass * getRegClass(const MachineInstr &MI, Register Reg)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)
This file declares a class to represent arbitrary precision floating point values and provide a varie...
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
Definition CSEInfo.cpp:27
#define LLVM_ABI
Definition Compiler.h:213
#define LLVM_EXTERNAL_VISIBILITY
Definition Compiler.h:132
static Value * expandAbs(CallInst *Orig)
#define op(i)
std::pair< Instruction::BinaryOps, Value * > OffsetOp
Find all possible pairs (BinOp, RHS) that BinOp V, RHS can be simplified.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static LVOptions Options
Definition LVOptions.cpp:25
static FeatureBitset getFeatures(MCSubtargetInfo &STI, StringRef CPU, StringRef TuneCPU, StringRef FS, ArrayRef< StringRef > ProcNames, ArrayRef< SubtargetSubTypeKV > ProcDesc, ArrayRef< SubtargetFeatureKV > ProcFeatures)
Register Reg
static unsigned countMCSymbolRefExpr(const MCExpr *Expr)
static std::string MipsMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS, unsigned VariantID=0)
static uint64_t convertIntToDoubleImm(uint64_t ImmOp64)
static uint32_t covertDoubleImmToSingleImm(uint64_t ImmOp64)
static unsigned getRegisterForMxtrDSP(MCInst &Inst, bool IsMFDSP)
static bool hasShortDelaySlot(MCInst &Inst)
LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMipsAsmParser()
static bool needsExpandMemInst(MCInst &Inst, const MCInstrDesc &MCID)
cl::opt< bool > EmitJalrReloc
static bool isShiftedUIntAtAnyPosition(uint64_t x)
Can the value be represented by a unsigned N-bit value and a shift left?
static bool isEvaluated(const MCExpr *Expr)
static unsigned getRegisterForMxtrC0(MCInst &Inst, bool IsMFTC0)
static const MCSymbol * getSingleMCSymbol(const MCExpr *Expr)
static MCRegister nextReg(MCRegister Reg)
static unsigned getRegisterForMxtrFP(MCInst &Inst, bool IsMFTC1)
static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands, uint64_t ErrorInfo)
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static bool isReg(const MCInst &MI, unsigned OpNo)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
static PPCTargetMachine::PPCABI computeTargetABI(const Triple &TT, const TargetOptions &Options)
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:480
This file defines the SmallVector class.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
#define LLVM_DEBUG(...)
Definition Debug.h:114
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
static std::optional< unsigned > getOpcode(ArrayRef< VPValue * > Values)
Returns the opcode of Values or ~0 if they do not all agree.
Definition VPlanSLP.cpp:247
static const fltSemantics & IEEEdouble()
Definition APFloat.h:297
APInt bitcastToAPInt() const
Definition APFloat.h:1335
uint64_t getZExtValue() const
Get zero extended value.
Definition APInt.h:1541
SMLoc getLoc() const
Get the current source location.
Definition AsmLexer.h:115
const AsmToken peekTok(bool ShouldSkipSpace=true)
Look ahead at the next token to be lexed.
Definition AsmLexer.h:121
bool is(AsmToken::TokenKind K) const
Check if the current token has kind K.
Definition AsmLexer.h:147
bool isNot(AsmToken::TokenKind K) const
Check if the current token has kind K.
Definition AsmLexer.h:150
Target independent representation for an assembler token.
Definition MCAsmMacro.h:22
LLVM_ABI SMLoc getLoc() const
Definition AsmLexer.cpp:31
int64_t getIntVal() const
Definition MCAsmMacro.h:108
bool isNot(TokenKind K) const
Definition MCAsmMacro.h:76
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
Definition MCAsmMacro.h:103
bool is(TokenKind K) const
Definition MCAsmMacro.h:75
TokenKind getKind() const
Definition MCAsmMacro.h:74
LLVM_ABI SMRange getLocRange() const
Definition AsmLexer.cpp:37
StringRef getIdentifier() const
Get the identifier string for the current token, which should be an identifier or a string.
Definition MCAsmMacro.h:92
Base class for user error types.
Definition Error.h:354
Container class for subtarget features.
void printExpr(raw_ostream &, const MCExpr &) const
virtual void Initialize(MCAsmParser &Parser)
Initialize the extension for parsing using the given Parser.
virtual void eatToEndOfStatement()=0
Skip to the end of the current statement, for error recovery.
bool parseToken(AsmToken::TokenKind T, const Twine &Msg="unexpected token")
virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc)=0
Parse an arbitrary expression.
AsmLexer & getLexer()
const AsmToken & getTok() const
Get the current AsmToken from the stream.
virtual bool parseIdentifier(StringRef &Res)=0
Parse an identifier or string (as a quoted identifier) and set Res to the identifier contents.
virtual const AsmToken & Lex()=0
Get the next AsmToken in the stream, possibly handling file inclusion first.
virtual void addAliasForDirective(StringRef Directive, StringRef Alias)=0
Binary assembler expressions.
Definition MCExpr.h:299
const MCExpr * getLHS() const
Get the left-hand side expression of the binary operator.
Definition MCExpr.h:446
const MCExpr * getRHS() const
Get the right-hand side expression of the binary operator.
Definition MCExpr.h:449
static LLVM_ABI const MCBinaryExpr * create(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.cpp:201
@ Div
Signed division.
Definition MCExpr.h:304
@ Shl
Shift left.
Definition MCExpr.h:321
@ LShr
Logical shift right.
Definition MCExpr.h:323
@ Sub
Subtraction.
Definition MCExpr.h:324
@ Mul
Multiplication.
Definition MCExpr.h:317
@ Mod
Signed remainder.
Definition MCExpr.h:316
@ And
Bitwise and.
Definition MCExpr.h:303
@ Or
Bitwise or.
Definition MCExpr.h:319
@ Xor
Bitwise exclusive or.
Definition MCExpr.h:325
@ Add
Addition.
Definition MCExpr.h:302
int64_t getValue() const
Definition MCExpr.h:171
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
Base class for the full range of assembler expressions which are needed for parsing.
Definition MCExpr.h:34
LLVM_ABI bool evaluateAsRelocatable(MCValue &Res, const MCAssembler *Asm) const
Try to evaluate the expression to a relocatable value, i.e.
Definition MCExpr.cpp:450
@ Unary
Unary expressions.
Definition MCExpr.h:44
@ Constant
Constant expressions.
Definition MCExpr.h:42
@ SymbolRef
References to labels and assigned expressions.
Definition MCExpr.h:43
@ Target
Target specific expression.
Definition MCExpr.h:46
@ Specifier
Expression with a relocation specifier.
Definition MCExpr.h:45
@ Binary
Binary expressions.
Definition MCExpr.h:41
ExprKind getKind() const
Definition MCExpr.h:85
SMLoc getLoc() const
Definition MCExpr.h:86
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
unsigned getNumOperands() const
Definition MCInst.h:212
SMLoc getLoc() const
Definition MCInst.h:208
void setLoc(SMLoc loc)
Definition MCInst.h:207
unsigned getOpcode() const
Definition MCInst.h:202
void addOperand(const MCOperand Op)
Definition MCInst.h:215
void setOpcode(unsigned Op)
Definition MCInst.h:201
void clear()
Definition MCInst.h:223
const MCOperand & getOperand(unsigned i) const
Definition MCInst.h:210
Describe properties that are true of each instruction in the target description file.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
ArrayRef< MCOperandInfo > operands() const
bool mayStore() const
Return true if this instruction could possibly modify memory.
bool mayLoad() const
Return true if this instruction could possibly read memory.
bool isBranch() const
Returns true if this is a conditional, unconditional, or indirect branch.
bool isCall() const
Return true if the instruction is a call.
bool hasDelaySlot() const
Returns true if the specified instruction has a delay slot which must be filled by the code generator...
Interface to description of machine instruction set.
Definition MCInstrInfo.h:27
This holds information about one operand of a machine instruction, indicating the register class for ...
Definition MCInstrDesc.h:87
uint8_t OperandType
Information about the type of the operand.
Instances of this class represent operands of the MCInst class.
Definition MCInst.h:40
void setImm(int64_t Val)
Definition MCInst.h:89
static MCOperand createExpr(const MCExpr *Val)
Definition MCInst.h:166
int64_t getImm() const
Definition MCInst.h:84
static MCOperand createReg(MCRegister Reg)
Definition MCInst.h:138
static MCOperand createImm(int64_t Val)
Definition MCInst.h:145
bool isImm() const
Definition MCInst.h:66
bool isReg() const
Definition MCInst.h:65
MCRegister getReg() const
Returns the register number.
Definition MCInst.h:73
const MCExpr * getExpr() const
Definition MCInst.h:118
bool isExpr() const
Definition MCInst.h:69
MCParsedAsmOperand - This abstract class represents a source-level assembly instruction operand.
virtual bool isReg() const =0
isReg - Is this a register operand?
virtual MCRegister getReg() const =0
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
constexpr bool isValid() const
Definition MCRegister.h:84
constexpr unsigned id() const
Definition MCRegister.h:82
static const MCSpecifierExpr * create(const MCExpr *Expr, Spec S, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.cpp:743
Streaming machine code generation interface.
Definition MCStreamer.h:220
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
virtual void emitRelocDirective(const MCExpr &Offset, StringRef Name, const MCExpr *Expr, SMLoc Loc={})
Record a relocation described by the .reloc directive.
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
void setFeatureBits(const FeatureBitset &FeatureBits_)
const Triple & getTargetTriple() const
const FeatureBitset & getFeatureBits() const
FeatureBitset ToggleFeature(uint64_t FB)
Toggle a feature and return the re-computed feature bits.
virtual unsigned getHwMode(enum HwModeType type=HwMode_Default) const
HwMode ID corresponding to the 'type' parameter is retrieved from the HwMode bit set of the current s...
Represent a reference to a symbol from inside an expression.
Definition MCExpr.h:190
uint16_t getSpecifier() const
Definition MCExpr.h:233
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:214
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
bool isInSection() const
isInSection - Check if this symbol is defined in some section (i.e., it is defined but not absolute).
Definition MCSymbol.h:237
bool isUndefined() const
isUndefined - Check if this symbol undefined (i.e., implicitly defined).
Definition MCSymbol.h:243
StringRef getName() const
getName - Get the symbol name.
Definition MCSymbol.h:188
bool isVariable() const
isVariable - Check if this is a variable symbol.
Definition MCSymbol.h:267
const MCExpr * getVariableValue() const
Get the expression of the variable symbol.
Definition MCSymbol.h:270
bool isTemporary() const
isTemporary - Check if this is an assembler temporary symbol.
Definition MCSymbol.h:205
MCTargetAsmParser - Generic interface to target specific assembly parsers.
MCStreamer & getStreamer()
Definition MCStreamer.h:101
MCContext & getContext()
Unary assembler expressions.
Definition MCExpr.h:243
const MCSymbol * getAddSym() const
Definition MCValue.h:49
int64_t getConstant() const
Definition MCValue.h:44
const MCSymbol * getSubSym() const
Definition MCValue.h:51
void emitRRX(unsigned Opcode, MCRegister Reg0, MCRegister Reg1, MCOperand Op2, SMLoc IDLoc, const MCSubtargetInfo *STI)
void emitRRRX(unsigned Opcode, MCRegister Reg0, MCRegister Reg1, MCRegister Reg2, MCOperand Op3, SMLoc IDLoc, const MCSubtargetInfo *STI)
void emitRX(unsigned Opcode, MCRegister Reg0, MCOperand Op1, SMLoc IDLoc, const MCSubtargetInfo *STI)
void emitR(unsigned Opcode, MCRegister Reg0, SMLoc IDLoc, const MCSubtargetInfo *STI)
void emitRRI(unsigned Opcode, MCRegister Reg0, MCRegister Reg1, int16_t Imm, SMLoc IDLoc, const MCSubtargetInfo *STI)
void emitEmptyDelaySlot(bool hasShortDelaySlot, SMLoc IDLoc, const MCSubtargetInfo *STI)
void emitRI(unsigned Opcode, MCRegister Reg0, int32_t Imm, SMLoc IDLoc, const MCSubtargetInfo *STI)
void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc, const MCSubtargetInfo *STI)
void emitRR(unsigned Opcode, MCRegister Reg0, MCRegister Reg1, SMLoc IDLoc, const MCSubtargetInfo *STI)
void updateABIInfo(const PredicateLibrary &P)
void emitRRIII(unsigned Opcode, MCRegister Reg0, MCRegister Reg1, int16_t Imm0, int16_t Imm1, int16_t Imm2, SMLoc IDLoc, const MCSubtargetInfo *STI)
void emitDSLL(MCRegister DstReg, MCRegister SrcReg, int16_t ShiftAmount, SMLoc IDLoc, const MCSubtargetInfo *STI)
void emitGPRestore(int Offset, SMLoc IDLoc, const MCSubtargetInfo *STI)
Emit the $gp restore operation for .cprestore.
void emitNop(SMLoc IDLoc, const MCSubtargetInfo *STI)
void emitRRR(unsigned Opcode, MCRegister Reg0, MCRegister Reg1, MCRegister Reg2, SMLoc IDLoc, const MCSubtargetInfo *STI)
virtual void emitDirectiveSetNoReorder()
Ternary parse status returned by various parse* methods.
constexpr bool isFailure() const
static constexpr StatusTy Failure
constexpr bool isSuccess() const
static constexpr StatusTy Success
static constexpr StatusTy NoMatch
constexpr bool isNoMatch() const
constexpr unsigned id() const
Definition Register.h:100
Represents a location in source code.
Definition SMLoc.h:22
static SMLoc getFromPointer(const char *Ptr)
Definition SMLoc.h:35
constexpr const char * getPointer() const
Definition SMLoc.h:33
void push_back(const T &Elt)
iterator end()
Definition StringMap.h:224
iterator find(StringRef Key)
Definition StringMap.h:237
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition StringRef.h:472
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition StringRef.h:573
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition StringRef.h:261
constexpr bool empty() const
empty - Check if the string is empty.
Definition StringRef.h:143
LLVM_ABI bool isLittleEndian() const
Tests whether the target triple is little endian.
Definition Triple.cpp:2082
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
@ Entry
Definition COFF.h:862
@ SHF_ALLOC
Definition ELF.h:1248
@ SHF_MIPS_GPREL
Definition ELF.h:1331
@ SHF_WRITE
Definition ELF.h:1245
@ SHT_PROGBITS
Definition ELF.h:1147
@ SHT_NOBITS
Definition ELF.h:1154
@ STB_LOCAL
Definition ELF.h:1404
bool parseAssignmentExpression(StringRef Name, bool allow_redef, MCAsmParser &Parser, MCSymbol *&Symbol, const MCExpr *&Value)
Parse a value expression and return whether it can be assigned to a symbol with the given name.
@ CE
Windows NT (Windows on ARM)
Definition MCAsmInfo.h:48
LLVM_ABI std::string getABIName()
Context & getContext() const
Definition BasicBlock.h:99
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
Definition SFrame.h:77
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:532
FunctionAddr VTableAddr Value
Definition InstrProf.h:137
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:165
Target & getTheMips64Target()
static bool isMem(const MachineInstr &MI, unsigned Op)
LLVM_ABI std::pair< StringRef, StringRef > getToken(StringRef Source, StringRef Delimiters=" \t\n\v\f\r")
getToken - This function extracts one token from source, ignoring any leading characters that appear ...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
static StringRef getCPU(StringRef CPU)
Processes a CPU name.
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
Definition bit.h:303
Op::Description Desc
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
Definition bit.h:202
SmallVectorImpl< std::unique_ptr< MCParsedAsmOperand > > OperandVector
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
Definition MathExtras.h:150
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:167
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:189
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
Definition MathExtras.h:155
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
@ Success
The lock was released successfully.
Target & getTheMips64elTarget()
uint64_t offsetToAlignment(uint64_t Value, Align Alignment)
Returns the offset to the next integer (mod 2**64) that is greater than or equal to Value and is a mu...
Definition Alignment.h:186
@ Ref
The access may reference the value stored in memory.
Definition ModRef.h:32
@ Other
Any other memory.
Definition ModRef.h:68
To bit_cast(const From &from) noexcept
Definition bit.h:90
Target & getTheMipselTarget()
DWARFExpression::Operation Op
constexpr bool isShiftedInt(int64_t x)
Checks if a signed integer is an N bit number shifted left by S.
Definition MathExtras.h:182
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Definition MathExtras.h:248
static uint16_t getSpecifier(const MCSymbolRefExpr *SRE)
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
Definition MathExtras.h:572
Target & getTheMipsTarget()
constexpr bool isShiftedUInt(uint64_t x)
Checks if a unsigned integer is an N bit number shifted left by S.
Definition MathExtras.h:198
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:869
#define N
RegisterMCAsmParser - Helper template for registering a target specific assembly parser,...