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