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 if (!Inst.getOperand(0).isExpr()) {
2112 return Error(IDLoc, "unsupported constant in relocation");
2113 }
2114
2115 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
2116
2117 // We can do this expansion if there's only 1 symbol in the argument
2118 // expression.
2119 if (countMCSymbolRefExpr(JalExpr) > 1)
2120 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
2121
2122 // FIXME: This is checking the expression can be handled by the later stages
2123 // of the assembler. We ought to leave it to those later stages.
2124 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
2125
2126 if (expandLoadAddress(Mips::T9, Mips::NoRegister, Inst.getOperand(0),
2127 !isGP64bit(), IDLoc, Out, STI))
2128 return true;
2129
2130 MCInst JalrInst;
2131 if (inMicroMipsMode())
2132 JalrInst.setOpcode(IsCpRestoreSet ? Mips::JALRS_MM : Mips::JALR_MM);
2133 else
2134 JalrInst.setOpcode(Mips::JALR);
2135 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
2136 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
2137
2138 if (isJalrRelocAvailable(JalExpr)) {
2139 // As an optimization hint for the linker, before the JALR we add:
2140 // .reloc tmplabel, R_{MICRO}MIPS_JALR, symbol
2141 // tmplabel:
2142 MCSymbol *TmpLabel = getContext().createTempSymbol();
2143 const MCExpr *TmpExpr = MCSymbolRefExpr::create(TmpLabel, getContext());
2144 const MCExpr *RelocJalrExpr =
2146 getContext(), IDLoc);
2147
2149 *TmpExpr, inMicroMipsMode() ? "R_MICROMIPS_JALR" : "R_MIPS_JALR",
2150 RelocJalrExpr, IDLoc, *STI);
2151 TOut.getStreamer().emitLabel(TmpLabel);
2152 }
2153
2154 Inst = JalrInst;
2155 ExpandedJalSym = true;
2156 }
2157
2158 if (MCID.mayLoad() || MCID.mayStore()) {
2159 // Check the offset of memory operand, if it is a symbol
2160 // reference or immediate we may have to expand instructions.
2161 if (needsExpandMemInst(Inst, MCID)) {
2162 switch (MCID.operands()[MCID.getNumOperands() - 1].OperandType) {
2164 expandMem9Inst(Inst, IDLoc, Out, STI, MCID.mayLoad());
2165 break;
2166 default:
2167 expandMem16Inst(Inst, IDLoc, Out, STI, MCID.mayLoad());
2168 break;
2169 }
2170 return getParser().hasPendingError();
2171 }
2172 }
2173
2174 if (inMicroMipsMode()) {
2175 if (MCID.mayLoad() && Opcode != Mips::LWP_MM) {
2176 // Try to create 16-bit GP relative load instruction.
2177 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
2178 const MCOperandInfo &OpInfo = MCID.operands()[i];
2179 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2180 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
2181 MCOperand &Op = Inst.getOperand(i);
2182 if (Op.isImm()) {
2183 int MemOffset = Op.getImm();
2184 MCOperand &DstReg = Inst.getOperand(0);
2185 MCOperand &BaseReg = Inst.getOperand(1);
2186 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
2187 getContext().getRegisterInfo()->getRegClass(
2188 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
2189 (BaseReg.getReg() == Mips::GP ||
2190 BaseReg.getReg() == Mips::GP_64)) {
2191
2192 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
2193 IDLoc, STI);
2194 return false;
2195 }
2196 }
2197 }
2198 } // for
2199 } // if load
2200
2201 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
2202
2203 MCOperand Opnd;
2204 int Imm;
2205
2206 switch (Opcode) {
2207 default:
2208 break;
2209 case Mips::ADDIUSP_MM:
2210 Opnd = Inst.getOperand(0);
2211 if (!Opnd.isImm())
2212 return Error(IDLoc, "expected immediate operand kind");
2213 Imm = Opnd.getImm();
2214 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
2215 Imm % 4 != 0)
2216 return Error(IDLoc, "immediate operand value out of range");
2217 break;
2218 case Mips::SLL16_MM:
2219 case Mips::SRL16_MM:
2220 Opnd = Inst.getOperand(2);
2221 if (!Opnd.isImm())
2222 return Error(IDLoc, "expected immediate operand kind");
2223 Imm = Opnd.getImm();
2224 if (Imm < 1 || Imm > 8)
2225 return Error(IDLoc, "immediate operand value out of range");
2226 break;
2227 case Mips::LI16_MM:
2228 Opnd = Inst.getOperand(1);
2229 if (!Opnd.isImm())
2230 return Error(IDLoc, "expected immediate operand kind");
2231 Imm = Opnd.getImm();
2232 if (Imm < -1 || Imm > 126)
2233 return Error(IDLoc, "immediate operand value out of range");
2234 break;
2235 case Mips::ADDIUR2_MM:
2236 Opnd = Inst.getOperand(2);
2237 if (!Opnd.isImm())
2238 return Error(IDLoc, "expected immediate operand kind");
2239 Imm = Opnd.getImm();
2240 if (!(Imm == 1 || Imm == -1 ||
2241 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
2242 return Error(IDLoc, "immediate operand value out of range");
2243 break;
2244 case Mips::ANDI16_MM:
2245 Opnd = Inst.getOperand(2);
2246 if (!Opnd.isImm())
2247 return Error(IDLoc, "expected immediate operand kind");
2248 Imm = Opnd.getImm();
2249 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
2250 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
2251 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
2252 return Error(IDLoc, "immediate operand value out of range");
2253 break;
2254 case Mips::LBU16_MM:
2255 Opnd = Inst.getOperand(2);
2256 if (!Opnd.isImm())
2257 return Error(IDLoc, "expected immediate operand kind");
2258 Imm = Opnd.getImm();
2259 if (Imm < -1 || Imm > 14)
2260 return Error(IDLoc, "immediate operand value out of range");
2261 break;
2262 case Mips::SB16_MM:
2263 case Mips::SB16_MMR6:
2264 Opnd = Inst.getOperand(2);
2265 if (!Opnd.isImm())
2266 return Error(IDLoc, "expected immediate operand kind");
2267 Imm = Opnd.getImm();
2268 if (Imm < 0 || Imm > 15)
2269 return Error(IDLoc, "immediate operand value out of range");
2270 break;
2271 case Mips::LHU16_MM:
2272 case Mips::SH16_MM:
2273 case Mips::SH16_MMR6:
2274 Opnd = Inst.getOperand(2);
2275 if (!Opnd.isImm())
2276 return Error(IDLoc, "expected immediate operand kind");
2277 Imm = Opnd.getImm();
2278 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
2279 return Error(IDLoc, "immediate operand value out of range");
2280 break;
2281 case Mips::LW16_MM:
2282 case Mips::SW16_MM:
2283 case Mips::SW16_MMR6:
2284 Opnd = Inst.getOperand(2);
2285 if (!Opnd.isImm())
2286 return Error(IDLoc, "expected immediate operand kind");
2287 Imm = Opnd.getImm();
2288 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
2289 return Error(IDLoc, "immediate operand value out of range");
2290 break;
2291 case Mips::ADDIUPC_MM:
2292 Opnd = Inst.getOperand(1);
2293 if (!Opnd.isImm())
2294 return Error(IDLoc, "expected immediate operand kind");
2295 Imm = Opnd.getImm();
2296 if ((Imm % 4 != 0) || !isInt<25>(Imm))
2297 return Error(IDLoc, "immediate operand value out of range");
2298 break;
2299 case Mips::LWP_MM:
2300 case Mips::SWP_MM:
2301 if (Inst.getOperand(0).getReg() == Mips::RA)
2302 return Error(IDLoc, "invalid operand for instruction");
2303 break;
2304 case Mips::MOVEP_MM:
2305 case Mips::MOVEP_MMR6: {
2306 unsigned R0 = Inst.getOperand(0).getReg();
2307 unsigned R1 = Inst.getOperand(1).getReg();
2308 bool RegPair = ((R0 == Mips::A1 && R1 == Mips::A2) ||
2309 (R0 == Mips::A1 && R1 == Mips::A3) ||
2310 (R0 == Mips::A2 && R1 == Mips::A3) ||
2311 (R0 == Mips::A0 && R1 == Mips::S5) ||
2312 (R0 == Mips::A0 && R1 == Mips::S6) ||
2313 (R0 == Mips::A0 && R1 == Mips::A1) ||
2314 (R0 == Mips::A0 && R1 == Mips::A2) ||
2315 (R0 == Mips::A0 && R1 == Mips::A3));
2316 if (!RegPair)
2317 return Error(IDLoc, "invalid operand for instruction");
2318 break;
2319 }
2320 }
2321 }
2322
2323 bool FillDelaySlot =
2324 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
2325
2326 // Get previous instruction`s forbidden slot attribute and
2327 // whether set reorder.
2328 bool PrevForbiddenSlotAttr = CurForbiddenSlotAttr;
2329
2330 // Flag represents we set reorder after nop.
2331 bool SetReorderAfterNop = false;
2332
2333 // If previous instruction has forbidden slot and .set reorder
2334 // is active and current instruction is CTI.
2335 // Then emit a NOP after it.
2336 if (PrevForbiddenSlotAttr && !SafeInForbiddenSlot(MCID)) {
2337 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
2338 // When 'FillDelaySlot' is true, the existing logic will add
2339 // noreorder before instruction and reorder after it. So there
2340 // need exclude this case avoiding two '.set reorder'.
2341 // The format of the first case is:
2342 // .set noreorder
2343 // bnezc
2344 // nop
2345 // .set reorder
2346 if (AssemblerOptions.back()->isReorder() && !FillDelaySlot) {
2347 SetReorderAfterNop = true;
2349 }
2350 }
2351
2352 // Save current instruction`s forbidden slot and whether set reorder.
2353 // This is the judgment condition for whether to add nop.
2354 // We would add a couple of '.set noreorder' and '.set reorder' to
2355 // wrap the current instruction and the next instruction.
2356 CurForbiddenSlotAttr =
2357 hasForbiddenSlot(MCID) && AssemblerOptions.back()->isReorder();
2358
2359 if (FillDelaySlot || CurForbiddenSlotAttr)
2361
2362 MacroExpanderResultTy ExpandResult =
2363 tryExpandInstruction(Inst, IDLoc, Out, STI);
2364 switch (ExpandResult) {
2365 case MER_NotAMacro:
2366 Out.emitInstruction(Inst, *STI);
2367 break;
2368 case MER_Success:
2369 break;
2370 case MER_Fail:
2371 return true;
2372 }
2373
2374 // When current instruction was not CTI, recover reorder state.
2375 // The format of the second case is:
2376 // .set noreoder
2377 // bnezc
2378 // add
2379 // .set reorder
2380 if (PrevForbiddenSlotAttr && !SetReorderAfterNop && !FillDelaySlot &&
2381 AssemblerOptions.back()->isReorder()) {
2383 }
2384
2385 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
2386 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
2387 if (inMicroMipsMode()) {
2388 TOut.setUsesMicroMips();
2389 TOut.updateABIInfo(*this);
2390 }
2391
2392 // If this instruction has a delay slot and .set reorder is active,
2393 // emit a NOP after it.
2394 // The format of the third case is:
2395 // .set noreorder
2396 // bnezc
2397 // nop
2398 // .set noreorder
2399 // j
2400 // nop
2401 // .set reorder
2402 if (FillDelaySlot) {
2403 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst), IDLoc, STI);
2405 }
2406
2407 if ((Opcode == Mips::JalOneReg || Opcode == Mips::JalTwoReg ||
2408 ExpandedJalSym) &&
2409 isPicAndNotNxxAbi()) {
2410 if (IsCpRestoreSet) {
2411 // We need a NOP between the JALR and the LW:
2412 // If .set reorder has been used, we've already emitted a NOP.
2413 // If .set noreorder has been used, we need to emit a NOP at this point.
2414 if (!AssemblerOptions.back()->isReorder())
2415 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst), IDLoc,
2416 STI);
2417
2418 // Load the $gp from the stack.
2419 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
2420 } else
2421 Warning(IDLoc, "no .cprestore used in PIC mode");
2422 }
2423
2424 return false;
2425}
2426
2427void MipsAsmParser::onEndOfFile() {
2428 MipsTargetStreamer &TOut = getTargetStreamer();
2429 SMLoc IDLoc = SMLoc();
2430 // If has pending forbidden slot, fill nop and recover reorder.
2431 if (CurForbiddenSlotAttr) {
2432 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
2433 if (AssemblerOptions.back()->isReorder())
2435 }
2436}
2437
2438MipsAsmParser::MacroExpanderResultTy
2439MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2440 const MCSubtargetInfo *STI) {
2441 switch (Inst.getOpcode()) {
2442 default:
2443 return MER_NotAMacro;
2444 case Mips::LoadImm32:
2445 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2446 case Mips::LoadImm64:
2447 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2448 case Mips::LoadAddrImm32:
2449 case Mips::LoadAddrImm64:
2450 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2451 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
2452 "expected immediate operand kind");
2453
2454 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
2455 Inst.getOperand(1),
2456 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
2457 Out, STI)
2458 ? MER_Fail
2459 : MER_Success;
2460 case Mips::LoadAddrReg32:
2461 case Mips::LoadAddrReg64:
2462 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2463 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2464 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
2465 "expected immediate operand kind");
2466
2467 return expandLoadAddress(Inst.getOperand(0).getReg(),
2468 Inst.getOperand(1).getReg(), Inst.getOperand(2),
2469 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
2470 Out, STI)
2471 ? MER_Fail
2472 : MER_Success;
2473 case Mips::B_MM_Pseudo:
2474 case Mips::B_MMR6_Pseudo:
2475 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
2476 : MER_Success;
2477 case Mips::SWM_MM:
2478 case Mips::LWM_MM:
2479 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
2480 : MER_Success;
2481 case Mips::JalOneReg:
2482 case Mips::JalTwoReg:
2483 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2484 case Mips::BneImm:
2485 case Mips::BeqImm:
2486 case Mips::BEQLImmMacro:
2487 case Mips::BNELImmMacro:
2488 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2489 case Mips::BLT:
2490 case Mips::BLE:
2491 case Mips::BGE:
2492 case Mips::BGT:
2493 case Mips::BLTU:
2494 case Mips::BLEU:
2495 case Mips::BGEU:
2496 case Mips::BGTU:
2497 case Mips::BLTL:
2498 case Mips::BLEL:
2499 case Mips::BGEL:
2500 case Mips::BGTL:
2501 case Mips::BLTUL:
2502 case Mips::BLEUL:
2503 case Mips::BGEUL:
2504 case Mips::BGTUL:
2505 case Mips::BLTImmMacro:
2506 case Mips::BLEImmMacro:
2507 case Mips::BGEImmMacro:
2508 case Mips::BGTImmMacro:
2509 case Mips::BLTUImmMacro:
2510 case Mips::BLEUImmMacro:
2511 case Mips::BGEUImmMacro:
2512 case Mips::BGTUImmMacro:
2513 case Mips::BLTLImmMacro:
2514 case Mips::BLELImmMacro:
2515 case Mips::BGELImmMacro:
2516 case Mips::BGTLImmMacro:
2517 case Mips::BLTULImmMacro:
2518 case Mips::BLEULImmMacro:
2519 case Mips::BGEULImmMacro:
2520 case Mips::BGTULImmMacro:
2521 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2522 case Mips::SDivMacro:
2523 case Mips::SDivIMacro:
2524 case Mips::SRemMacro:
2525 case Mips::SRemIMacro:
2526 return expandDivRem(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2527 : MER_Success;
2528 case Mips::DSDivMacro:
2529 case Mips::DSDivIMacro:
2530 case Mips::DSRemMacro:
2531 case Mips::DSRemIMacro:
2532 return expandDivRem(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2533 : MER_Success;
2534 case Mips::UDivMacro:
2535 case Mips::UDivIMacro:
2536 case Mips::URemMacro:
2537 case Mips::URemIMacro:
2538 return expandDivRem(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2539 : MER_Success;
2540 case Mips::DUDivMacro:
2541 case Mips::DUDivIMacro:
2542 case Mips::DURemMacro:
2543 case Mips::DURemIMacro:
2544 return expandDivRem(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2545 : MER_Success;
2546 case Mips::PseudoTRUNC_W_S:
2547 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2548 : MER_Success;
2549 case Mips::PseudoTRUNC_W_D32:
2550 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
2551 : MER_Success;
2552 case Mips::PseudoTRUNC_W_D:
2553 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2554 : MER_Success;
2555
2556 case Mips::LoadImmSingleGPR:
2557 return expandLoadSingleImmToGPR(Inst, IDLoc, Out, STI) ? MER_Fail
2558 : MER_Success;
2559 case Mips::LoadImmSingleFGR:
2560 return expandLoadSingleImmToFPR(Inst, IDLoc, Out, STI) ? MER_Fail
2561 : MER_Success;
2562 case Mips::LoadImmDoubleGPR:
2563 return expandLoadDoubleImmToGPR(Inst, IDLoc, Out, STI) ? MER_Fail
2564 : MER_Success;
2565 case Mips::LoadImmDoubleFGR:
2566 return expandLoadDoubleImmToFPR(Inst, true, IDLoc, Out, STI) ? MER_Fail
2567 : MER_Success;
2568 case Mips::LoadImmDoubleFGR_32:
2569 return expandLoadDoubleImmToFPR(Inst, false, IDLoc, Out, STI) ? MER_Fail
2570 : MER_Success;
2571
2572 case Mips::Ulh:
2573 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2574 case Mips::Ulhu:
2575 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2576 case Mips::Ush:
2577 return expandUsh(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2578 case Mips::Ulw:
2579 case Mips::Usw:
2580 return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2581 case Mips::NORImm:
2582 case Mips::NORImm64:
2583 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2584 case Mips::SGE:
2585 case Mips::SGEU:
2586 return expandSge(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2587 case Mips::SGEImm:
2588 case Mips::SGEUImm:
2589 case Mips::SGEImm64:
2590 case Mips::SGEUImm64:
2591 return expandSgeImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2592 case Mips::SGTImm:
2593 case Mips::SGTUImm:
2594 case Mips::SGTImm64:
2595 case Mips::SGTUImm64:
2596 return expandSgtImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2597 case Mips::SLE:
2598 case Mips::SLEU:
2599 return expandSle(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2600 case Mips::SLEImm:
2601 case Mips::SLEUImm:
2602 case Mips::SLEImm64:
2603 case Mips::SLEUImm64:
2604 return expandSleImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2605 case Mips::SLTImm64:
2606 if (isInt<16>(Inst.getOperand(2).getImm())) {
2607 Inst.setOpcode(Mips::SLTi64);
2608 return MER_NotAMacro;
2609 }
2610 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2611 case Mips::SLTUImm64:
2612 if (isInt<16>(Inst.getOperand(2).getImm())) {
2613 Inst.setOpcode(Mips::SLTiu64);
2614 return MER_NotAMacro;
2615 }
2616 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2617 case Mips::ADDi: case Mips::ADDi_MM:
2618 case Mips::ADDiu: case Mips::ADDiu_MM:
2619 case Mips::SLTi: case Mips::SLTi_MM:
2620 case Mips::SLTiu: case Mips::SLTiu_MM:
2621 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2622 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2623 int64_t ImmValue = Inst.getOperand(2).getImm();
2624 if (isInt<16>(ImmValue))
2625 return MER_NotAMacro;
2626 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2627 : MER_Success;
2628 }
2629 return MER_NotAMacro;
2630 case Mips::ANDi: case Mips::ANDi_MM: case Mips::ANDi64:
2631 case Mips::ORi: case Mips::ORi_MM: case Mips::ORi64:
2632 case Mips::XORi: case Mips::XORi_MM: case Mips::XORi64:
2633 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2634 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2635 int64_t ImmValue = Inst.getOperand(2).getImm();
2636 if (isUInt<16>(ImmValue))
2637 return MER_NotAMacro;
2638 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2639 : MER_Success;
2640 }
2641 return MER_NotAMacro;
2642 case Mips::ROL:
2643 case Mips::ROR:
2644 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2645 case Mips::ROLImm:
2646 case Mips::RORImm:
2647 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2648 case Mips::DROL:
2649 case Mips::DROR:
2650 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2651 case Mips::DROLImm:
2652 case Mips::DRORImm:
2653 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2654 case Mips::ABSMacro:
2655 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2656 case Mips::MULImmMacro:
2657 case Mips::DMULImmMacro:
2658 return expandMulImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2659 case Mips::MULOMacro:
2660 case Mips::DMULOMacro:
2661 return expandMulO(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2662 case Mips::MULOUMacro:
2663 case Mips::DMULOUMacro:
2664 return expandMulOU(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2665 case Mips::DMULMacro:
2666 return expandDMULMacro(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2667 case Mips::LDMacro:
2668 case Mips::SDMacro:
2669 return expandLoadStoreDMacro(Inst, IDLoc, Out, STI,
2670 Inst.getOpcode() == Mips::LDMacro)
2671 ? MER_Fail
2672 : MER_Success;
2673 case Mips::SDC1_M1:
2674 return expandStoreDM1Macro(Inst, IDLoc, Out, STI)
2675 ? MER_Fail
2676 : MER_Success;
2677 case Mips::SEQMacro:
2678 return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2679 case Mips::SEQIMacro:
2680 return expandSeqI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2681 case Mips::SNEMacro:
2682 return expandSne(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2683 case Mips::SNEIMacro:
2684 return expandSneI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2685 case Mips::MFTC0: case Mips::MTTC0:
2686 case Mips::MFTGPR: case Mips::MTTGPR:
2687 case Mips::MFTLO: case Mips::MTTLO:
2688 case Mips::MFTHI: case Mips::MTTHI:
2689 case Mips::MFTACX: case Mips::MTTACX:
2690 case Mips::MFTDSP: case Mips::MTTDSP:
2691 case Mips::MFTC1: case Mips::MTTC1:
2692 case Mips::MFTHC1: case Mips::MTTHC1:
2693 case Mips::CFTC1: case Mips::CTTC1:
2694 return expandMXTRAlias(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2695 case Mips::SaaAddr:
2696 case Mips::SaadAddr:
2697 return expandSaaAddr(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2698 }
2699}
2700
2701bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
2702 MCStreamer &Out,
2703 const MCSubtargetInfo *STI) {
2704 MipsTargetStreamer &TOut = getTargetStreamer();
2705
2706 // Create a JALR instruction which is going to replace the pseudo-JAL.
2707 MCInst JalrInst;
2708 JalrInst.setLoc(IDLoc);
2709 const MCOperand FirstRegOp = Inst.getOperand(0);
2710 const unsigned Opcode = Inst.getOpcode();
2711
2712 if (Opcode == Mips::JalOneReg) {
2713 // jal $rs => jalr $rs
2714 if (IsCpRestoreSet && inMicroMipsMode()) {
2715 JalrInst.setOpcode(Mips::JALRS16_MM);
2716 JalrInst.addOperand(FirstRegOp);
2717 } else if (inMicroMipsMode()) {
2718 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
2719 JalrInst.addOperand(FirstRegOp);
2720 } else {
2721 JalrInst.setOpcode(Mips::JALR);
2722 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
2723 JalrInst.addOperand(FirstRegOp);
2724 }
2725 } else if (Opcode == Mips::JalTwoReg) {
2726 // jal $rd, $rs => jalr $rd, $rs
2727 if (IsCpRestoreSet && inMicroMipsMode())
2728 JalrInst.setOpcode(Mips::JALRS_MM);
2729 else
2730 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
2731 JalrInst.addOperand(FirstRegOp);
2732 const MCOperand SecondRegOp = Inst.getOperand(1);
2733 JalrInst.addOperand(SecondRegOp);
2734 }
2735 Out.emitInstruction(JalrInst, *STI);
2736
2737 // If .set reorder is active and branch instruction has a delay slot,
2738 // emit a NOP after it.
2739 const MCInstrDesc &MCID = MII.get(JalrInst.getOpcode());
2740 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2741 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst), IDLoc,
2742 STI);
2743
2744 return false;
2745}
2746
2747/// Can the value be represented by a unsigned N-bit value and a shift left?
2748template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
2749 return x && isUInt<N>(x >> llvm::countr_zero(x));
2750}
2751
2752/// Load (or add) an immediate into a register.
2753///
2754/// @param ImmValue The immediate to load.
2755/// @param DstReg The register that will hold the immediate.
2756/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2757/// for a simple initialization.
2758/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2759/// @param IsAddress True if the immediate represents an address. False if it
2760/// is an integer.
2761/// @param IDLoc Location of the immediate in the source file.
2762bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
2763 unsigned SrcReg, bool Is32BitImm,
2764 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2765 const MCSubtargetInfo *STI) {
2766 MipsTargetStreamer &TOut = getTargetStreamer();
2767
2768 if (!Is32BitImm && !isGP64bit()) {
2769 Error(IDLoc, "instruction requires a 64-bit architecture");
2770 return true;
2771 }
2772
2773 if (Is32BitImm) {
2774 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2775 // Sign extend up to 64-bit so that the predicates match the hardware
2776 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2777 // true.
2778 ImmValue = SignExtend64<32>(ImmValue);
2779 } else {
2780 Error(IDLoc, "instruction requires a 32-bit immediate");
2781 return true;
2782 }
2783 }
2784
2785 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2786 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2787
2788 bool UseSrcReg = false;
2789 if (SrcReg != Mips::NoRegister)
2790 UseSrcReg = true;
2791
2792 unsigned TmpReg = DstReg;
2793 if (UseSrcReg &&
2794 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
2795 // At this point we need AT to perform the expansions and we exit if it is
2796 // not available.
2797 unsigned ATReg = getATReg(IDLoc);
2798 if (!ATReg)
2799 return true;
2800 TmpReg = ATReg;
2801 }
2802
2803 if (isInt<16>(ImmValue)) {
2804 if (!UseSrcReg)
2805 SrcReg = ZeroReg;
2806
2807 // This doesn't quite follow the usual ABI expectations for N32 but matches
2808 // traditional assembler behaviour. N32 would normally use addiu for both
2809 // integers and addresses.
2810 if (IsAddress && !Is32BitImm) {
2811 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
2812 return false;
2813 }
2814
2815 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
2816 return false;
2817 }
2818
2819 if (isUInt<16>(ImmValue)) {
2820 unsigned TmpReg = DstReg;
2821 if (SrcReg == DstReg) {
2822 TmpReg = getATReg(IDLoc);
2823 if (!TmpReg)
2824 return true;
2825 }
2826
2827 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
2828 if (UseSrcReg)
2829 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
2830 return false;
2831 }
2832
2833 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2834 warnIfNoMacro(IDLoc);
2835
2836 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2837 uint16_t Bits15To0 = ImmValue & 0xffff;
2838 if (!Is32BitImm && !isInt<32>(ImmValue)) {
2839 // Traditional behaviour seems to special case this particular value. It's
2840 // not clear why other masks are handled differently.
2841 if (ImmValue == 0xffffffff) {
2842 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2843 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
2844 if (UseSrcReg)
2845 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
2846 return false;
2847 }
2848
2849 // Expand to an ORi instead of a LUi to avoid sign-extending into the
2850 // upper 32 bits.
2851 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2852 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
2853 if (Bits15To0)
2854 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
2855 if (UseSrcReg)
2856 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
2857 return false;
2858 }
2859
2860 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
2861 if (Bits15To0)
2862 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
2863 if (UseSrcReg)
2864 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
2865 return false;
2866 }
2867
2868 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2869 if (Is32BitImm) {
2870 Error(IDLoc, "instruction requires a 32-bit immediate");
2871 return true;
2872 }
2873
2874 // We've processed ImmValue satisfying isUInt<16> above, so ImmValue must be
2875 // at least 17-bit wide here.
2876 unsigned BitWidth = llvm::bit_width((uint64_t)ImmValue);
2877 assert(BitWidth >= 17 && "ImmValue must be at least 17-bit wide");
2878
2879 // Traditionally, these immediates are shifted as little as possible and as
2880 // such we align the most significant bit to bit 15 of our temporary.
2881 unsigned ShiftAmount = BitWidth - 16;
2882 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
2883 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2884 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
2885
2886 if (UseSrcReg)
2887 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
2888
2889 return false;
2890 }
2891
2892 warnIfNoMacro(IDLoc);
2893
2894 // The remaining case is packed with a sequence of dsll and ori with zeros
2895 // being omitted and any neighbouring dsll's being coalesced.
2896 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2897
2898 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2899 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
2900 IDLoc, Out, STI))
2901 return false;
2902
2903 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2904 // skip it and defer the shift to the next chunk.
2905 unsigned ShiftCarriedForwards = 16;
2906 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2907 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2908
2909 if (ImmChunk != 0) {
2910 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2911 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
2912 ShiftCarriedForwards = 0;
2913 }
2914
2915 ShiftCarriedForwards += 16;
2916 }
2917 ShiftCarriedForwards -= 16;
2918
2919 // Finish any remaining shifts left by trailing zeros.
2920 if (ShiftCarriedForwards)
2921 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2922
2923 if (UseSrcReg)
2924 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
2925
2926 return false;
2927}
2928
2929bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
2930 MCStreamer &Out, const MCSubtargetInfo *STI) {
2931 const MCOperand &ImmOp = Inst.getOperand(1);
2932 assert(ImmOp.isImm() && "expected immediate operand kind");
2933 const MCOperand &DstRegOp = Inst.getOperand(0);
2934 assert(DstRegOp.isReg() && "expected register operand kind");
2935
2936 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
2937 Is32BitImm, false, IDLoc, Out, STI))
2938 return true;
2939
2940 return false;
2941}
2942
2943bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2944 const MCOperand &Offset,
2945 bool Is32BitAddress, SMLoc IDLoc,
2946 MCStreamer &Out,
2947 const MCSubtargetInfo *STI) {
2948 // la can't produce a usable address when addresses are 64-bit.
2949 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2950 Warning(IDLoc, "la used to load 64-bit address");
2951 // Continue as if we had 'dla' instead.
2952 Is32BitAddress = false;
2953 }
2954
2955 // dla requires 64-bit addresses.
2956 if (!Is32BitAddress && !hasMips3()) {
2957 Error(IDLoc, "instruction requires a 64-bit architecture");
2958 return true;
2959 }
2960
2961 if (!Offset.isImm())
2962 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
2963 Is32BitAddress, IDLoc, Out, STI);
2964
2965 if (!ABI.ArePtrs64bit()) {
2966 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2967 Is32BitAddress = true;
2968 }
2969
2970 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
2971 IDLoc, Out, STI);
2972}
2973
2974bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2975 unsigned DstReg, unsigned SrcReg,
2976 bool Is32BitSym, SMLoc IDLoc,
2977 MCStreamer &Out,
2978 const MCSubtargetInfo *STI) {
2979 MipsTargetStreamer &TOut = getTargetStreamer();
2980 bool UseSrcReg = SrcReg != Mips::NoRegister && SrcReg != Mips::ZERO &&
2981 SrcReg != Mips::ZERO_64;
2982 warnIfNoMacro(IDLoc);
2983
2984 if (inPicMode()) {
2985 MCValue Res;
2986 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2987 Error(IDLoc, "expected relocatable expression");
2988 return true;
2989 }
2990 if (Res.getSymB() != nullptr) {
2991 Error(IDLoc, "expected relocatable expression with only one symbol");
2992 return true;
2993 }
2994
2995 bool IsPtr64 = ABI.ArePtrs64bit();
2996 bool IsLocalSym =
2997 Res.getSymA()->getSymbol().isInSection() ||
2998 Res.getSymA()->getSymbol().isTemporary() ||
2999 (Res.getSymA()->getSymbol().isELF() &&
3000 cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
3002 // For O32, "$"-prefixed symbols are recognized as temporary while
3003 // .L-prefixed symbols are not (PrivateGlobalPrefix is "$"). Recognize ".L"
3004 // manually.
3005 if (ABI.IsO32() && Res.getSymA()->getSymbol().getName().starts_with(".L"))
3006 IsLocalSym = true;
3007 bool UseXGOT = STI->hasFeature(Mips::FeatureXGOT) && !IsLocalSym;
3008
3009 // The case where the result register is $25 is somewhat special. If the
3010 // symbol in the final relocation is external and not modified with a
3011 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16
3012 // or R_MIPS_CALL16 instead of R_MIPS_GOT_DISP in 64-bit case.
3013 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
3014 Res.getConstant() == 0 && !IsLocalSym) {
3015 if (UseXGOT) {
3017 SymExpr, getContext());
3019 SymExpr, getContext());
3020 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(CallHiExpr), IDLoc,
3021 STI);
3022 TOut.emitRRR(IsPtr64 ? Mips::DADDu : Mips::ADDu, DstReg, DstReg, GPReg,
3023 IDLoc, STI);
3024 TOut.emitRRX(IsPtr64 ? Mips::LD : Mips::LW, DstReg, DstReg,
3025 MCOperand::createExpr(CallLoExpr), IDLoc, STI);
3026 } else {
3027 const MCExpr *CallExpr =
3028 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
3029 TOut.emitRRX(IsPtr64 ? Mips::LD : Mips::LW, DstReg, GPReg,
3030 MCOperand::createExpr(CallExpr), IDLoc, STI);
3031 }
3032 return false;
3033 }
3034
3035 unsigned TmpReg = DstReg;
3036 if (UseSrcReg &&
3037 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
3038 SrcReg)) {
3039 // If $rs is the same as $rd, we need to use AT.
3040 // If it is not available we exit.
3041 unsigned ATReg = getATReg(IDLoc);
3042 if (!ATReg)
3043 return true;
3044 TmpReg = ATReg;
3045 }
3046
3047 // FIXME: In case of N32 / N64 ABI and emabled XGOT, local addresses
3048 // loaded using R_MIPS_GOT_PAGE / R_MIPS_GOT_OFST pair of relocations.
3049 // FIXME: Implement XGOT for microMIPS.
3050 if (UseXGOT) {
3051 // Loading address from XGOT
3052 // External GOT: lui $tmp, %got_hi(symbol)($gp)
3053 // addu $tmp, $tmp, $gp
3054 // lw $tmp, %got_lo(symbol)($tmp)
3055 // >addiu $tmp, $tmp, offset
3056 // >addiu $rd, $tmp, $rs
3057 // The addiu's marked with a '>' may be omitted if they are redundant. If
3058 // this happens then the last instruction must use $rd as the result
3059 // register.
3060 const MCExpr *CallHiExpr =
3061 MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, SymExpr, getContext());
3062 const MCExpr *CallLoExpr = MipsMCExpr::create(
3063 MipsMCExpr::MEK_GOT_LO16, Res.getSymA(), getContext());
3064
3065 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(CallHiExpr), IDLoc,
3066 STI);
3067 TOut.emitRRR(IsPtr64 ? Mips::DADDu : Mips::ADDu, TmpReg, TmpReg, GPReg,
3068 IDLoc, STI);
3069 TOut.emitRRX(IsPtr64 ? Mips::LD : Mips::LW, TmpReg, TmpReg,
3070 MCOperand::createExpr(CallLoExpr), IDLoc, STI);
3071
3072 if (Res.getConstant() != 0)
3073 TOut.emitRRX(IsPtr64 ? Mips::DADDiu : Mips::ADDiu, TmpReg, TmpReg,
3075 Res.getConstant(), getContext())),
3076 IDLoc, STI);
3077
3078 if (UseSrcReg)
3079 TOut.emitRRR(IsPtr64 ? Mips::DADDu : Mips::ADDu, DstReg, TmpReg, SrcReg,
3080 IDLoc, STI);
3081 return false;
3082 }
3083
3084 const MipsMCExpr *GotExpr = nullptr;
3085 const MCExpr *LoExpr = nullptr;
3086 if (ABI.IsN32() || ABI.IsN64()) {
3087 // The remaining cases are:
3088 // Small offset: ld $tmp, %got_disp(symbol)($gp)
3089 // >daddiu $tmp, $tmp, offset
3090 // >daddu $rd, $tmp, $rs
3091 // The daddiu's marked with a '>' may be omitted if they are redundant. If
3092 // this happens then the last instruction must use $rd as the result
3093 // register.
3095 getContext());
3096 if (Res.getConstant() != 0) {
3097 // Symbols fully resolve with just the %got_disp(symbol) but we
3098 // must still account for any offset to the symbol for
3099 // expressions like symbol+8.
3100 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
3101
3102 // FIXME: Offsets greater than 16 bits are not yet implemented.
3103 // FIXME: The correct range is a 32-bit sign-extended number.
3104 if (Res.getConstant() < -0x8000 || Res.getConstant() > 0x7fff) {
3105 Error(IDLoc, "macro instruction uses large offset, which is not "
3106 "currently supported");
3107 return true;
3108 }
3109 }
3110 } else {
3111 // The remaining cases are:
3112 // External GOT: lw $tmp, %got(symbol)($gp)
3113 // >addiu $tmp, $tmp, offset
3114 // >addiu $rd, $tmp, $rs
3115 // Local GOT: lw $tmp, %got(symbol+offset)($gp)
3116 // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
3117 // >addiu $rd, $tmp, $rs
3118 // The addiu's marked with a '>' may be omitted if they are redundant. If
3119 // this happens then the last instruction must use $rd as the result
3120 // register.
3121 if (IsLocalSym) {
3122 GotExpr =
3123 MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
3124 LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
3125 } else {
3126 // External symbols fully resolve the symbol with just the %got(symbol)
3127 // but we must still account for any offset to the symbol for
3128 // expressions like symbol+8.
3130 getContext());
3131 if (Res.getConstant() != 0)
3132 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
3133 }
3134 }
3135
3136 TOut.emitRRX(IsPtr64 ? Mips::LD : Mips::LW, TmpReg, GPReg,
3137 MCOperand::createExpr(GotExpr), IDLoc, STI);
3138
3139 if (LoExpr)
3140 TOut.emitRRX(IsPtr64 ? Mips::DADDiu : Mips::ADDiu, TmpReg, TmpReg,
3141 MCOperand::createExpr(LoExpr), IDLoc, STI);
3142
3143 if (UseSrcReg)
3144 TOut.emitRRR(IsPtr64 ? Mips::DADDu : Mips::ADDu, DstReg, TmpReg, SrcReg,
3145 IDLoc, STI);
3146
3147 return false;
3148 }
3149
3150 const MipsMCExpr *HiExpr =
3151 MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
3152 const MipsMCExpr *LoExpr =
3153 MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
3154
3155 // This is the 64-bit symbol address expansion.
3156 if (ABI.ArePtrs64bit() && isGP64bit()) {
3157 // We need AT for the 64-bit expansion in the cases where the optional
3158 // source register is the destination register and for the superscalar
3159 // scheduled form.
3160 //
3161 // If it is not available we exit if the destination is the same as the
3162 // source register.
3163
3164 const MipsMCExpr *HighestExpr =
3165 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
3166 const MipsMCExpr *HigherExpr =
3167 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
3168
3169 bool RdRegIsRsReg =
3170 UseSrcReg &&
3171 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg);
3172
3173 if (canUseATReg() && UseSrcReg && RdRegIsRsReg) {
3174 unsigned ATReg = getATReg(IDLoc);
3175
3176 // If $rs is the same as $rd:
3177 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
3178 // daddiu $at, $at, %higher(sym)
3179 // dsll $at, $at, 16
3180 // daddiu $at, $at, %hi(sym)
3181 // dsll $at, $at, 16
3182 // daddiu $at, $at, %lo(sym)
3183 // daddu $rd, $at, $rd
3184 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
3185 STI);
3186 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3187 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3188 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3189 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3190 IDLoc, STI);
3191 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3192 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
3193 IDLoc, STI);
3194 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
3195
3196 return false;
3197 } else if (canUseATReg() && !RdRegIsRsReg && DstReg != getATReg(IDLoc)) {
3198 unsigned ATReg = getATReg(IDLoc);
3199
3200 // If the $rs is different from $rd or if $rs isn't specified and we
3201 // have $at available:
3202 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3203 // lui $at, %hi(sym)
3204 // daddiu $rd, $rd, %higher(sym)
3205 // daddiu $at, $at, %lo(sym)
3206 // dsll32 $rd, $rd, 0
3207 // daddu $rd, $rd, $at
3208 // (daddu $rd, $rd, $rs)
3209 //
3210 // Which is preferred for superscalar issue.
3211 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3212 STI);
3213 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3214 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3215 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3216 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
3217 IDLoc, STI);
3218 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
3219 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
3220 if (UseSrcReg)
3221 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3222
3223 return false;
3224 } else if ((!canUseATReg() && !RdRegIsRsReg) ||
3225 (canUseATReg() && DstReg == getATReg(IDLoc))) {
3226 // Otherwise, synthesize the address in the destination register
3227 // serially:
3228 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3229 // daddiu $rd, $rd, %higher(sym)
3230 // dsll $rd, $rd, 16
3231 // daddiu $rd, $rd, %hi(sym)
3232 // dsll $rd, $rd, 16
3233 // daddiu $rd, $rd, %lo(sym)
3234 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3235 STI);
3236 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3237 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3238 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3239 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3240 MCOperand::createExpr(HiExpr), IDLoc, STI);
3241 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3242 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3243 MCOperand::createExpr(LoExpr), IDLoc, STI);
3244 if (UseSrcReg)
3245 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3246
3247 return false;
3248 } else {
3249 // We have a case where SrcReg == DstReg and we don't have $at
3250 // available. We can't expand this case, so error out appropriately.
3251 assert(SrcReg == DstReg && !canUseATReg() &&
3252 "Could have expanded dla but didn't?");
3253 reportParseError(IDLoc,
3254 "pseudo-instruction requires $at, which is not available");
3255 return true;
3256 }
3257 }
3258
3259 // And now, the 32-bit symbol address expansion:
3260 // If $rs is the same as $rd:
3261 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
3262 // ori $at, $at, %lo(sym)
3263 // addu $rd, $at, $rd
3264 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
3265 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
3266 // ori $rd, $rd, %lo(sym)
3267 // (addu $rd, $rd, $rs)
3268 unsigned TmpReg = DstReg;
3269 if (UseSrcReg &&
3270 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
3271 // If $rs is the same as $rd, we need to use AT.
3272 // If it is not available we exit.
3273 unsigned ATReg = getATReg(IDLoc);
3274 if (!ATReg)
3275 return true;
3276 TmpReg = ATReg;
3277 }
3278
3279 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3280 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
3281 IDLoc, STI);
3282
3283 if (UseSrcReg)
3284 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
3285 else
3286 assert(
3287 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
3288
3289 return false;
3290}
3291
3292// Each double-precision register DO-D15 overlaps with two of the single
3293// precision registers F0-F31. As an example, all of the following hold true:
3294// D0 + 1 == F1, F1 + 1 == D1, F1 + 1 == F2, depending on the context.
3295static unsigned nextReg(unsigned Reg) {
3296 if (MipsMCRegisterClasses[Mips::FGR32RegClassID].contains(Reg))
3297 return Reg == (unsigned)Mips::F31 ? (unsigned)Mips::F0 : Reg + 1;
3298 switch (Reg) {
3299 default: llvm_unreachable("Unknown register in assembly macro expansion!");
3300 case Mips::ZERO: return Mips::AT;
3301 case Mips::AT: return Mips::V0;
3302 case Mips::V0: return Mips::V1;
3303 case Mips::V1: return Mips::A0;
3304 case Mips::A0: return Mips::A1;
3305 case Mips::A1: return Mips::A2;
3306 case Mips::A2: return Mips::A3;
3307 case Mips::A3: return Mips::T0;
3308 case Mips::T0: return Mips::T1;
3309 case Mips::T1: return Mips::T2;
3310 case Mips::T2: return Mips::T3;
3311 case Mips::T3: return Mips::T4;
3312 case Mips::T4: return Mips::T5;
3313 case Mips::T5: return Mips::T6;
3314 case Mips::T6: return Mips::T7;
3315 case Mips::T7: return Mips::S0;
3316 case Mips::S0: return Mips::S1;
3317 case Mips::S1: return Mips::S2;
3318 case Mips::S2: return Mips::S3;
3319 case Mips::S3: return Mips::S4;
3320 case Mips::S4: return Mips::S5;
3321 case Mips::S5: return Mips::S6;
3322 case Mips::S6: return Mips::S7;
3323 case Mips::S7: return Mips::T8;
3324 case Mips::T8: return Mips::T9;
3325 case Mips::T9: return Mips::K0;
3326 case Mips::K0: return Mips::K1;
3327 case Mips::K1: return Mips::GP;
3328 case Mips::GP: return Mips::SP;
3329 case Mips::SP: return Mips::FP;
3330 case Mips::FP: return Mips::RA;
3331 case Mips::RA: return Mips::ZERO;
3332 case Mips::D0: return Mips::F1;
3333 case Mips::D1: return Mips::F3;
3334 case Mips::D2: return Mips::F5;
3335 case Mips::D3: return Mips::F7;
3336 case Mips::D4: return Mips::F9;
3337 case Mips::D5: return Mips::F11;
3338 case Mips::D6: return Mips::F13;
3339 case Mips::D7: return Mips::F15;
3340 case Mips::D8: return Mips::F17;
3341 case Mips::D9: return Mips::F19;
3342 case Mips::D10: return Mips::F21;
3343 case Mips::D11: return Mips::F23;
3344 case Mips::D12: return Mips::F25;
3345 case Mips::D13: return Mips::F27;
3346 case Mips::D14: return Mips::F29;
3347 case Mips::D15: return Mips::F31;
3348 }
3349}
3350
3351// FIXME: This method is too general. In principle we should compute the number
3352// of instructions required to synthesize the immediate inline compared to
3353// synthesizing the address inline and relying on non .text sections.
3354// For static O32 and N32 this may yield a small benefit, for static N64 this is
3355// likely to yield a much larger benefit as we have to synthesize a 64bit
3356// address to load a 64 bit value.
3357bool MipsAsmParser::emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc,
3358 MCSymbol *Sym) {
3359 unsigned ATReg = getATReg(IDLoc);
3360 if (!ATReg)
3361 return true;
3362
3363 if(IsPicEnabled) {
3364 const MCExpr *GotSym =
3366 const MipsMCExpr *GotExpr =
3367 MipsMCExpr::create(MipsMCExpr::MEK_GOT, GotSym, getContext());
3368
3369 if(isABI_O32() || isABI_N32()) {
3370 TOut.emitRRX(Mips::LW, ATReg, GPReg, MCOperand::createExpr(GotExpr),
3371 IDLoc, STI);
3372 } else { //isABI_N64()
3373 TOut.emitRRX(Mips::LD, ATReg, GPReg, MCOperand::createExpr(GotExpr),
3374 IDLoc, STI);
3375 }
3376 } else { //!IsPicEnabled
3377 const MCExpr *HiSym =
3379 const MipsMCExpr *HiExpr =
3380 MipsMCExpr::create(MipsMCExpr::MEK_HI, HiSym, getContext());
3381
3382 // FIXME: This is technically correct but gives a different result to gas,
3383 // but gas is incomplete there (it has a fixme noting it doesn't work with
3384 // 64-bit addresses).
3385 // FIXME: With -msym32 option, the address expansion for N64 should probably
3386 // use the O32 / N32 case. It's safe to use the 64 address expansion as the
3387 // symbol's value is considered sign extended.
3388 if(isABI_O32() || isABI_N32()) {
3389 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3390 } else { //isABI_N64()
3391 const MCExpr *HighestSym =
3393 const MipsMCExpr *HighestExpr =
3394 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, HighestSym, getContext());
3395 const MCExpr *HigherSym =
3397 const MipsMCExpr *HigherExpr =
3398 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, HigherSym, getContext());
3399
3400 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
3401 STI);
3402 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3403 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3404 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3405 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3406 IDLoc, STI);
3407 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3408 }
3409 }
3410 return false;
3411}
3412
3414 // If ImmOp64 is AsmToken::Integer type (all bits set to zero in the
3415 // exponent field), convert it to double (e.g. 1 to 1.0)
3416 if ((Hi_32(ImmOp64) & 0x7ff00000) == 0) {
3417 APFloat RealVal(APFloat::IEEEdouble(), ImmOp64);
3418 ImmOp64 = RealVal.bitcastToAPInt().getZExtValue();
3419 }
3420 return ImmOp64;
3421}
3422
3424 // Conversion of a double in an uint64_t to a float in a uint32_t,
3425 // retaining the bit pattern of a float.
3426 double DoubleImm = llvm::bit_cast<double>(ImmOp64);
3427 float TmpFloat = static_cast<float>(DoubleImm);
3428 return llvm::bit_cast<uint32_t>(TmpFloat);
3429}
3430
3431bool MipsAsmParser::expandLoadSingleImmToGPR(MCInst &Inst, SMLoc IDLoc,
3432 MCStreamer &Out,
3433 const MCSubtargetInfo *STI) {
3434 assert(Inst.getNumOperands() == 2 && "Invalid operand count");
3435 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&
3436 "Invalid instruction operand.");
3437
3438 unsigned FirstReg = Inst.getOperand(0).getReg();
3439 uint64_t ImmOp64 = Inst.getOperand(1).getImm();
3440
3442
3443 return loadImmediate(ImmOp32, FirstReg, Mips::NoRegister, true, false, IDLoc,
3444 Out, STI);
3445}
3446
3447bool MipsAsmParser::expandLoadSingleImmToFPR(MCInst &Inst, SMLoc IDLoc,
3448 MCStreamer &Out,
3449 const MCSubtargetInfo *STI) {
3450 MipsTargetStreamer &TOut = getTargetStreamer();
3451 assert(Inst.getNumOperands() == 2 && "Invalid operand count");
3452 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&
3453 "Invalid instruction operand.");
3454
3455 unsigned FirstReg = Inst.getOperand(0).getReg();
3456 uint64_t ImmOp64 = Inst.getOperand(1).getImm();
3457
3458 ImmOp64 = convertIntToDoubleImm(ImmOp64);
3459
3460 uint32_t ImmOp32 = covertDoubleImmToSingleImm(ImmOp64);
3461
3462 unsigned TmpReg = Mips::ZERO;
3463 if (ImmOp32 != 0) {
3464 TmpReg = getATReg(IDLoc);
3465 if (!TmpReg)
3466 return true;
3467 }
3468
3469 if (Lo_32(ImmOp64) == 0) {
3470 if (TmpReg != Mips::ZERO && loadImmediate(ImmOp32, TmpReg, Mips::NoRegister,
3471 true, false, IDLoc, Out, STI))
3472 return true;
3473 TOut.emitRR(Mips::MTC1, FirstReg, TmpReg, IDLoc, STI);
3474 return false;
3475 }
3476
3477 MCSection *CS = getStreamer().getCurrentSectionOnly();
3478 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3479 // where appropriate.
3480 MCSection *ReadOnlySection =
3481 getContext().getELFSection(".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3482
3483 MCSymbol *Sym = getContext().createTempSymbol();
3484 const MCExpr *LoSym =
3486 const MipsMCExpr *LoExpr =
3487 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3488
3489 getStreamer().switchSection(ReadOnlySection);
3490 getStreamer().emitLabel(Sym, IDLoc);
3491 getStreamer().emitInt32(ImmOp32);
3492 getStreamer().switchSection(CS);
3493
3494 if (emitPartialAddress(TOut, IDLoc, Sym))
3495 return true;
3496 TOut.emitRRX(Mips::LWC1, FirstReg, TmpReg, MCOperand::createExpr(LoExpr),
3497 IDLoc, STI);
3498 return false;
3499}
3500
3501bool MipsAsmParser::expandLoadDoubleImmToGPR(MCInst &Inst, SMLoc IDLoc,
3502 MCStreamer &Out,
3503 const MCSubtargetInfo *STI) {
3504 MipsTargetStreamer &TOut = getTargetStreamer();
3505 assert(Inst.getNumOperands() == 2 && "Invalid operand count");
3506 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&
3507 "Invalid instruction operand.");
3508
3509 unsigned FirstReg = Inst.getOperand(0).getReg();
3510 uint64_t ImmOp64 = Inst.getOperand(1).getImm();
3511
3512 ImmOp64 = convertIntToDoubleImm(ImmOp64);
3513
3514 if (Lo_32(ImmOp64) == 0) {
3515 if (isGP64bit()) {
3516 if (loadImmediate(ImmOp64, FirstReg, Mips::NoRegister, false, false,
3517 IDLoc, Out, STI))
3518 return true;
3519 } else {
3520 if (loadImmediate(Hi_32(ImmOp64), FirstReg, Mips::NoRegister, true, false,
3521 IDLoc, Out, STI))
3522 return true;
3523
3524 if (loadImmediate(0, nextReg(FirstReg), Mips::NoRegister, true, false,
3525 IDLoc, Out, STI))
3526 return true;
3527 }
3528 return false;
3529 }
3530
3531 MCSection *CS = getStreamer().getCurrentSectionOnly();
3532 MCSection *ReadOnlySection =
3533 getContext().getELFSection(".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3534
3535 MCSymbol *Sym = getContext().createTempSymbol();
3536 const MCExpr *LoSym =
3538 const MipsMCExpr *LoExpr =
3539 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3540
3541 getStreamer().switchSection(ReadOnlySection);
3542 getStreamer().emitLabel(Sym, IDLoc);
3543 getStreamer().emitValueToAlignment(Align(8));
3544 getStreamer().emitIntValue(ImmOp64, 8);
3545 getStreamer().switchSection(CS);
3546
3547 unsigned TmpReg = getATReg(IDLoc);
3548 if (!TmpReg)
3549 return true;
3550
3551 if (emitPartialAddress(TOut, IDLoc, Sym))
3552 return true;
3553
3554 TOut.emitRRX(isABI_N64() ? Mips::DADDiu : Mips::ADDiu, TmpReg, TmpReg,
3555 MCOperand::createExpr(LoExpr), IDLoc, STI);
3556
3557 if (isGP64bit())
3558 TOut.emitRRI(Mips::LD, FirstReg, TmpReg, 0, IDLoc, STI);
3559 else {
3560 TOut.emitRRI(Mips::LW, FirstReg, TmpReg, 0, IDLoc, STI);
3561 TOut.emitRRI(Mips::LW, nextReg(FirstReg), TmpReg, 4, IDLoc, STI);
3562 }
3563 return false;
3564}
3565
3566bool MipsAsmParser::expandLoadDoubleImmToFPR(MCInst &Inst, bool Is64FPU,
3567 SMLoc IDLoc, MCStreamer &Out,
3568 const MCSubtargetInfo *STI) {
3569 MipsTargetStreamer &TOut = getTargetStreamer();
3570 assert(Inst.getNumOperands() == 2 && "Invalid operand count");
3571 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&
3572 "Invalid instruction operand.");
3573
3574 unsigned FirstReg = Inst.getOperand(0).getReg();
3575 uint64_t ImmOp64 = Inst.getOperand(1).getImm();
3576
3577 ImmOp64 = convertIntToDoubleImm(ImmOp64);
3578
3579 unsigned TmpReg = Mips::ZERO;
3580 if (ImmOp64 != 0) {
3581 TmpReg = getATReg(IDLoc);
3582 if (!TmpReg)
3583 return true;
3584 }
3585
3586 if ((Lo_32(ImmOp64) == 0) &&
3587 !((Hi_32(ImmOp64) & 0xffff0000) && (Hi_32(ImmOp64) & 0x0000ffff))) {
3588 if (isGP64bit()) {
3589 if (TmpReg != Mips::ZERO &&
3590 loadImmediate(ImmOp64, TmpReg, Mips::NoRegister, false, false, IDLoc,
3591 Out, STI))
3592 return true;
3593 TOut.emitRR(Mips::DMTC1, FirstReg, TmpReg, IDLoc, STI);
3594 return false;
3595 }
3596
3597 if (TmpReg != Mips::ZERO &&
3598 loadImmediate(Hi_32(ImmOp64), TmpReg, Mips::NoRegister, true, false,
3599 IDLoc, Out, STI))
3600 return true;
3601
3602 if (hasMips32r2()) {
3603 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3604 TOut.emitRRR(Mips::MTHC1_D32, FirstReg, FirstReg, TmpReg, IDLoc, STI);
3605 } else {
3606 TOut.emitRR(Mips::MTC1, nextReg(FirstReg), TmpReg, IDLoc, STI);
3607 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3608 }
3609 return false;
3610 }
3611
3612 MCSection *CS = getStreamer().getCurrentSectionOnly();
3613 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3614 // where appropriate.
3615 MCSection *ReadOnlySection =
3616 getContext().getELFSection(".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3617
3618 MCSymbol *Sym = getContext().createTempSymbol();
3619 const MCExpr *LoSym =
3621 const MipsMCExpr *LoExpr =
3622 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3623
3624 getStreamer().switchSection(ReadOnlySection);
3625 getStreamer().emitLabel(Sym, IDLoc);
3626 getStreamer().emitValueToAlignment(Align(8));
3627 getStreamer().emitIntValue(ImmOp64, 8);
3628 getStreamer().switchSection(CS);
3629
3630 if (emitPartialAddress(TOut, IDLoc, Sym))
3631 return true;
3632
3633 TOut.emitRRX(Is64FPU ? Mips::LDC164 : Mips::LDC1, FirstReg, TmpReg,
3634 MCOperand::createExpr(LoExpr), IDLoc, STI);
3635
3636 return false;
3637}
3638
3639bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
3640 MCStreamer &Out,
3641 const MCSubtargetInfo *STI) {
3642 MipsTargetStreamer &TOut = getTargetStreamer();
3643
3644 assert(MII.get(Inst.getOpcode()).getNumOperands() == 1 &&
3645 "unexpected number of operands");
3646
3647 MCOperand Offset = Inst.getOperand(0);
3648 if (Offset.isExpr()) {
3649 Inst.clear();
3650 Inst.setOpcode(Mips::BEQ_MM);
3651 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3652 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3653 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
3654 } else {
3655 assert(Offset.isImm() && "expected immediate operand kind");
3656 if (isInt<11>(Offset.getImm())) {
3657 // If offset fits into 11 bits then this instruction becomes microMIPS
3658 // 16-bit unconditional branch instruction.
3659 if (inMicroMipsMode())
3660 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
3661 } else {
3662 if (!isInt<17>(Offset.getImm()))
3663 return Error(IDLoc, "branch target out of range");
3664 if (offsetToAlignment(Offset.getImm(), Align(2)))
3665 return Error(IDLoc, "branch to misaligned address");
3666 Inst.clear();
3667 Inst.setOpcode(Mips::BEQ_MM);
3668 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3669 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3670 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
3671 }
3672 }
3673 Out.emitInstruction(Inst, *STI);
3674
3675 // If .set reorder is active and branch instruction has a delay slot,
3676 // emit a NOP after it.
3677 const MCInstrDesc &MCID = MII.get(Inst.getOpcode());
3678 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
3679 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
3680
3681 return false;
3682}
3683
3684bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3685 const MCSubtargetInfo *STI) {
3686 MipsTargetStreamer &TOut = getTargetStreamer();
3687 const MCOperand &DstRegOp = Inst.getOperand(0);
3688 assert(DstRegOp.isReg() && "expected register operand kind");
3689
3690 const MCOperand &ImmOp = Inst.getOperand(1);
3691 assert(ImmOp.isImm() && "expected immediate operand kind");
3692
3693 const MCOperand &MemOffsetOp = Inst.getOperand(2);
3694 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
3695 "expected immediate or expression operand");
3696
3697 bool IsLikely = false;
3698
3699 unsigned OpCode = 0;
3700 switch(Inst.getOpcode()) {
3701 case Mips::BneImm:
3702 OpCode = Mips::BNE;
3703 break;
3704 case Mips::BeqImm:
3705 OpCode = Mips::BEQ;
3706 break;
3707 case Mips::BEQLImmMacro:
3708 OpCode = Mips::BEQL;
3709 IsLikely = true;
3710 break;
3711 case Mips::BNELImmMacro:
3712 OpCode = Mips::BNEL;
3713 IsLikely = true;
3714 break;
3715 default:
3716 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
3717 break;
3718 }
3719
3720 int64_t ImmValue = ImmOp.getImm();
3721 if (ImmValue == 0) {
3722 if (IsLikely) {
3723 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO,
3724 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3725 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3726 } else
3727 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
3728 STI);
3729 } else {
3730 warnIfNoMacro(IDLoc);
3731
3732 unsigned ATReg = getATReg(IDLoc);
3733 if (!ATReg)
3734 return true;
3735
3736 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
3737 IDLoc, Out, STI))
3738 return true;
3739
3740 if (IsLikely) {
3741 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg,
3742 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3743 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3744 } else
3745 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
3746 }
3747 return false;
3748}
3749
3750void MipsAsmParser::expandMem16Inst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3751 const MCSubtargetInfo *STI, bool IsLoad) {
3752 unsigned NumOp = Inst.getNumOperands();
3753 assert((NumOp == 3 || NumOp == 4) && "unexpected operands number");
3754 unsigned StartOp = NumOp == 3 ? 0 : 1;
3755
3756 const MCOperand &DstRegOp = Inst.getOperand(StartOp);
3757 assert(DstRegOp.isReg() && "expected register operand kind");
3758 const MCOperand &BaseRegOp = Inst.getOperand(StartOp + 1);
3759 assert(BaseRegOp.isReg() && "expected register operand kind");
3760 const MCOperand &OffsetOp = Inst.getOperand(StartOp + 2);
3761
3762 MipsTargetStreamer &TOut = getTargetStreamer();
3763 unsigned OpCode = Inst.getOpcode();
3764 unsigned DstReg = DstRegOp.getReg();
3765 unsigned BaseReg = BaseRegOp.getReg();
3766 unsigned TmpReg = DstReg;
3767
3768 const MCInstrDesc &Desc = MII.get(OpCode);
3769 int16_t DstRegClass = Desc.operands()[StartOp].RegClass;
3770 unsigned DstRegClassID =
3771 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
3772 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
3773 (DstRegClassID == Mips::GPR64RegClassID);
3774
3775 if (!IsLoad || !IsGPR || (BaseReg == DstReg)) {
3776 // At this point we need AT to perform the expansions
3777 // and we exit if it is not available.
3778 TmpReg = getATReg(IDLoc);
3779 if (!TmpReg)
3780 return;
3781 }
3782
3783 auto emitInstWithOffset = [&](const MCOperand &Off) {
3784 if (NumOp == 3)
3785 TOut.emitRRX(OpCode, DstReg, TmpReg, Off, IDLoc, STI);
3786 else
3787 TOut.emitRRRX(OpCode, DstReg, DstReg, TmpReg, Off, IDLoc, STI);
3788 };
3789
3790 if (OffsetOp.isImm()) {
3791 int64_t LoOffset = OffsetOp.getImm() & 0xffff;
3792 int64_t HiOffset = OffsetOp.getImm() & ~0xffff;
3793
3794 // If msb of LoOffset is 1(negative number) we must increment
3795 // HiOffset to account for the sign-extension of the low part.
3796 if (LoOffset & 0x8000)
3797 HiOffset += 0x10000;
3798
3799 bool IsLargeOffset = HiOffset != 0;
3800
3801 if (IsLargeOffset) {
3802 bool Is32BitImm = isInt<32>(OffsetOp.getImm());
3803 if (loadImmediate(HiOffset, TmpReg, Mips::NoRegister, Is32BitImm, true,
3804 IDLoc, Out, STI))
3805 return;
3806 }
3807
3808 if (BaseReg != Mips::ZERO && BaseReg != Mips::ZERO_64)
3809 TOut.emitRRR(ABI.ArePtrs64bit() ? Mips::DADDu : Mips::ADDu, TmpReg,
3810 TmpReg, BaseReg, IDLoc, STI);
3811 emitInstWithOffset(MCOperand::createImm(int16_t(LoOffset)));
3812 return;
3813 }
3814
3815 if (OffsetOp.isExpr()) {
3816 if (inPicMode()) {
3817 // FIXME:
3818 // c) Check that immediates of R_MIPS_GOT16/R_MIPS_LO16 relocations
3819 // do not exceed 16-bit.
3820 // d) Use R_MIPS_GOT_PAGE/R_MIPS_GOT_OFST relocations instead
3821 // of R_MIPS_GOT_DISP in appropriate cases to reduce number
3822 // of GOT entries.
3823 MCValue Res;
3824 if (!OffsetOp.getExpr()->evaluateAsRelocatable(Res, nullptr, nullptr)) {
3825 Error(IDLoc, "expected relocatable expression");
3826 return;
3827 }
3828 if (Res.getSymB() != nullptr) {
3829 Error(IDLoc, "expected relocatable expression with only one symbol");
3830 return;
3831 }
3832
3833 loadAndAddSymbolAddress(Res.getSymA(), TmpReg, BaseReg,
3834 !ABI.ArePtrs64bit(), IDLoc, Out, STI);
3835 emitInstWithOffset(MCOperand::createImm(int16_t(Res.getConstant())));
3836 } else {
3837 // FIXME: Implement 64-bit case.
3838 // 1) lw $8, sym => lui $8, %hi(sym)
3839 // lw $8, %lo(sym)($8)
3840 // 2) sw $8, sym => lui $at, %hi(sym)
3841 // sw $8, %lo(sym)($at)
3842 const MCExpr *OffExpr = OffsetOp.getExpr();
3843 MCOperand LoOperand = MCOperand::createExpr(
3844 MipsMCExpr::create(MipsMCExpr::MEK_LO, OffExpr, getContext()));
3845 MCOperand HiOperand = MCOperand::createExpr(
3846 MipsMCExpr::create(MipsMCExpr::MEK_HI, OffExpr, getContext()));
3847
3848 if (ABI.IsN64()) {
3849 MCOperand HighestOperand = MCOperand::createExpr(
3850 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, OffExpr, getContext()));
3851 MCOperand HigherOperand = MCOperand::createExpr(
3852 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, OffExpr, getContext()));
3853
3854 TOut.emitRX(Mips::LUi, TmpReg, HighestOperand, IDLoc, STI);
3855 TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, HigherOperand, IDLoc, STI);
3856 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
3857 TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, HiOperand, IDLoc, STI);
3858 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
3859 if (BaseReg != Mips::ZERO && BaseReg != Mips::ZERO_64)
3860 TOut.emitRRR(Mips::DADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI);
3861 emitInstWithOffset(LoOperand);
3862 } else {
3863 // Generate the base address in TmpReg.
3864 TOut.emitRX(Mips::LUi, TmpReg, HiOperand, IDLoc, STI);
3865 if (BaseReg != Mips::ZERO)
3866 TOut.emitRRR(Mips::ADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI);
3867 // Emit the load or store with the adjusted base and offset.
3868 emitInstWithOffset(LoOperand);
3869 }
3870 }
3871 return;
3872 }
3873
3874 llvm_unreachable("unexpected operand type");
3875}
3876
3877void MipsAsmParser::expandMem9Inst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3878 const MCSubtargetInfo *STI, bool IsLoad) {
3879 unsigned NumOp = Inst.getNumOperands();
3880 assert((NumOp == 3 || NumOp == 4) && "unexpected operands number");
3881 unsigned StartOp = NumOp == 3 ? 0 : 1;
3882
3883 const MCOperand &DstRegOp = Inst.getOperand(StartOp);
3884 assert(DstRegOp.isReg() && "expected register operand kind");
3885 const MCOperand &BaseRegOp = Inst.getOperand(StartOp + 1);
3886 assert(BaseRegOp.isReg() && "expected register operand kind");
3887 const MCOperand &OffsetOp = Inst.getOperand(StartOp + 2);
3888
3889 MipsTargetStreamer &TOut = getTargetStreamer();
3890 unsigned OpCode = Inst.getOpcode();
3891 unsigned DstReg = DstRegOp.getReg();
3892 unsigned BaseReg = BaseRegOp.getReg();
3893 unsigned TmpReg = DstReg;
3894
3895 const MCInstrDesc &Desc = MII.get(OpCode);
3896 int16_t DstRegClass = Desc.operands()[StartOp].RegClass;
3897 unsigned DstRegClassID =
3898 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
3899 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
3900 (DstRegClassID == Mips::GPR64RegClassID);
3901
3902 if (!IsLoad || !IsGPR || (BaseReg == DstReg)) {
3903 // At this point we need AT to perform the expansions
3904 // and we exit if it is not available.
3905 TmpReg = getATReg(IDLoc);
3906 if (!TmpReg)
3907 return;
3908 }
3909
3910 auto emitInst = [&]() {
3911 if (NumOp == 3)
3912 TOut.emitRRX(OpCode, DstReg, TmpReg, MCOperand::createImm(0), IDLoc, STI);
3913 else
3914 TOut.emitRRRX(OpCode, DstReg, DstReg, TmpReg, MCOperand::createImm(0),
3915 IDLoc, STI);
3916 };
3917
3918 if (OffsetOp.isImm()) {
3919 loadImmediate(OffsetOp.getImm(), TmpReg, BaseReg, !ABI.ArePtrs64bit(), true,
3920 IDLoc, Out, STI);
3921 emitInst();
3922 return;
3923 }
3924
3925 if (OffsetOp.isExpr()) {
3926 loadAndAddSymbolAddress(OffsetOp.getExpr(), TmpReg, BaseReg,
3927 !ABI.ArePtrs64bit(), IDLoc, Out, STI);
3928 emitInst();
3929 return;
3930 }
3931
3932 llvm_unreachable("unexpected operand type");
3933}
3934
3935bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
3936 MCStreamer &Out,
3937 const MCSubtargetInfo *STI) {
3938 unsigned OpNum = Inst.getNumOperands();
3939 unsigned Opcode = Inst.getOpcode();
3940 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
3941
3942 assert(Inst.getOperand(OpNum - 1).isImm() &&
3943 Inst.getOperand(OpNum - 2).isReg() &&
3944 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
3945
3946 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
3947 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
3948 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
3949 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
3950 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
3951 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
3952 // It can be implemented as SWM16 or LWM16 instruction.
3953 if (inMicroMipsMode() && hasMips32r6())
3954 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
3955 else
3956 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
3957 }
3958
3959 Inst.setOpcode(NewOpcode);
3960 Out.emitInstruction(Inst, *STI);
3961 return false;
3962}
3963
3964bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
3965 MCStreamer &Out,
3966 const MCSubtargetInfo *STI) {
3967 MipsTargetStreamer &TOut = getTargetStreamer();
3968 bool EmittedNoMacroWarning = false;
3969 unsigned PseudoOpcode = Inst.getOpcode();
3970 unsigned SrcReg = Inst.getOperand(0).getReg();
3971 const MCOperand &TrgOp = Inst.getOperand(1);
3972 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
3973
3974 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
3975 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
3976
3977 unsigned TrgReg;
3978 if (TrgOp.isReg())
3979 TrgReg = TrgOp.getReg();
3980 else if (TrgOp.isImm()) {
3981 warnIfNoMacro(IDLoc);
3982 EmittedNoMacroWarning = true;
3983
3984 TrgReg = getATReg(IDLoc);
3985 if (!TrgReg)
3986 return true;
3987
3988 switch(PseudoOpcode) {
3989 default:
3990 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3991 case Mips::BLTImmMacro:
3992 PseudoOpcode = Mips::BLT;
3993 break;
3994 case Mips::BLEImmMacro:
3995 PseudoOpcode = Mips::BLE;
3996 break;
3997 case Mips::BGEImmMacro:
3998 PseudoOpcode = Mips::BGE;
3999 break;
4000 case Mips::BGTImmMacro:
4001 PseudoOpcode = Mips::BGT;
4002 break;
4003 case Mips::BLTUImmMacro:
4004 PseudoOpcode = Mips::BLTU;
4005 break;
4006 case Mips::BLEUImmMacro:
4007 PseudoOpcode = Mips::BLEU;
4008 break;
4009 case Mips::BGEUImmMacro:
4010 PseudoOpcode = Mips::BGEU;
4011 break;
4012 case Mips::BGTUImmMacro:
4013 PseudoOpcode = Mips::BGTU;
4014 break;
4015 case Mips::BLTLImmMacro:
4016 PseudoOpcode = Mips::BLTL;
4017 break;
4018 case Mips::BLELImmMacro:
4019 PseudoOpcode = Mips::BLEL;
4020 break;
4021 case Mips::BGELImmMacro:
4022 PseudoOpcode = Mips::BGEL;
4023 break;
4024 case Mips::BGTLImmMacro:
4025 PseudoOpcode = Mips::BGTL;
4026 break;
4027 case Mips::BLTULImmMacro:
4028 PseudoOpcode = Mips::BLTUL;
4029 break;
4030 case Mips::BLEULImmMacro:
4031 PseudoOpcode = Mips::BLEUL;
4032 break;
4033 case Mips::BGEULImmMacro:
4034 PseudoOpcode = Mips::BGEUL;
4035 break;
4036 case Mips::BGTULImmMacro:
4037 PseudoOpcode = Mips::BGTUL;
4038 break;
4039 }
4040
4041 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
4042 false, IDLoc, Out, STI))
4043 return true;
4044 }
4045
4046 switch (PseudoOpcode) {
4047 case Mips::BLT:
4048 case Mips::BLTU:
4049 case Mips::BLTL:
4050 case Mips::BLTUL:
4051 AcceptsEquality = false;
4052 ReverseOrderSLT = false;
4053 IsUnsigned =
4054 ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
4055 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
4056 ZeroSrcOpcode = Mips::BGTZ;
4057 ZeroTrgOpcode = Mips::BLTZ;
4058 break;
4059 case Mips::BLE:
4060 case Mips::BLEU:
4061 case Mips::BLEL:
4062 case Mips::BLEUL:
4063 AcceptsEquality = true;
4064 ReverseOrderSLT = true;
4065 IsUnsigned =
4066 ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
4067 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
4068 ZeroSrcOpcode = Mips::BGEZ;
4069 ZeroTrgOpcode = Mips::BLEZ;
4070 break;
4071 case Mips::BGE:
4072 case Mips::BGEU:
4073 case Mips::BGEL:
4074 case Mips::BGEUL:
4075 AcceptsEquality = true;
4076 ReverseOrderSLT = false;
4077 IsUnsigned =
4078 ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
4079 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
4080 ZeroSrcOpcode = Mips::BLEZ;
4081 ZeroTrgOpcode = Mips::BGEZ;
4082 break;
4083 case Mips::BGT:
4084 case Mips::BGTU:
4085 case Mips::BGTL:
4086 case Mips::BGTUL:
4087 AcceptsEquality = false;
4088 ReverseOrderSLT = true;
4089 IsUnsigned =
4090 ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
4091 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
4092 ZeroSrcOpcode = Mips::BLTZ;
4093 ZeroTrgOpcode = Mips::BGTZ;
4094 break;
4095 default:
4096 llvm_unreachable("unknown opcode for branch pseudo-instruction");
4097 }
4098
4099 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
4100 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
4101 if (IsSrcRegZero && IsTrgRegZero) {
4102 // FIXME: All of these Opcode-specific if's are needed for compatibility
4103 // with GAS' behaviour. However, they may not generate the most efficient
4104 // code in some circumstances.
4105 if (PseudoOpcode == Mips::BLT) {
4106 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
4107 IDLoc, STI);
4108 return false;
4109 }
4110 if (PseudoOpcode == Mips::BLE) {
4111 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
4112 IDLoc, STI);
4113 Warning(IDLoc, "branch is always taken");
4114 return false;
4115 }
4116 if (PseudoOpcode == Mips::BGE) {
4117 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
4118 IDLoc, STI);
4119 Warning(IDLoc, "branch is always taken");
4120 return false;
4121 }
4122 if (PseudoOpcode == Mips::BGT) {
4123 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
4124 IDLoc, STI);
4125 return false;
4126 }
4127 if (PseudoOpcode == Mips::BGTU) {
4128 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
4129 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
4130 return false;
4131 }
4132 if (AcceptsEquality) {
4133 // If both registers are $0 and the pseudo-branch accepts equality, it
4134 // will always be taken, so we emit an unconditional branch.
4135 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
4136 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
4137 Warning(IDLoc, "branch is always taken");
4138 return false;
4139 }
4140 // If both registers are $0 and the pseudo-branch does not accept
4141 // equality, it will never be taken, so we don't have to emit anything.
4142 return false;
4143 }
4144 if (IsSrcRegZero || IsTrgRegZero) {
4145 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
4146 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
4147 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
4148 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
4149 // the pseudo-branch will never be taken, so we don't emit anything.
4150 // This only applies to unsigned pseudo-branches.
4151 return false;
4152 }
4153 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
4154 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
4155 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
4156 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
4157 // the pseudo-branch will always be taken, so we emit an unconditional
4158 // branch.
4159 // This only applies to unsigned pseudo-branches.
4160 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
4161 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
4162 Warning(IDLoc, "branch is always taken");
4163 return false;
4164 }
4165 if (IsUnsigned) {
4166 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
4167 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
4168 // the pseudo-branch will be taken only when the non-zero register is
4169 // different from 0, so we emit a BNEZ.
4170 //
4171 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
4172 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
4173 // the pseudo-branch will be taken only when the non-zero register is
4174 // equal to 0, so we emit a BEQZ.
4175 //
4176 // Because only BLEU and BGEU branch on equality, we can use the
4177 // AcceptsEquality variable to decide when to emit the BEQZ.
4178 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
4179 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
4180 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
4181 return false;
4182 }
4183 // If we have a signed pseudo-branch and one of the registers is $0,
4184 // we can use an appropriate compare-to-zero branch. We select which one
4185 // to use in the switch statement above.
4186 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
4187 IsSrcRegZero ? TrgReg : SrcReg,
4188 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
4189 return false;
4190 }
4191
4192 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
4193 // expansions. If it is not available, we return.
4194 unsigned ATRegNum = getATReg(IDLoc);
4195 if (!ATRegNum)
4196 return true;
4197
4198 if (!EmittedNoMacroWarning)
4199 warnIfNoMacro(IDLoc);
4200
4201 // SLT fits well with 2 of our 4 pseudo-branches:
4202 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
4203 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
4204 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
4205 // This is accomplished by using a BNEZ with the result of the SLT.
4206 //
4207 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
4208 // and BLE with BGT), so we change the BNEZ into a BEQZ.
4209 // Because only BGE and BLE branch on equality, we can use the
4210 // AcceptsEquality variable to decide when to emit the BEQZ.
4211 // Note that the order of the SLT arguments doesn't change between
4212 // opposites.
4213 //
4214 // The same applies to the unsigned variants, except that SLTu is used
4215 // instead of SLT.
4216 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
4217 ReverseOrderSLT ? TrgReg : SrcReg,
4218 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
4219
4220 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
4221 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
4222 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
4223 STI);
4224 return false;
4225}
4226
4227// Expand a integer division macro.
4228//
4229// Notably we don't have to emit a warning when encountering $rt as the $zero
4230// register, or 0 as an immediate. processInstruction() has already done that.
4231//
4232// The destination register can only be $zero when expanding (S)DivIMacro or
4233// D(S)DivMacro.
4234
4235bool MipsAsmParser::expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4236 const MCSubtargetInfo *STI,
4237 const bool IsMips64, const bool Signed) {
4238 MipsTargetStreamer &TOut = getTargetStreamer();
4239
4240 warnIfNoMacro(IDLoc);
4241
4242 const MCOperand &RdRegOp = Inst.getOperand(0);
4243 assert(RdRegOp.isReg() && "expected register operand kind");
4244 unsigned RdReg = RdRegOp.getReg();
4245
4246 const MCOperand &RsRegOp = Inst.getOperand(1);
4247 assert(RsRegOp.isReg() && "expected register operand kind");
4248 unsigned RsReg = RsRegOp.getReg();
4249
4250 unsigned RtReg;
4251 int64_t ImmValue;
4252
4253 const MCOperand &RtOp = Inst.getOperand(2);
4254 assert((RtOp.isReg() || RtOp.isImm()) &&
4255 "expected register or immediate operand kind");
4256 if (RtOp.isReg())
4257 RtReg = RtOp.getReg();
4258 else
4259 ImmValue = RtOp.getImm();
4260
4261 unsigned DivOp;
4262 unsigned ZeroReg;
4263 unsigned SubOp;
4264
4265 if (IsMips64) {
4266 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
4267 ZeroReg = Mips::ZERO_64;
4268 SubOp = Mips::DSUB;
4269 } else {
4270 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
4271 ZeroReg = Mips::ZERO;
4272 SubOp = Mips::SUB;
4273 }
4274
4275 bool UseTraps = useTraps();
4276
4277 unsigned Opcode = Inst.getOpcode();
4278 bool isDiv = Opcode == Mips::SDivMacro || Opcode == Mips::SDivIMacro ||
4279 Opcode == Mips::UDivMacro || Opcode == Mips::UDivIMacro ||
4280 Opcode == Mips::DSDivMacro || Opcode == Mips::DSDivIMacro ||
4281 Opcode == Mips::DUDivMacro || Opcode == Mips::DUDivIMacro;
4282
4283 bool isRem = Opcode == Mips::SRemMacro || Opcode == Mips::SRemIMacro ||
4284 Opcode == Mips::URemMacro || Opcode == Mips::URemIMacro ||
4285 Opcode == Mips::DSRemMacro || Opcode == Mips::DSRemIMacro ||
4286 Opcode == Mips::DURemMacro || Opcode == Mips::DURemIMacro;
4287
4288 if (RtOp.isImm()) {
4289 unsigned ATReg = getATReg(IDLoc);
4290 if (!ATReg)
4291 return true;
4292
4293 if (ImmValue == 0) {
4294 if (UseTraps)
4295 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
4296 else
4297 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
4298 return false;
4299 }
4300
4301 if (isRem && (ImmValue == 1 || (Signed && (ImmValue == -1)))) {
4302 TOut.emitRRR(Mips::OR, RdReg, ZeroReg, ZeroReg, IDLoc, STI);
4303 return false;
4304 } else if (isDiv && ImmValue == 1) {
4305 TOut.emitRRR(Mips::OR, RdReg, RsReg, Mips::ZERO, IDLoc, STI);
4306 return false;
4307 } else if (isDiv && Signed && ImmValue == -1) {
4308 TOut.emitRRR(SubOp, RdReg, ZeroReg, RsReg, IDLoc, STI);
4309 return false;
4310 } else {
4311 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue),
4312 false, Inst.getLoc(), Out, STI))
4313 return true;
4314 TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI);
4315 TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
4316 return false;
4317 }
4318 return true;
4319 }
4320
4321 // If the macro expansion of (d)div(u) or (d)rem(u) would always trap or
4322 // break, insert the trap/break and exit. This gives a different result to
4323 // GAS. GAS has an inconsistency/missed optimization in that not all cases
4324 // are handled equivalently. As the observed behaviour is the same, we're ok.
4325 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
4326 if (UseTraps) {
4327 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
4328 return false;
4329 }
4330 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
4331 return false;
4332 }
4333
4334 // (d)rem(u) $0, $X, $Y is a special case. Like div $zero, $X, $Y, it does
4335 // not expand to macro sequence.
4336 if (isRem && (RdReg == Mips::ZERO || RdReg == Mips::ZERO_64)) {
4337 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
4338 return false;
4339 }
4340
4341 // Temporary label for first branch traget
4342 MCContext &Context = TOut.getStreamer().getContext();
4343 MCSymbol *BrTarget;
4344 MCOperand LabelOp;
4345
4346 if (UseTraps) {
4347 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
4348 } else {
4349 // Branch to the li instruction.
4350 BrTarget = Context.createTempSymbol();
4351 LabelOp = MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4352 TOut.emitRRX(Mips::BNE, RtReg, ZeroReg, LabelOp, IDLoc, STI);
4353 }
4354
4355 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
4356
4357 if (!UseTraps)
4358 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
4359
4360 if (!Signed) {
4361 if (!UseTraps)
4362 TOut.getStreamer().emitLabel(BrTarget);
4363
4364 TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
4365 return false;
4366 }
4367
4368 unsigned ATReg = getATReg(IDLoc);
4369 if (!ATReg)
4370 return true;
4371
4372 if (!UseTraps)
4373 TOut.getStreamer().emitLabel(BrTarget);
4374
4375 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
4376
4377 // Temporary label for the second branch target.
4378 MCSymbol *BrTargetEnd = Context.createTempSymbol();
4379 MCOperand LabelOpEnd =
4380 MCOperand::createExpr(MCSymbolRefExpr::create(BrTargetEnd, Context));
4381
4382 // Branch to the mflo instruction.
4383 TOut.emitRRX(Mips::BNE, RtReg, ATReg, LabelOpEnd, IDLoc, STI);
4384
4385 if (IsMips64) {
4386 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
4387 TOut.emitDSLL(ATReg, ATReg, 63, IDLoc, STI);
4388 } else {
4389 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
4390 }
4391
4392 if (UseTraps)
4393 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
4394 else {
4395 // Branch to the mflo instruction.
4396 TOut.emitRRX(Mips::BNE, RsReg, ATReg, LabelOpEnd, IDLoc, STI);
4397 TOut.emitNop(IDLoc, STI);
4398 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
4399 }
4400
4401 TOut.getStreamer().emitLabel(BrTargetEnd);
4402 TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
4403 return false;
4404}
4405
4406bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
4407 SMLoc IDLoc, MCStreamer &Out,
4408 const MCSubtargetInfo *STI) {
4409 MipsTargetStreamer &TOut = getTargetStreamer();
4410
4411 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4412 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
4413 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
4414
4415 unsigned FirstReg = Inst.getOperand(0).getReg();
4416 unsigned SecondReg = Inst.getOperand(1).getReg();
4417 unsigned ThirdReg = Inst.getOperand(2).getReg();
4418
4419 if (hasMips1() && !hasMips2()) {
4420 unsigned ATReg = getATReg(IDLoc);
4421 if (!ATReg)
4422 return true;
4423 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4424 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4425 TOut.emitNop(IDLoc, STI);
4426 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
4427 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
4428 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
4429 TOut.emitNop(IDLoc, STI);
4430 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
4431 : Mips::CVT_W_S,
4432 FirstReg, SecondReg, IDLoc, STI);
4433 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
4434 TOut.emitNop(IDLoc, STI);
4435 return false;
4436 }
4437
4438 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
4439 : Mips::TRUNC_W_S,
4440 FirstReg, SecondReg, IDLoc, STI);
4441
4442 return false;
4443}
4444
4445bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
4446 MCStreamer &Out, const MCSubtargetInfo *STI) {
4447 if (hasMips32r6() || hasMips64r6()) {
4448 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
4449 }
4450
4451 const MCOperand &DstRegOp = Inst.getOperand(0);
4452 assert(DstRegOp.isReg() && "expected register operand kind");
4453 const MCOperand &SrcRegOp = Inst.getOperand(1);
4454 assert(SrcRegOp.isReg() && "expected register operand kind");
4455 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4456 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4457
4458 MipsTargetStreamer &TOut = getTargetStreamer();
4459 unsigned DstReg = DstRegOp.getReg();
4460 unsigned SrcReg = SrcRegOp.getReg();
4461 int64_t OffsetValue = OffsetImmOp.getImm();
4462
4463 // NOTE: We always need AT for ULHU, as it is always used as the source
4464 // register for one of the LBu's.
4465 warnIfNoMacro(IDLoc);
4466 unsigned ATReg = getATReg(IDLoc);
4467 if (!ATReg)
4468 return true;
4469
4470 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4471 if (IsLargeOffset) {
4472 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4473 IDLoc, Out, STI))
4474 return true;
4475 }
4476
4477 int64_t FirstOffset = IsLargeOffset ? 0 : OffsetValue;
4478 int64_t SecondOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4479 if (isLittle())
4480 std::swap(FirstOffset, SecondOffset);
4481
4482 unsigned FirstLbuDstReg = IsLargeOffset ? DstReg : ATReg;
4483 unsigned SecondLbuDstReg = IsLargeOffset ? ATReg : DstReg;
4484
4485 unsigned LbuSrcReg = IsLargeOffset ? ATReg : SrcReg;
4486 unsigned SllReg = IsLargeOffset ? DstReg : ATReg;
4487
4488 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
4489 FirstOffset, IDLoc, STI);
4490 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondOffset, IDLoc, STI);
4491 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
4492 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
4493
4494 return false;
4495}
4496
4497bool MipsAsmParser::expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4498 const MCSubtargetInfo *STI) {
4499 if (hasMips32r6() || hasMips64r6()) {
4500 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
4501 }
4502
4503 const MCOperand &DstRegOp = Inst.getOperand(0);
4504 assert(DstRegOp.isReg() && "expected register operand kind");
4505 const MCOperand &SrcRegOp = Inst.getOperand(1);
4506 assert(SrcRegOp.isReg() && "expected register operand kind");
4507 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4508 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4509
4510 MipsTargetStreamer &TOut = getTargetStreamer();
4511 unsigned DstReg = DstRegOp.getReg();
4512 unsigned SrcReg = SrcRegOp.getReg();
4513 int64_t OffsetValue = OffsetImmOp.getImm();
4514
4515 warnIfNoMacro(IDLoc);
4516 unsigned ATReg = getATReg(IDLoc);
4517 if (!ATReg)
4518 return true;
4519
4520 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4521 if (IsLargeOffset) {
4522 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4523 IDLoc, Out, STI))
4524 return true;
4525 }
4526
4527 int64_t FirstOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4528 int64_t SecondOffset = IsLargeOffset ? 0 : OffsetValue;
4529 if (isLittle())
4530 std::swap(FirstOffset, SecondOffset);
4531
4532 if (IsLargeOffset) {
4533 TOut.emitRRI(Mips::SB, DstReg, ATReg, FirstOffset, IDLoc, STI);
4534 TOut.emitRRI(Mips::SRL, DstReg, DstReg, 8, IDLoc, STI);
4535 TOut.emitRRI(Mips::SB, DstReg, ATReg, SecondOffset, IDLoc, STI);
4536 TOut.emitRRI(Mips::LBu, ATReg, ATReg, 0, IDLoc, STI);
4537 TOut.emitRRI(Mips::SLL, DstReg, DstReg, 8, IDLoc, STI);
4538 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
4539 } else {
4540 TOut.emitRRI(Mips::SB, DstReg, SrcReg, FirstOffset, IDLoc, STI);
4541 TOut.emitRRI(Mips::SRL, ATReg, DstReg, 8, IDLoc, STI);
4542 TOut.emitRRI(Mips::SB, ATReg, SrcReg, SecondOffset, IDLoc, STI);
4543 }
4544
4545 return false;
4546}
4547
4548bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4549 const MCSubtargetInfo *STI) {
4550 if (hasMips32r6() || hasMips64r6()) {
4551 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
4552 }
4553
4554 const MCOperand &DstRegOp = Inst.getOperand(0);
4555 assert(DstRegOp.isReg() && "expected register operand kind");
4556 const MCOperand &SrcRegOp = Inst.getOperand(1);
4557 assert(SrcRegOp.isReg() && "expected register operand kind");
4558 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4559 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4560
4561 MipsTargetStreamer &TOut = getTargetStreamer();
4562 unsigned DstReg = DstRegOp.getReg();
4563 unsigned SrcReg = SrcRegOp.getReg();
4564 int64_t OffsetValue = OffsetImmOp.getImm();
4565
4566 // Compute left/right load/store offsets.
4567 bool IsLargeOffset = !(isInt<16>(OffsetValue + 3) && isInt<16>(OffsetValue));
4568 int64_t LxlOffset = IsLargeOffset ? 0 : OffsetValue;
4569 int64_t LxrOffset = IsLargeOffset ? 3 : (OffsetValue + 3);
4570 if (isLittle())
4571 std::swap(LxlOffset, LxrOffset);
4572
4573 bool IsLoadInst = (Inst.getOpcode() == Mips::Ulw);
4574 bool DoMove = IsLoadInst && (SrcReg == DstReg) && !IsLargeOffset;
4575 unsigned TmpReg = SrcReg;
4576 if (IsLargeOffset || DoMove) {
4577 warnIfNoMacro(IDLoc);
4578 TmpReg = getATReg(IDLoc);
4579 if (!TmpReg)
4580 return true;
4581 }
4582
4583 if (IsLargeOffset) {
4584 if (loadImmediate(OffsetValue, TmpReg, SrcReg, !ABI.ArePtrs64bit(), true,
4585 IDLoc, Out, STI))
4586 return true;
4587 }
4588
4589 if (DoMove)
4590 std::swap(DstReg, TmpReg);
4591
4592 unsigned XWL = IsLoadInst ? Mips::LWL : Mips::SWL;
4593 unsigned XWR = IsLoadInst ? Mips::LWR : Mips::SWR;
4594 TOut.emitRRI(XWL, DstReg, TmpReg, LxlOffset, IDLoc, STI);
4595 TOut.emitRRI(XWR, DstReg, TmpReg, LxrOffset, IDLoc, STI);
4596
4597 if (DoMove)
4598 TOut.emitRRR(Mips::OR, TmpReg, DstReg, Mips::ZERO, IDLoc, STI);
4599
4600 return false;
4601}
4602
4603bool MipsAsmParser::expandSge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4604 const MCSubtargetInfo *STI) {
4605 MipsTargetStreamer &TOut = getTargetStreamer();
4606
4607 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4608 assert(Inst.getOperand(0).isReg() &&
4609 Inst.getOperand(1).isReg() &&
4610 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
4611
4612 unsigned DstReg = Inst.getOperand(0).getReg();
4613 unsigned SrcReg = Inst.getOperand(1).getReg();
4614 unsigned OpReg = Inst.getOperand(2).getReg();
4615 unsigned OpCode;
4616
4617 warnIfNoMacro(IDLoc);
4618
4619 switch (Inst.getOpcode()) {
4620 case Mips::SGE:
4621 OpCode = Mips::SLT;
4622 break;
4623 case Mips::SGEU:
4624 OpCode = Mips::SLTu;
4625 break;
4626 default:
4627 llvm_unreachable("unexpected 'sge' opcode");
4628 }
4629
4630 // $SrcReg >= $OpReg is equal to (not ($SrcReg < $OpReg))
4631 TOut.emitRRR(OpCode, DstReg, SrcReg, OpReg, IDLoc, STI);
4632 TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI);
4633
4634 return false;
4635}
4636
4637bool MipsAsmParser::expandSgeImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4638 const MCSubtargetInfo *STI) {
4639 MipsTargetStreamer &TOut = getTargetStreamer();
4640
4641 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4642 assert(Inst.getOperand(0).isReg() &&
4643 Inst.getOperand(1).isReg() &&
4644 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
4645
4646 unsigned DstReg = Inst.getOperand(0).getReg();
4647 unsigned SrcReg = Inst.getOperand(1).getReg();
4648 int64_t ImmValue = Inst.getOperand(2).getImm();
4649 unsigned OpRegCode, OpImmCode;
4650
4651 warnIfNoMacro(IDLoc);
4652
4653 switch (Inst.getOpcode()) {
4654 case Mips::SGEImm:
4655 case Mips::SGEImm64:
4656 OpRegCode = Mips::SLT;
4657 OpImmCode = Mips::SLTi;
4658 break;
4659 case Mips::SGEUImm:
4660 case Mips::SGEUImm64:
4661 OpRegCode = Mips::SLTu;
4662 OpImmCode = Mips::SLTiu;
4663 break;
4664 default:
4665 llvm_unreachable("unexpected 'sge' opcode with immediate");
4666 }
4667
4668 // $SrcReg >= Imm is equal to (not ($SrcReg < Imm))
4669 if (isInt<16>(ImmValue)) {
4670 // Use immediate version of STL.
4671 TOut.emitRRI(OpImmCode, DstReg, SrcReg, ImmValue, IDLoc, STI);
4672 TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI);
4673 } else {
4674 unsigned ImmReg = DstReg;
4675 if (DstReg == SrcReg) {
4676 unsigned ATReg = getATReg(Inst.getLoc());
4677 if (!ATReg)
4678 return true;
4679 ImmReg = ATReg;
4680 }
4681
4682 if (loadImmediate(ImmValue, ImmReg, Mips::NoRegister, isInt<32>(ImmValue),
4683 false, IDLoc, Out, STI))
4684 return true;
4685
4686 TOut.emitRRR(OpRegCode, DstReg, SrcReg, ImmReg, IDLoc, STI);
4687 TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI);
4688 }
4689
4690 return false;
4691}
4692
4693bool MipsAsmParser::expandSgtImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4694 const MCSubtargetInfo *STI) {
4695 MipsTargetStreamer &TOut = getTargetStreamer();
4696
4697 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4698 assert(Inst.getOperand(0).isReg() &&
4699 Inst.getOperand(1).isReg() &&
4700 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
4701
4702 unsigned DstReg = Inst.getOperand(0).getReg();
4703 unsigned SrcReg = Inst.getOperand(1).getReg();
4704 unsigned ImmReg = DstReg;
4705 int64_t ImmValue = Inst.getOperand(2).getImm();
4706 unsigned OpCode;
4707
4708 warnIfNoMacro(IDLoc);
4709
4710 switch (Inst.getOpcode()) {
4711 case Mips::SGTImm:
4712 case Mips::SGTImm64:
4713 OpCode = Mips::SLT;
4714 break;
4715 case Mips::SGTUImm:
4716 case Mips::SGTUImm64:
4717 OpCode = Mips::SLTu;
4718 break;
4719 default:
4720 llvm_unreachable("unexpected 'sgt' opcode with immediate");
4721 }
4722
4723 if (DstReg == SrcReg) {
4724 unsigned ATReg = getATReg(Inst.getLoc());
4725 if (!ATReg)
4726 return true;
4727 ImmReg = ATReg;
4728 }
4729
4730 if (loadImmediate(ImmValue, ImmReg, Mips::NoRegister, isInt<32>(ImmValue),
4731 false, IDLoc, Out, STI))
4732 return true;
4733
4734 // $SrcReg > $ImmReg is equal to $ImmReg < $SrcReg
4735 TOut.emitRRR(OpCode, DstReg, ImmReg, SrcReg, IDLoc, STI);
4736
4737 return false;
4738}
4739
4740bool MipsAsmParser::expandSle(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4741 const MCSubtargetInfo *STI) {
4742 MipsTargetStreamer &TOut = getTargetStreamer();
4743
4744 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4745 assert(Inst.getOperand(0).isReg() &&
4746 Inst.getOperand(1).isReg() &&
4747 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
4748
4749 unsigned DstReg = Inst.getOperand(0).getReg();
4750 unsigned SrcReg = Inst.getOperand(1).getReg();
4751 unsigned OpReg = Inst.getOperand(2).getReg();
4752 unsigned OpCode;
4753
4754 warnIfNoMacro(IDLoc);
4755
4756 switch (Inst.getOpcode()) {
4757 case Mips::SLE:
4758 OpCode = Mips::SLT;
4759 break;
4760 case Mips::SLEU:
4761 OpCode = Mips::SLTu;
4762 break;
4763 default:
4764 llvm_unreachable("unexpected 'sge' opcode");
4765 }
4766
4767 // $SrcReg <= $OpReg is equal to (not ($OpReg < $SrcReg))
4768 TOut.emitRRR(OpCode, DstReg, OpReg, SrcReg, IDLoc, STI);
4769 TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI);
4770
4771 return false;
4772}
4773
4774bool MipsAsmParser::expandSleImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4775 const MCSubtargetInfo *STI) {
4776 MipsTargetStreamer &TOut = getTargetStreamer();
4777
4778 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4779 assert(Inst.getOperand(0).isReg() &&
4780 Inst.getOperand(1).isReg() &&
4781 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
4782
4783 unsigned DstReg = Inst.getOperand(0).getReg();
4784 unsigned SrcReg = Inst.getOperand(1).getReg();
4785 int64_t ImmValue = Inst.getOperand(2).getImm();
4786 unsigned OpRegCode;
4787
4788 warnIfNoMacro(IDLoc);
4789
4790 switch (Inst.getOpcode()) {
4791 case Mips::SLEImm:
4792 case Mips::SLEImm64:
4793 OpRegCode = Mips::SLT;
4794 break;
4795 case Mips::SLEUImm:
4796 case Mips::SLEUImm64:
4797 OpRegCode = Mips::SLTu;
4798 break;
4799 default:
4800 llvm_unreachable("unexpected 'sge' opcode with immediate");
4801 }
4802
4803 // $SrcReg <= Imm is equal to (not (Imm < $SrcReg))
4804 unsigned ImmReg = DstReg;
4805 if (DstReg == SrcReg) {
4806 unsigned ATReg = getATReg(Inst.getLoc());
4807 if (!ATReg)
4808 return true;
4809 ImmReg = ATReg;
4810 }
4811
4812 if (loadImmediate(ImmValue, ImmReg, Mips::NoRegister, isInt<32>(ImmValue),
4813 false, IDLoc, Out, STI))
4814 return true;
4815
4816 TOut.emitRRR(OpRegCode, DstReg, ImmReg, SrcReg, IDLoc, STI);
4817 TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI);
4818
4819 return false;
4820}
4821
4822bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
4823 MCStreamer &Out,
4824 const MCSubtargetInfo *STI) {
4825 MipsTargetStreamer &TOut = getTargetStreamer();
4826
4827 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4828 assert(Inst.getOperand(0).isReg() &&
4829 Inst.getOperand(1).isReg() &&
4830 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
4831
4832 unsigned ATReg = Mips::NoRegister;
4833 unsigned FinalDstReg = Mips::NoRegister;
4834 unsigned DstReg = Inst.getOperand(0).getReg();
4835 unsigned SrcReg = Inst.getOperand(1).getReg();
4836 int64_t ImmValue = Inst.getOperand(2).getImm();
4837
4838 bool Is32Bit = isInt<32>(ImmValue) || (!isGP64bit() && isUInt<32>(ImmValue));
4839
4840 unsigned FinalOpcode = Inst.getOpcode();
4841
4842 if (DstReg == SrcReg) {
4843 ATReg = getATReg(Inst.getLoc());
4844 if (!ATReg)
4845 return true;
4846 FinalDstReg = DstReg;
4847 DstReg = ATReg;
4848 }
4849
4850 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false,
4851 Inst.getLoc(), Out, STI)) {
4852 switch (FinalOpcode) {
4853 default:
4854 llvm_unreachable("unimplemented expansion");
4855 case Mips::ADDi:
4856 FinalOpcode = Mips::ADD;
4857 break;
4858 case Mips::ADDiu:
4859 FinalOpcode = Mips::ADDu;
4860 break;
4861 case Mips::ANDi:
4862 FinalOpcode = Mips::AND;
4863 break;
4864 case Mips::NORImm:
4865 FinalOpcode = Mips::NOR;
4866 break;
4867 case Mips::ORi:
4868 FinalOpcode = Mips::OR;
4869 break;
4870 case Mips::SLTi:
4871 FinalOpcode = Mips::SLT;
4872 break;
4873 case Mips::SLTiu:
4874 FinalOpcode = Mips::SLTu;
4875 break;
4876 case Mips::XORi:
4877 FinalOpcode = Mips::XOR;
4878 break;
4879 case Mips::ADDi_MM:
4880 FinalOpcode = Mips::ADD_MM;
4881 break;
4882 case Mips::ADDiu_MM:
4883 FinalOpcode = Mips::ADDu_MM;
4884 break;
4885 case Mips::ANDi_MM:
4886 FinalOpcode = Mips::AND_MM;
4887 break;
4888 case Mips::ORi_MM:
4889 FinalOpcode = Mips::OR_MM;
4890 break;
4891 case Mips::SLTi_MM:
4892 FinalOpcode = Mips::SLT_MM;
4893 break;
4894 case Mips::SLTiu_MM:
4895 FinalOpcode = Mips::SLTu_MM;
4896 break;
4897 case Mips::XORi_MM:
4898 FinalOpcode = Mips::XOR_MM;
4899 break;
4900 case Mips::ANDi64:
4901 FinalOpcode = Mips::AND64;
4902 break;
4903 case Mips::NORImm64:
4904 FinalOpcode = Mips::NOR64;
4905 break;
4906 case Mips::ORi64:
4907 FinalOpcode = Mips::OR64;
4908 break;
4909 case Mips::SLTImm64:
4910 FinalOpcode = Mips::SLT64;
4911 break;
4912 case Mips::SLTUImm64:
4913 FinalOpcode = Mips::SLTu64;
4914 break;
4915 case Mips::XORi64:
4916 FinalOpcode = Mips::XOR64;
4917 break;
4918 }
4919
4920 if (FinalDstReg == Mips::NoRegister)
4921 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
4922 else
4923 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
4924 return false;
4925 }
4926 return true;
4927}
4928
4929bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4930 const MCSubtargetInfo *STI) {
4931 MipsTargetStreamer &TOut = getTargetStreamer();
4932 unsigned ATReg = Mips::NoRegister;
4933 unsigned DReg = Inst.getOperand(0).getReg();
4934 unsigned SReg = Inst.getOperand(1).getReg();
4935 unsigned TReg = Inst.getOperand(2).getReg();
4936 unsigned TmpReg = DReg;
4937
4938 unsigned FirstShift = Mips::NOP;
4939 unsigned SecondShift = Mips::NOP;
4940
4941 if (hasMips32r2()) {
4942 if (DReg == SReg) {
4943 TmpReg = getATReg(Inst.getLoc());
4944 if (!TmpReg)
4945 return true;
4946 }
4947
4948 if (Inst.getOpcode() == Mips::ROL) {
4949 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4950 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
4951 return false;
4952 }
4953
4954 if (Inst.getOpcode() == Mips::ROR) {
4955 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
4956 return false;
4957 }
4958
4959 return true;
4960 }
4961
4962 if (hasMips32()) {
4963 switch (Inst.getOpcode()) {
4964 default:
4965 llvm_unreachable("unexpected instruction opcode");
4966 case Mips::ROL:
4967 FirstShift = Mips::SRLV;
4968 SecondShift = Mips::SLLV;
4969 break;
4970 case Mips::ROR:
4971 FirstShift = Mips::SLLV;
4972 SecondShift = Mips::SRLV;
4973 break;
4974 }
4975
4976 ATReg = getATReg(Inst.getLoc());
4977 if (!ATReg)
4978 return true;
4979
4980 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4981 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4982 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4983 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
4984
4985 return false;
4986 }
4987
4988 return true;
4989}
4990
4991bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
4992 MCStreamer &Out,
4993 const MCSubtargetInfo *STI) {
4994 MipsTargetStreamer &TOut = getTargetStreamer();
4995 unsigned ATReg = Mips::NoRegister;
4996 unsigned DReg = Inst.getOperand(0).getReg();
4997 unsigned SReg = Inst.getOperand(1).getReg();
4998 int64_t ImmValue = Inst.getOperand(2).getImm();
4999
5000 unsigned FirstShift = Mips::NOP;
5001 unsigned SecondShift = Mips::NOP;
5002
5003 if (hasMips32r2()) {
5004 if (Inst.getOpcode() == Mips::ROLImm) {
5005 uint64_t MaxShift = 32;
5006 uint64_t ShiftValue = ImmValue;
5007 if (ImmValue != 0)
5008 ShiftValue = MaxShift - ImmValue;
5009 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
5010 return false;
5011 }
5012
5013 if (Inst.getOpcode() == Mips::RORImm) {
5014 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
5015 return false;
5016 }
5017
5018 return true;
5019 }
5020
5021 if (hasMips32()) {
5022 if (ImmValue == 0) {
5023 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
5024 return false;
5025 }
5026
5027 switch (Inst.getOpcode()) {
5028 default:
5029 llvm_unreachable("unexpected instruction opcode");
5030 case Mips::ROLImm:
5031 FirstShift = Mips::SLL;
5032 SecondShift = Mips::SRL;
5033 break;
5034 case Mips::RORImm:
5035 FirstShift = Mips::SRL;
5036 SecondShift = Mips::SLL;
5037 break;
5038 }
5039
5040 ATReg = getATReg(Inst.getLoc());
5041 if (!ATReg)
5042 return true;
5043
5044 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
5045 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
5046 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
5047
5048 return false;
5049 }
5050
5051 return true;
5052}
5053
5054bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5055 const MCSubtargetInfo *STI) {
5056 MipsTargetStreamer &TOut = getTargetStreamer();
5057 unsigned ATReg = Mips::NoRegister;
5058 unsigned DReg = Inst.getOperand(0).getReg();
5059 unsigned SReg = Inst.getOperand(1).getReg();
5060 unsigned TReg = Inst.getOperand(2).getReg();
5061 unsigned TmpReg = DReg;
5062
5063 unsigned FirstShift = Mips::NOP;
5064 unsigned SecondShift = Mips::NOP;
5065
5066 if (hasMips64r2()) {
5067 if (TmpReg == SReg) {
5068 TmpReg = getATReg(Inst.getLoc());
5069 if (!TmpReg)
5070 return true;
5071 }
5072
5073 if (Inst.getOpcode() == Mips::DROL) {
5074 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
5075 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
5076 return false;
5077 }
5078
5079 if (Inst.getOpcode() == Mips::DROR) {
5080 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
5081 return false;
5082 }
5083
5084 return true;
5085 }
5086
5087 if (hasMips64()) {
5088 switch (Inst.getOpcode()) {
5089 default:
5090 llvm_unreachable("unexpected instruction opcode");
5091 case Mips::DROL:
5092 FirstShift = Mips::DSRLV;
5093 SecondShift = Mips::DSLLV;
5094 break;
5095 case Mips::DROR:
5096 FirstShift = Mips::DSLLV;
5097 SecondShift = Mips::DSRLV;
5098 break;
5099 }
5100
5101 ATReg = getATReg(Inst.getLoc());
5102 if (!ATReg)
5103 return true;
5104
5105 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
5106 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
5107 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
5108 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
5109
5110 return false;
5111 }
5112
5113 return true;
5114}
5115
5116bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
5117 MCStreamer &Out,
5118 const MCSubtargetInfo *STI) {
5119 MipsTargetStreamer &TOut = getTargetStreamer();
5120 unsigned ATReg = Mips::NoRegister;
5121 unsigned DReg = Inst.getOperand(0).getReg();
5122 unsigned SReg = Inst.getOperand(1).getReg();
5123 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
5124
5125 unsigned FirstShift = Mips::NOP;
5126 unsigned SecondShift = Mips::NOP;
5127
5128 MCInst TmpInst;
5129
5130 if (hasMips64r2()) {
5131 unsigned FinalOpcode = Mips::NOP;
5132 if (ImmValue == 0)
5133 FinalOpcode = Mips::DROTR;
5134 else if (ImmValue % 32 == 0)
5135 FinalOpcode = Mips::DROTR32;
5136 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
5137 if (Inst.getOpcode() == Mips::DROLImm)
5138 FinalOpcode = Mips::DROTR32;
5139 else
5140 FinalOpcode = Mips::DROTR;
5141 } else if (ImmValue >= 33) {
5142 if (Inst.getOpcode() == Mips::DROLImm)
5143 FinalOpcode = Mips::DROTR;
5144 else
5145 FinalOpcode = Mips::DROTR32;
5146 }
5147
5148 uint64_t ShiftValue = ImmValue % 32;
5149 if (Inst.getOpcode() == Mips::DROLImm)
5150 ShiftValue = (32 - ImmValue % 32) % 32;
5151
5152 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
5153
5154 return false;
5155 }
5156
5157 if (hasMips64()) {
5158 if (ImmValue == 0) {
5159 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
5160 return false;
5161 }
5162
5163 switch (Inst.getOpcode()) {
5164 default:
5165 llvm_unreachable("unexpected instruction opcode");
5166 case Mips::DROLImm:
5167 if ((ImmValue >= 1) && (ImmValue <= 31)) {
5168 FirstShift = Mips::DSLL;
5169 SecondShift = Mips::DSRL32;
5170 }
5171 if (ImmValue == 32) {
5172 FirstShift = Mips::DSLL32;
5173 SecondShift = Mips::DSRL32;
5174 }
5175 if ((ImmValue >= 33) && (ImmValue <= 63)) {
5176 FirstShift = Mips::DSLL32;
5177 SecondShift = Mips::DSRL;
5178 }
5179 break;
5180 case Mips::DRORImm:
5181 if ((ImmValue >= 1) && (ImmValue <= 31)) {
5182 FirstShift = Mips::DSRL;
5183 SecondShift = Mips::DSLL32;
5184 }
5185 if (ImmValue == 32) {
5186 FirstShift = Mips::DSRL32;
5187 SecondShift = Mips::DSLL32;
5188 }
5189 if ((ImmValue >= 33) && (ImmValue <= 63)) {
5190 FirstShift = Mips::DSRL32;
5191 SecondShift = Mips::DSLL;
5192 }
5193 break;
5194 }
5195
5196 ATReg = getATReg(Inst.getLoc());
5197 if (!ATReg)
5198 return true;
5199
5200 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
5201 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
5202 Inst.getLoc(), STI);
5203 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
5204
5205 return false;
5206 }
5207
5208 return true;
5209}
5210
5211bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5212 const MCSubtargetInfo *STI) {
5213 MipsTargetStreamer &TOut = getTargetStreamer();
5214 unsigned FirstRegOp = Inst.getOperand(0).getReg();
5215 unsigned SecondRegOp = Inst.getOperand(1).getReg();
5216
5217 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
5218 if (FirstRegOp != SecondRegOp)
5219 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
5220 else
5221 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
5222 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
5223
5224 return false;
5225}
5226
5227bool MipsAsmParser::expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5228 const MCSubtargetInfo *STI) {
5229 MipsTargetStreamer &TOut = getTargetStreamer();
5230 unsigned ATReg = Mips::NoRegister;
5231 unsigned DstReg = Inst.getOperand(0).getReg();
5232 unsigned SrcReg = Inst.getOperand(1).getReg();
5233 int32_t ImmValue = Inst.getOperand(2).getImm();
5234
5235 ATReg = getATReg(IDLoc);
5236 if (!ATReg)
5237 return true;
5238
5239 loadImmediate(ImmValue, ATReg, Mips::NoRegister, true, false, IDLoc, Out,
5240 STI);
5241
5242 TOut.emitRR(Inst.getOpcode() == Mips::MULImmMacro ? Mips::MULT : Mips::DMULT,
5243 SrcReg, ATReg, IDLoc, STI);
5244
5245 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
5246
5247 return false;
5248}
5249
5250bool MipsAsmParser::expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5251 const MCSubtargetInfo *STI) {
5252 MipsTargetStreamer &TOut = getTargetStreamer();
5253 unsigned ATReg = Mips::NoRegister;
5254 unsigned DstReg = Inst.getOperand(0).getReg();
5255 unsigned SrcReg = Inst.getOperand(1).getReg();
5256 unsigned TmpReg = Inst.getOperand(2).getReg();
5257
5258 ATReg = getATReg(Inst.getLoc());
5259 if (!ATReg)
5260 return true;
5261
5262 TOut.emitRR(Inst.getOpcode() == Mips::MULOMacro ? Mips::MULT : Mips::DMULT,
5263 SrcReg, TmpReg, IDLoc, STI);
5264
5265 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
5266
5267 TOut.emitRRI(Inst.getOpcode() == Mips::MULOMacro ? Mips::SRA : Mips::DSRA32,
5268 DstReg, DstReg, 0x1F, IDLoc, STI);
5269
5270 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
5271
5272 if (useTraps()) {
5273 TOut.emitRRI(Mips::TNE, DstReg, ATReg, 6, IDLoc, STI);
5274 } else {
5275 MCContext & Context = TOut.getStreamer().getContext();
5276 MCSymbol * BrTarget = Context.createTempSymbol();
5277 MCOperand LabelOp =
5279
5280 TOut.emitRRX(Mips::BEQ, DstReg, ATReg, LabelOp, IDLoc, STI);
5281 if (AssemblerOptions.back()->isReorder())
5282 TOut.emitNop(IDLoc, STI);
5283 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
5284
5285 TOut.getStreamer().emitLabel(BrTarget);
5286 }
5287 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
5288
5289 return false;
5290}
5291
5292bool MipsAsmParser::expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5293 const MCSubtargetInfo *STI) {
5294 MipsTargetStreamer &TOut = getTargetStreamer();
5295 unsigned ATReg = Mips::NoRegister;
5296 unsigned DstReg = Inst.getOperand(0).getReg();
5297 unsigned SrcReg = Inst.getOperand(1).getReg();
5298 unsigned TmpReg = Inst.getOperand(2).getReg();
5299
5300 ATReg = getATReg(IDLoc);
5301 if (!ATReg)
5302 return true;
5303
5304 TOut.emitRR(Inst.getOpcode() == Mips::MULOUMacro ? Mips::MULTu : Mips::DMULTu,
5305 SrcReg, TmpReg, IDLoc, STI);
5306
5307 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
5308 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
5309 if (useTraps()) {
5310 TOut.emitRRI(Mips::TNE, ATReg, Mips::ZERO, 6, IDLoc, STI);
5311 } else {
5312 MCContext & Context = TOut.getStreamer().getContext();
5313 MCSymbol * BrTarget = Context.createTempSymbol();
5314 MCOperand LabelOp =
5316
5317 TOut.emitRRX(Mips::BEQ, ATReg, Mips::ZERO, LabelOp, IDLoc, STI);
5318 if (AssemblerOptions.back()->isReorder())
5319 TOut.emitNop(IDLoc, STI);
5320 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
5321
5322 TOut.getStreamer().emitLabel(BrTarget);
5323 }
5324
5325 return false;
5326}
5327
5328bool MipsAsmParser::expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5329 const MCSubtargetInfo *STI) {
5330 MipsTargetStreamer &TOut = getTargetStreamer();
5331 unsigned DstReg = Inst.getOperand(0).getReg();
5332 unsigned SrcReg = Inst.getOperand(1).getReg();
5333 unsigned TmpReg = Inst.getOperand(2).getReg();
5334
5335 TOut.emitRR(Mips::DMULTu, SrcReg, TmpReg, IDLoc, STI);
5336 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
5337
5338 return false;
5339}
5340
5341// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
5342// lw $<reg+1>>, offset+4($reg2)'
5343// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);
5344// sw $<reg+1>>, offset+4($reg2)'
5345// for O32.
5346bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc,
5347 MCStreamer &Out,
5348 const MCSubtargetInfo *STI,
5349 bool IsLoad) {
5350 if (!isABI_O32())
5351 return true;
5352
5353 warnIfNoMacro(IDLoc);
5354
5355 MipsTargetStreamer &TOut = getTargetStreamer();
5356 unsigned Opcode = IsLoad ? Mips::LW : Mips::SW;
5357 unsigned FirstReg = Inst.getOperand(0).getReg();
5358 unsigned SecondReg = nextReg(FirstReg);
5359 unsigned BaseReg = Inst.getOperand(1).getReg();
5360 if (!SecondReg)
5361 return true;
5362
5363 warnIfRegIndexIsAT(FirstReg, IDLoc);
5364
5365 assert(Inst.getOperand(2).isImm() &&
5366 "Offset for load macro is not immediate!");
5367
5368 MCOperand &FirstOffset = Inst.getOperand(2);
5369 signed NextOffset = FirstOffset.getImm() + 4;
5370 MCOperand SecondOffset = MCOperand::createImm(NextOffset);
5371
5372 if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
5373 return true;
5374
5375 // For loads, clobber the base register with the second load instead of the
5376 // first if the BaseReg == FirstReg.
5377 if (FirstReg != BaseReg || !IsLoad) {
5378 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
5379 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
5380 } else {
5381 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
5382 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
5383 }
5384
5385 return false;
5386}
5387
5388
5389// Expand 's.d $<reg> offset($reg2)' to 'swc1 $<reg+1>, offset($reg2);
5390// swc1 $<reg>, offset+4($reg2)'
5391// or if little endian to 'swc1 $<reg>, offset($reg2);
5392// swc1 $<reg+1>, offset+4($reg2)'
5393// for Mips1.
5394bool MipsAsmParser::expandStoreDM1Macro(MCInst &Inst, SMLoc IDLoc,
5395 MCStreamer &Out,
5396 const MCSubtargetInfo *STI) {
5397 if (!isABI_O32())
5398 return true;
5399
5400 warnIfNoMacro(IDLoc);
5401
5402 MipsTargetStreamer &TOut = getTargetStreamer();
5403 unsigned Opcode = Mips::SWC1;
5404 unsigned FirstReg = Inst.getOperand(0).getReg();
5405 unsigned SecondReg = nextReg(FirstReg);
5406 unsigned BaseReg = Inst.getOperand(1).getReg();
5407 if (!SecondReg)
5408 return true;
5409
5410 warnIfRegIndexIsAT(FirstReg, IDLoc);
5411
5412 assert(Inst.getOperand(2).isImm() &&
5413 "Offset for macro is not immediate!");
5414
5415 MCOperand &FirstOffset = Inst.getOperand(2);
5416 signed NextOffset = FirstOffset.getImm() + 4;
5417 MCOperand SecondOffset = MCOperand::createImm(NextOffset);
5418
5419 if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
5420 return true;
5421
5422 if (!IsLittleEndian)
5423 std::swap(FirstReg, SecondReg);
5424
5425 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
5426 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
5427
5428 return false;
5429}
5430
5431bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5432 const MCSubtargetInfo *STI) {
5433 MipsTargetStreamer &TOut = getTargetStreamer();
5434
5435 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
5436 assert(Inst.getOperand(0).isReg() &&
5437 Inst.getOperand(1).isReg() &&
5438 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
5439
5440 unsigned DstReg = Inst.getOperand(0).getReg();
5441 unsigned SrcReg = Inst.getOperand(1).getReg();
5442 unsigned OpReg = Inst.getOperand(2).getReg();
5443
5444 warnIfNoMacro(IDLoc);
5445
5446 if (SrcReg != Mips::ZERO && OpReg != Mips::ZERO) {
5447 TOut.emitRRR(Mips::XOR, DstReg, SrcReg, OpReg, IDLoc, STI);
5448 TOut.emitRRI(Mips::SLTiu, DstReg, DstReg, 1, IDLoc, STI);
5449 return false;
5450 }
5451
5452 unsigned Reg = SrcReg == Mips::ZERO ? OpReg : SrcReg;
5453 TOut.emitRRI(Mips::SLTiu, DstReg, Reg, 1, IDLoc, STI);
5454 return false;
5455}
5456
5457bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5458 const MCSubtargetInfo *STI) {
5459 MipsTargetStreamer &TOut = getTargetStreamer();
5460
5461 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
5462 assert(Inst.getOperand(0).isReg() &&
5463 Inst.getOperand(1).isReg() &&
5464 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
5465
5466 unsigned DstReg = Inst.getOperand(0).getReg();
5467 unsigned SrcReg = Inst.getOperand(1).getReg();
5468 int64_t Imm = Inst.getOperand(2).getImm();
5469
5470 warnIfNoMacro(IDLoc);
5471
5472 if (Imm == 0) {
5473 TOut.emitRRI(Mips::SLTiu, DstReg, SrcReg, 1, IDLoc, STI);
5474 return false;
5475 }
5476
5477 if (SrcReg == Mips::ZERO) {
5478 Warning(IDLoc, "comparison is always false");
5479 TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu,
5480 DstReg, SrcReg, SrcReg, IDLoc, STI);
5481 return false;
5482 }
5483
5484 unsigned Opc;
5485 if (Imm > -0x8000 && Imm < 0) {
5486 Imm = -Imm;
5487 Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;
5488 } else {
5489 Opc = Mips::XORi;
5490 }
5491
5492 if (!isUInt<16>(Imm)) {
5493 unsigned ATReg = getATReg(IDLoc);
5494 if (!ATReg)
5495 return true;
5496
5497 if (loadImmediate(Imm, ATReg, Mips::NoRegister, true, isGP64bit(), IDLoc,
5498 Out, STI))
5499 return true;
5500
5501 TOut.emitRRR(Mips::XOR, DstReg, SrcReg, ATReg, IDLoc, STI);
5502 TOut.emitRRI(Mips::SLTiu, DstReg, DstReg, 1, IDLoc, STI);
5503 return false;
5504 }
5505
5506 TOut.emitRRI(Opc, DstReg, SrcReg, Imm, IDLoc, STI);
5507 TOut.emitRRI(Mips::SLTiu, DstReg, DstReg, 1, IDLoc, STI);
5508 return false;
5509}
5510
5511bool MipsAsmParser::expandSne(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5512 const MCSubtargetInfo *STI) {
5513
5514 MipsTargetStreamer &TOut = getTargetStreamer();
5515
5516 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
5517 assert(Inst.getOperand(0).isReg() &&
5518 Inst.getOperand(1).isReg() &&
5519 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
5520
5521 unsigned DstReg = Inst.getOperand(0).getReg();
5522 unsigned SrcReg = Inst.getOperand(1).getReg();
5523 unsigned OpReg = Inst.getOperand(2).getReg();
5524
5525 warnIfNoMacro(IDLoc);
5526
5527 if (SrcReg != Mips::ZERO && OpReg != Mips::ZERO) {
5528 TOut.emitRRR(Mips::XOR, DstReg, SrcReg, OpReg, IDLoc, STI);
5529 TOut.emitRRR(Mips::SLTu, DstReg, Mips::ZERO, DstReg, IDLoc, STI);
5530 return false;
5531 }
5532
5533 unsigned Reg = SrcReg == Mips::ZERO ? OpReg : SrcReg;
5534 TOut.emitRRR(Mips::SLTu, DstReg, Mips::ZERO, Reg, IDLoc, STI);
5535 return false;
5536}
5537
5538bool MipsAsmParser::expandSneI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5539 const MCSubtargetInfo *STI) {
5540 MipsTargetStreamer &TOut = getTargetStreamer();
5541
5542 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
5543 assert(Inst.getOperand(0).isReg() &&
5544 Inst.getOperand(1).isReg() &&
5545 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
5546
5547 unsigned DstReg = Inst.getOperand(0).getReg();
5548 unsigned SrcReg = Inst.getOperand(1).getReg();
5549 int64_t ImmValue = Inst.getOperand(2).getImm();
5550
5551 warnIfNoMacro(IDLoc);
5552
5553 if (ImmValue == 0) {
5554 TOut.emitRRR(Mips::SLTu, DstReg, Mips::ZERO, SrcReg, IDLoc, STI);
5555 return false;
5556 }
5557
5558 if (SrcReg == Mips::ZERO) {
5559 Warning(IDLoc, "comparison is always true");
5560 if (loadImmediate(1, DstReg, Mips::NoRegister, true, false, IDLoc, Out,
5561 STI))
5562 return true;
5563 return false;
5564 }
5565
5566 unsigned Opc;
5567 if (ImmValue > -0x8000 && ImmValue < 0) {
5568 ImmValue = -ImmValue;
5569 Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;
5570 } else {
5571 Opc = Mips::XORi;
5572 }
5573
5574 if (isUInt<16>(ImmValue)) {
5575 TOut.emitRRI(Opc, DstReg, SrcReg, ImmValue, IDLoc, STI);
5576 TOut.emitRRR(Mips::SLTu, DstReg, Mips::ZERO, DstReg, IDLoc, STI);
5577 return false;
5578 }
5579
5580 unsigned ATReg = getATReg(IDLoc);
5581 if (!ATReg)
5582 return true;
5583
5584 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue),
5585 false, IDLoc, Out, STI))
5586 return true;
5587
5588 TOut.emitRRR(Mips::XOR, DstReg, SrcReg, ATReg, IDLoc, STI);
5589 TOut.emitRRR(Mips::SLTu, DstReg, Mips::ZERO, DstReg, IDLoc, STI);
5590 return false;
5591}
5592
5593// Map the DSP accumulator and control register to the corresponding gpr
5594// operand. Unlike the other alias, the m(f|t)t(lo|hi|acx) instructions
5595// do not map the DSP registers contigously to gpr registers.
5596static unsigned getRegisterForMxtrDSP(MCInst &Inst, bool IsMFDSP) {
5597 switch (Inst.getOpcode()) {
5598 case Mips::MFTLO:
5599 case Mips::MTTLO:
5600 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
5601 case Mips::AC0:
5602 return Mips::ZERO;
5603 case Mips::AC1:
5604 return Mips::A0;
5605 case Mips::AC2:
5606 return Mips::T0;
5607 case Mips::AC3:
5608 return Mips::T4;
5609 default:
5610 llvm_unreachable("Unknown register for 'mttr' alias!");
5611 }
5612 case Mips::MFTHI:
5613 case Mips::MTTHI:
5614 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
5615 case Mips::AC0:
5616 return Mips::AT;
5617 case Mips::AC1:
5618 return Mips::A1;
5619 case Mips::AC2:
5620 return Mips::T1;
5621 case Mips::AC3:
5622 return Mips::T5;
5623 default:
5624 llvm_unreachable("Unknown register for 'mttr' alias!");
5625 }
5626 case Mips::MFTACX:
5627 case Mips::MTTACX:
5628 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
5629 case Mips::AC0:
5630 return Mips::V0;
5631 case Mips::AC1:
5632 return Mips::A2;
5633 case Mips::AC2:
5634 return Mips::T2;
5635 case Mips::AC3:
5636 return Mips::T6;
5637 default:
5638 llvm_unreachable("Unknown register for 'mttr' alias!");
5639 }
5640 case Mips::MFTDSP:
5641 case Mips::MTTDSP:
5642 return Mips::S0;
5643 default:
5644 llvm_unreachable("Unknown instruction for 'mttr' dsp alias!");
5645 }
5646}
5647
5648// Map the floating point register operand to the corresponding register
5649// operand.
5650static unsigned getRegisterForMxtrFP(MCInst &Inst, bool IsMFTC1) {
5651 switch (Inst.getOperand(IsMFTC1 ? 1 : 0).getReg()) {
5652 case Mips::F0: return Mips::ZERO;
5653 case Mips::F1: return Mips::AT;
5654 case Mips::F2: return Mips::V0;
5655 case Mips::F3: return Mips::V1;
5656 case Mips::F4: return Mips::A0;
5657 case Mips::F5: return Mips::A1;
5658 case Mips::F6: return Mips::A2;
5659 case Mips::F7: return Mips::A3;
5660 case Mips::F8: return Mips::T0;
5661 case Mips::F9: return Mips::T1;
5662 case Mips::F10: return Mips::T2;
5663 case Mips::F11: return Mips::T3;
5664 case Mips::F12: return Mips::T4;
5665 case Mips::F13: return Mips::T5;
5666 case Mips::F14: return Mips::T6;
5667 case Mips::F15: return Mips::T7;
5668 case Mips::F16: return Mips::S0;
5669 case Mips::F17: return Mips::S1;
5670 case Mips::F18: return Mips::S2;
5671 case Mips::F19: return Mips::S3;
5672 case Mips::F20: return Mips::S4;
5673 case Mips::F21: return Mips::S5;
5674 case Mips::F22: return Mips::S6;
5675 case Mips::F23: return Mips::S7;
5676 case Mips::F24: return Mips::T8;
5677 case Mips::F25: return Mips::T9;
5678 case Mips::F26: return Mips::K0;
5679 case Mips::F27: return Mips::K1;
5680 case Mips::F28: return Mips::GP;
5681 case Mips::F29: return Mips::SP;
5682 case Mips::F30: return Mips::FP;
5683 case Mips::F31: return Mips::RA;
5684 default: llvm_unreachable("Unknown register for mttc1 alias!");
5685 }
5686}
5687
5688// Map the coprocessor operand the corresponding gpr register operand.
5689static unsigned getRegisterForMxtrC0(MCInst &Inst, bool IsMFTC0) {
5690 switch (Inst.getOperand(IsMFTC0 ? 1 : 0).getReg()) {
5691 case Mips::COP00: return Mips::ZERO;
5692 case Mips::COP01: return Mips::AT;
5693 case Mips::COP02: return Mips::V0;
5694 case Mips::COP03: return Mips::V1;
5695 case Mips::COP04: return Mips::A0;
5696 case Mips::COP05: return Mips::A1;
5697 case Mips::COP06: return Mips::A2;
5698 case Mips::COP07: return Mips::A3;
5699 case Mips::COP08: return Mips::T0;
5700 case Mips::COP09: return Mips::T1;
5701 case Mips::COP010: return Mips::T2;
5702 case Mips::COP011: return Mips::T3;
5703 case Mips::COP012: return Mips::T4;
5704 case Mips::COP013: return Mips::T5;
5705 case Mips::COP014: return Mips::T6;
5706 case Mips::COP015: return Mips::T7;
5707 case Mips::COP016: return Mips::S0;
5708 case Mips::COP017: return Mips::S1;
5709 case Mips::COP018: return Mips::S2;
5710 case Mips::COP019: return Mips::S3;
5711 case Mips::COP020: return Mips::S4;
5712 case Mips::COP021: return Mips::S5;
5713 case Mips::COP022: return Mips::S6;
5714 case Mips::COP023: return Mips::S7;
5715 case Mips::COP024: return Mips::T8;
5716 case Mips::COP025: return Mips::T9;
5717 case Mips::COP026: return Mips::K0;
5718 case Mips::COP027: return Mips::K1;
5719 case Mips::COP028: return Mips::GP;
5720 case Mips::COP029: return Mips::SP;
5721 case Mips::COP030: return Mips::FP;
5722 case Mips::COP031: return Mips::RA;
5723 default: llvm_unreachable("Unknown register for mttc0 alias!");
5724 }
5725}
5726
5727/// Expand an alias of 'mftr' or 'mttr' into the full instruction, by producing
5728/// an mftr or mttr with the correctly mapped gpr register, u, sel and h bits.
5729bool MipsAsmParser::expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5730 const MCSubtargetInfo *STI) {
5731 MipsTargetStreamer &TOut = getTargetStreamer();
5732 unsigned rd = 0;
5733 unsigned u = 1;
5734 unsigned sel = 0;
5735 unsigned h = 0;
5736 bool IsMFTR = false;
5737 switch (Inst.getOpcode()) {
5738 case Mips::MFTC0:
5739 IsMFTR = true;
5740 [[fallthrough]];
5741 case Mips::MTTC0:
5742 u = 0;
5743 rd = getRegisterForMxtrC0(Inst, IsMFTR);
5744 sel = Inst.getOperand(2).getImm();
5745 break;
5746 case Mips::MFTGPR:
5747 IsMFTR = true;
5748 [[fallthrough]];
5749 case Mips::MTTGPR:
5750 rd = Inst.getOperand(IsMFTR ? 1 : 0).getReg();
5751 break;
5752 case Mips::MFTLO:
5753 case Mips::MFTHI:
5754 case Mips::MFTACX:
5755 case Mips::MFTDSP:
5756 IsMFTR = true;
5757 [[fallthrough]];
5758 case Mips::MTTLO:
5759 case Mips::MTTHI:
5760 case Mips::MTTACX:
5761 case Mips::MTTDSP:
5762 rd = getRegisterForMxtrDSP(Inst, IsMFTR);
5763 sel = 1;
5764 break;
5765 case Mips::MFTHC1:
5766 h = 1;
5767 [[fallthrough]];
5768 case Mips::MFTC1:
5769 IsMFTR = true;
5770 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5771 sel = 2;
5772 break;
5773 case Mips::MTTHC1:
5774 h = 1;
5775 [[fallthrough]];
5776 case Mips::MTTC1:
5777 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5778 sel = 2;
5779 break;
5780 case Mips::CFTC1:
5781 IsMFTR = true;
5782 [[fallthrough]];
5783 case Mips::CTTC1:
5784 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5785 sel = 3;
5786 break;
5787 }
5788 MCRegister Op0 = IsMFTR ? Inst.getOperand(0).getReg() : MCRegister(rd);
5789 MCRegister Op1 =
5790 IsMFTR ? MCRegister(rd)
5791 : (Inst.getOpcode() != Mips::MTTDSP ? Inst.getOperand(1).getReg()
5792 : Inst.getOperand(0).getReg());
5793
5794 TOut.emitRRIII(IsMFTR ? Mips::MFTR : Mips::MTTR, Op0, Op1, u, sel, h, IDLoc,
5795 STI);
5796 return false;
5797}
5798
5799bool MipsAsmParser::expandSaaAddr(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5800 const MCSubtargetInfo *STI) {
5801 assert(Inst.getNumOperands() == 3 && "expected three operands");
5802 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
5803 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
5804
5805 warnIfNoMacro(IDLoc);
5806
5807 MipsTargetStreamer &TOut = getTargetStreamer();
5808 unsigned Opcode = Inst.getOpcode() == Mips::SaaAddr ? Mips::SAA : Mips::SAAD;
5809 unsigned RtReg = Inst.getOperand(0).getReg();
5810 unsigned BaseReg = Inst.getOperand(1).getReg();
5811 const MCOperand &BaseOp = Inst.getOperand(2);
5812
5813 if (BaseOp.isImm()) {
5814 int64_t ImmValue = BaseOp.getImm();
5815 if (ImmValue == 0) {
5816 TOut.emitRR(Opcode, RtReg, BaseReg, IDLoc, STI);
5817 return false;
5818 }
5819 }
5820
5821 unsigned ATReg = getATReg(IDLoc);
5822 if (!ATReg)
5823 return true;
5824
5825 if (expandLoadAddress(ATReg, BaseReg, BaseOp, !isGP64bit(), IDLoc, Out, STI))
5826 return true;
5827
5828 TOut.emitRR(Opcode, RtReg, ATReg, IDLoc, STI);
5829 return false;
5830}
5831
5832unsigned
5833MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
5834 const OperandVector &Operands) {
5835 switch (Inst.getOpcode()) {
5836 default:
5837 return Match_Success;
5838 case Mips::DATI:
5839 case Mips::DAHI:
5840 if (static_cast<MipsOperand &>(*Operands[1])
5841 .isValidForTie(static_cast<MipsOperand &>(*Operands[2])))
5842 return Match_Success;
5843 return Match_RequiresSameSrcAndDst;
5844 }
5845}
5846
5847unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
5848 switch (Inst.getOpcode()) {
5849 // As described by the MIPSR6 spec, daui must not use the zero operand for
5850 // its source operand.
5851 case Mips::DAUI:
5852 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
5853 Inst.getOperand(1).getReg() == Mips::ZERO_64)
5854 return Match_RequiresNoZeroRegister;
5855 return Match_Success;
5856 // As described by the Mips32r2 spec, the registers Rd and Rs for
5857 // jalr.hb must be different.
5858 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
5859 // and registers Rd and Base for microMIPS lwp instruction
5860 case Mips::JALR_HB:
5861 case Mips::JALR_HB64:
5862 case Mips::JALRC_HB_MMR6:
5863 case Mips::JALRC_MMR6:
5864 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
5865 return Match_RequiresDifferentSrcAndDst;
5866 return Match_Success;
5867 case Mips::LWP_MM:
5868 if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
5869 return Match_RequiresDifferentSrcAndDst;
5870 return Match_Success;
5871 case Mips::SYNC:
5872 if (Inst.getOperand(0).getImm() != 0 && !hasMips32())
5873 return Match_NonZeroOperandForSync;
5874 return Match_Success;
5875 case Mips::MFC0:
5876 case Mips::MTC0:
5877 case Mips::MTC2:
5878 case Mips::MFC2:
5879 if (Inst.getOperand(2).getImm() != 0 && !hasMips32())
5880 return Match_NonZeroOperandForMTCX;
5881 return Match_Success;
5882 // As described the MIPSR6 spec, the compact branches that compare registers
5883 // must:
5884 // a) Not use the zero register.
5885 // b) Not use the same register twice.
5886 // c) rs < rt for bnec, beqc.
5887 // NB: For this case, the encoding will swap the operands as their
5888 // ordering doesn't matter. GAS performs this transformation too.
5889 // Hence, that constraint does not have to be enforced.
5890 //
5891 // The compact branches that branch iff the signed addition of two registers
5892 // would overflow must have rs >= rt. That can be handled like beqc/bnec with
5893 // operand swapping. They do not have restriction of using the zero register.
5894 case Mips::BLEZC: case Mips::BLEZC_MMR6:
5895 case Mips::BGEZC: case Mips::BGEZC_MMR6:
5896 case Mips::BGTZC: case Mips::BGTZC_MMR6:
5897 case Mips::BLTZC: case Mips::BLTZC_MMR6:
5898 case Mips::BEQZC: case Mips::BEQZC_MMR6:
5899 case Mips::BNEZC: case Mips::BNEZC_MMR6:
5900 case Mips::BLEZC64:
5901 case Mips::BGEZC64:
5902 case Mips::BGTZC64:
5903 case Mips::BLTZC64:
5904 case Mips::BEQZC64:
5905 case Mips::BNEZC64:
5906 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
5907 Inst.getOperand(0).getReg() == Mips::ZERO_64)
5908 return Match_RequiresNoZeroRegister;
5909 return Match_Success;
5910 case Mips::BGEC: case Mips::BGEC_MMR6:
5911 case Mips::BLTC: case Mips::BLTC_MMR6:
5912 case Mips::BGEUC: case Mips::BGEUC_MMR6:
5913 case Mips::BLTUC: case Mips::BLTUC_MMR6:
5914 case Mips::BEQC: case Mips::BEQC_MMR6:
5915 case Mips::BNEC: case Mips::BNEC_MMR6:
5916 case Mips::BGEC64:
5917 case Mips::BLTC64:
5918 case Mips::BGEUC64:
5919 case Mips::BLTUC64:
5920 case Mips::BEQC64:
5921 case Mips::BNEC64:
5922 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
5923 Inst.getOperand(0).getReg() == Mips::ZERO_64)
5924 return Match_RequiresNoZeroRegister;
5925 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
5926 Inst.getOperand(1).getReg() == Mips::ZERO_64)
5927 return Match_RequiresNoZeroRegister;
5928 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
5929 return Match_RequiresDifferentOperands;
5930 return Match_Success;
5931 case Mips::DINS: {
5932 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5933 "Operands must be immediates for dins!");
5934 const signed Pos = Inst.getOperand(2).getImm();
5935 const signed Size = Inst.getOperand(3).getImm();
5936 if ((0 > (Pos + Size)) || ((Pos + Size) > 32))
5937 return Match_RequiresPosSizeRange0_32;
5938 return Match_Success;
5939 }
5940 case Mips::DINSM:
5941 case Mips::DINSU: {
5942 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5943 "Operands must be immediates for dinsm/dinsu!");
5944 const signed Pos = Inst.getOperand(2).getImm();
5945 const signed Size = Inst.getOperand(3).getImm();
5946 if ((32 >= (Pos + Size)) || ((Pos + Size) > 64))
5947 return Match_RequiresPosSizeRange33_64;
5948 return Match_Success;
5949 }
5950 case Mips::DEXT: {
5951 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5952 "Operands must be immediates for DEXTM!");
5953 const signed Pos = Inst.getOperand(2).getImm();
5954 const signed Size = Inst.getOperand(3).getImm();
5955 if ((1 > (Pos + Size)) || ((Pos + Size) > 63))
5956 return Match_RequiresPosSizeUImm6;
5957 return Match_Success;
5958 }
5959 case Mips::DEXTM:
5960 case Mips::DEXTU: {
5961 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5962 "Operands must be immediates for dextm/dextu!");
5963 const signed Pos = Inst.getOperand(2).getImm();
5964 const signed Size = Inst.getOperand(3).getImm();
5965 if ((32 > (Pos + Size)) || ((Pos + Size) > 64))
5966 return Match_RequiresPosSizeRange33_64;
5967 return Match_Success;
5968 }
5969 case Mips::CRC32B: case Mips::CRC32CB:
5970 case Mips::CRC32H: case Mips::CRC32CH:
5971 case Mips::CRC32W: case Mips::CRC32CW:
5972 case Mips::CRC32D: case Mips::CRC32CD:
5973 if (Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg())
5974 return Match_RequiresSameSrcAndDst;
5975 return Match_Success;
5976 }
5977
5978 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags;
5979 if ((TSFlags & MipsII::HasFCCRegOperand) &&
5980 (Inst.getOperand(0).getReg() != Mips::FCC0) && !hasEightFccRegisters())
5981 return Match_NoFCCRegisterForCurrentISA;
5982
5983 return Match_Success;
5984
5985}
5986
5989 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
5990 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
5991 if (ErrorLoc == SMLoc())
5992 return Loc;
5993 return ErrorLoc;
5994 }
5995 return Loc;
5996}
5997
5998bool MipsAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
6000 MCStreamer &Out,
6002 bool MatchingInlineAsm) {
6003 MCInst Inst;
6004 unsigned MatchResult =
6005 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
6006
6007 switch (MatchResult) {
6008 case Match_Success:
6009 if (processInstruction(Inst, IDLoc, Out, STI))
6010 return true;
6011 return false;
6012 case Match_MissingFeature:
6013 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
6014 return true;
6015 case Match_InvalidTiedOperand:
6016 Error(IDLoc, "operand must match destination register");
6017 return true;
6018 case Match_InvalidOperand: {
6019 SMLoc ErrorLoc = IDLoc;
6020 if (ErrorInfo != ~0ULL) {
6021 if (ErrorInfo >= Operands.size())
6022 return Error(IDLoc, "too few operands for instruction");
6023
6024 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
6025 if (ErrorLoc == SMLoc())
6026 ErrorLoc = IDLoc;
6027 }
6028
6029 return Error(ErrorLoc, "invalid operand for instruction");
6030 }
6031 case Match_NonZeroOperandForSync:
6032 return Error(IDLoc,
6033 "s-type must be zero or unspecified for pre-MIPS32 ISAs");
6034 case Match_NonZeroOperandForMTCX:
6035 return Error(IDLoc, "selector must be zero for pre-MIPS32 ISAs");
6036 case Match_MnemonicFail:
6037 return Error(IDLoc, "invalid instruction");
6038 case Match_RequiresDifferentSrcAndDst:
6039 return Error(IDLoc, "source and destination must be different");
6040 case Match_RequiresDifferentOperands:
6041 return Error(IDLoc, "registers must be different");
6042 case Match_RequiresNoZeroRegister:
6043 return Error(IDLoc, "invalid operand ($zero) for instruction");
6044 case Match_RequiresSameSrcAndDst:
6045 return Error(IDLoc, "source and destination must match");
6046 case Match_NoFCCRegisterForCurrentISA:
6047 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6048 "non-zero fcc register doesn't exist in current ISA level");
6049 case Match_Immz:
6050 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
6051 case Match_UImm1_0:
6052 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6053 "expected 1-bit unsigned immediate");
6054 case Match_UImm2_0:
6055 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6056 "expected 2-bit unsigned immediate");
6057 case Match_UImm2_1:
6058 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6059 "expected immediate in range 1 .. 4");
6060 case Match_UImm3_0:
6061 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6062 "expected 3-bit unsigned immediate");
6063 case Match_UImm4_0:
6064 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6065 "expected 4-bit unsigned immediate");
6066 case Match_SImm4_0:
6067 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6068 "expected 4-bit signed immediate");
6069 case Match_UImm5_0:
6070 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6071 "expected 5-bit unsigned immediate");
6072 case Match_SImm5_0:
6073 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6074 "expected 5-bit signed immediate");
6075 case Match_UImm5_1:
6076 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6077 "expected immediate in range 1 .. 32");
6078 case Match_UImm5_32:
6079 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6080 "expected immediate in range 32 .. 63");
6081 case Match_UImm5_33:
6082 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6083 "expected immediate in range 33 .. 64");
6084 case Match_UImm5_0_Report_UImm6:
6085 // This is used on UImm5 operands that have a corresponding UImm5_32
6086 // operand to avoid confusing the user.
6087 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6088 "expected 6-bit unsigned immediate");
6089 case Match_UImm5_Lsl2:
6090 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6091 "expected both 7-bit unsigned immediate and multiple of 4");
6092 case Match_UImmRange2_64:
6093 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6094 "expected immediate in range 2 .. 64");
6095 case Match_UImm6_0:
6096 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6097 "expected 6-bit unsigned immediate");
6098 case Match_UImm6_Lsl2:
6099 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6100 "expected both 8-bit unsigned immediate and multiple of 4");
6101 case Match_SImm6_0:
6102 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6103 "expected 6-bit signed immediate");
6104 case Match_UImm7_0:
6105 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6106 "expected 7-bit unsigned immediate");
6107 case Match_UImm7_N1:
6108 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6109 "expected immediate in range -1 .. 126");
6110 case Match_SImm7_Lsl2:
6111 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6112 "expected both 9-bit signed immediate and multiple of 4");
6113 case Match_UImm8_0:
6114 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6115 "expected 8-bit unsigned immediate");
6116 case Match_UImm10_0:
6117 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6118 "expected 10-bit unsigned immediate");
6119 case Match_SImm10_0:
6120 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6121 "expected 10-bit signed immediate");
6122 case Match_SImm11_0:
6123 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6124 "expected 11-bit signed immediate");
6125 case Match_UImm16:
6126 case Match_UImm16_Relaxed:
6127 case Match_UImm16_AltRelaxed:
6128 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6129 "expected 16-bit unsigned immediate");
6130 case Match_SImm16:
6131 case Match_SImm16_Relaxed:
6132 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6133 "expected 16-bit signed immediate");
6134 case Match_SImm19_Lsl2:
6135 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6136 "expected both 19-bit signed immediate and multiple of 4");
6137 case Match_UImm20_0:
6138 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6139 "expected 20-bit unsigned immediate");
6140 case Match_UImm26_0:
6141 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6142 "expected 26-bit unsigned immediate");
6143 case Match_SImm32:
6144 case Match_SImm32_Relaxed:
6145 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6146 "expected 32-bit signed immediate");
6147 case Match_UImm32_Coerced:
6148 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6149 "expected 32-bit immediate");
6150 case Match_MemSImm9:
6151 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6152 "expected memory with 9-bit signed offset");
6153 case Match_MemSImm10:
6154 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6155 "expected memory with 10-bit signed offset");
6156 case Match_MemSImm10Lsl1:
6157 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6158 "expected memory with 11-bit signed offset and multiple of 2");
6159 case Match_MemSImm10Lsl2:
6160 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6161 "expected memory with 12-bit signed offset and multiple of 4");
6162 case Match_MemSImm10Lsl3:
6163 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6164 "expected memory with 13-bit signed offset and multiple of 8");
6165 case Match_MemSImm11:
6166 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6167 "expected memory with 11-bit signed offset");
6168 case Match_MemSImm12:
6169 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6170 "expected memory with 12-bit signed offset");
6171 case Match_MemSImm16:
6172 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6173 "expected memory with 16-bit signed offset");
6174 case Match_MemSImmPtr:
6175 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
6176 "expected memory with 32-bit signed offset");
6177 case Match_RequiresPosSizeRange0_32: {
6178 SMLoc ErrorStart = Operands[3]->getStartLoc();
6179 SMLoc ErrorEnd = Operands[4]->getEndLoc();
6180 return Error(ErrorStart, "size plus position are not in the range 0 .. 32",
6181 SMRange(ErrorStart, ErrorEnd));
6182 }
6183 case Match_RequiresPosSizeUImm6: {
6184 SMLoc ErrorStart = Operands[3]->getStartLoc();
6185 SMLoc ErrorEnd = Operands[4]->getEndLoc();
6186 return Error(ErrorStart, "size plus position are not in the range 1 .. 63",
6187 SMRange(ErrorStart, ErrorEnd));
6188 }
6189 case Match_RequiresPosSizeRange33_64: {
6190 SMLoc ErrorStart = Operands[3]->getStartLoc();
6191 SMLoc ErrorEnd = Operands[4]->getEndLoc();
6192 return Error(ErrorStart, "size plus position are not in the range 33 .. 64",
6193 SMRange(ErrorStart, ErrorEnd));
6194 }
6195 }
6196
6197 llvm_unreachable("Implement any new match types added!");
6198}
6199
6200void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
6201 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
6202 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
6203 ") without \".set noat\"");
6204}
6205
6206void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
6207 if (!AssemblerOptions.back()->isMacro())
6208 Warning(Loc, "macro instruction expanded into multiple instructions");
6209}
6210
6211void MipsAsmParser::ConvertXWPOperands(MCInst &Inst,
6212 const OperandVector &Operands) {
6213 assert(
6214 (Inst.getOpcode() == Mips::LWP_MM || Inst.getOpcode() == Mips::SWP_MM) &&
6215 "Unexpected instruction!");
6216 ((MipsOperand &)*Operands[1]).addGPR32ZeroAsmRegOperands(Inst, 1);
6217 int NextReg = nextReg(((MipsOperand &)*Operands[1]).getGPR32Reg());
6218 Inst.addOperand(MCOperand::createReg(NextReg));
6219 ((MipsOperand &)*Operands[2]).addMemOperands(Inst, 2);
6220}
6221
6222void
6223MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
6224 SMRange Range, bool ShowColors) {
6225 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
6226 Range, SMFixIt(Range, FixMsg),
6227 ShowColors);
6228}
6229
6230int MipsAsmParser::matchCPURegisterName(StringRef Name) {
6231 int CC;
6232
6234 .Case("zero", 0)
6235 .Cases("at", "AT", 1)
6236 .Case("a0", 4)
6237 .Case("a1", 5)
6238 .Case("a2", 6)
6239 .Case("a3", 7)
6240 .Case("v0", 2)
6241 .Case("v1", 3)
6242 .Case("s0", 16)
6243 .Case("s1", 17)
6244 .Case("s2", 18)
6245 .Case("s3", 19)
6246 .Case("s4", 20)
6247 .Case("s5", 21)
6248 .Case("s6", 22)
6249 .Case("s7", 23)
6250 .Case("k0", 26)
6251 .Case("k1", 27)
6252 .Case("gp", 28)
6253 .Case("sp", 29)
6254 .Case("fp", 30)
6255 .Case("s8", 30)
6256 .Case("ra", 31)
6257 .Case("t0", 8)
6258 .Case("t1", 9)
6259 .Case("t2", 10)
6260 .Case("t3", 11)
6261 .Case("t4", 12)
6262 .Case("t5", 13)
6263 .Case("t6", 14)
6264 .Case("t7", 15)
6265 .Case("t8", 24)
6266 .Case("t9", 25)
6267 .Default(-1);
6268
6269 if (!(isABI_N32() || isABI_N64()))
6270 return CC;
6271
6272 if (12 <= CC && CC <= 15) {
6273 // Name is one of t4-t7
6274 AsmToken RegTok = getLexer().peekTok();
6275 SMRange RegRange = RegTok.getLocRange();
6276
6278 .Case("t4", "t0")
6279 .Case("t5", "t1")
6280 .Case("t6", "t2")
6281 .Case("t7", "t3")
6282 .Default("");
6283 assert(FixedName != "" && "Register name is not one of t4-t7.");
6284
6285 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
6286 "Did you mean $" + FixedName + "?", RegRange);
6287 }
6288
6289 // Although SGI documentation just cuts out t0-t3 for n32/n64,
6290 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
6291 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
6292 if (8 <= CC && CC <= 11)
6293 CC += 4;
6294
6295 if (CC == -1)
6297 .Case("a4", 8)
6298 .Case("a5", 9)
6299 .Case("a6", 10)
6300 .Case("a7", 11)
6301 .Case("kt0", 26)
6302 .Case("kt1", 27)
6303 .Default(-1);
6304
6305 return CC;
6306}
6307
6308int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
6309 int CC;
6310
6312 .Case("hwr_cpunum", 0)
6313 .Case("hwr_synci_step", 1)
6314 .Case("hwr_cc", 2)
6315 .Case("hwr_ccres", 3)
6316 .Case("hwr_ulr", 29)
6317 .Default(-1);
6318
6319 return CC;
6320}
6321
6322int MipsAsmParser::matchFPURegisterName(StringRef Name) {
6323 if (Name[0] == 'f') {
6324 StringRef NumString = Name.substr(1);
6325 unsigned IntVal;
6326 if (NumString.getAsInteger(10, IntVal))
6327 return -1; // This is not an integer.
6328 if (IntVal > 31) // Maximum index for fpu register.
6329 return -1;
6330 return IntVal;
6331 }
6332 return -1;
6333}
6334
6335int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
6336 if (Name.starts_with("fcc")) {
6337 StringRef NumString = Name.substr(3);
6338 unsigned IntVal;
6339 if (NumString.getAsInteger(10, IntVal))
6340 return -1; // This is not an integer.
6341 if (IntVal > 7) // There are only 8 fcc registers.
6342 return -1;
6343 return IntVal;
6344 }
6345 return -1;
6346}
6347
6348int MipsAsmParser::matchACRegisterName(StringRef Name) {
6349 if (Name.starts_with("ac")) {
6350 StringRef NumString = Name.substr(2);
6351 unsigned IntVal;
6352 if (NumString.getAsInteger(10, IntVal))
6353 return -1; // This is not an integer.
6354 if (IntVal > 3) // There are only 3 acc registers.
6355 return -1;
6356 return IntVal;
6357 }
6358 return -1;
6359}
6360
6361int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
6362 unsigned IntVal;
6363
6364 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
6365 return -1;
6366
6367 if (IntVal > 31)
6368 return -1;
6369
6370 return IntVal;
6371}
6372
6373int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
6374 int CC;
6375
6377 .Case("msair", 0)
6378 .Case("msacsr", 1)
6379 .Case("msaaccess", 2)
6380 .Case("msasave", 3)
6381 .Case("msamodify", 4)
6382 .Case("msarequest", 5)
6383 .Case("msamap", 6)
6384 .Case("msaunmap", 7)
6385 .Default(-1);
6386
6387 return CC;
6388}
6389
6390bool MipsAsmParser::canUseATReg() {
6391 return AssemblerOptions.back()->getATRegIndex() != 0;
6392}
6393
6394unsigned MipsAsmParser::getATReg(SMLoc Loc) {
6395 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
6396 if (ATIndex == 0) {
6397 reportParseError(Loc,
6398 "pseudo-instruction requires $at, which is not available");
6399 return 0;
6400 }
6401 unsigned AT = getReg(
6402 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
6403 return AT;
6404}
6405
6406unsigned MipsAsmParser::getReg(int RC, int RegNo) {
6407 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
6408}
6409
6410bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
6411 MCAsmParser &Parser = getParser();
6412 LLVM_DEBUG(dbgs() << "parseOperand\n");
6413
6414 // Check if the current operand has a custom associated parser, if so, try to
6415 // custom parse the operand, or fallback to the general approach.
6416 // Setting the third parameter to true tells the parser to keep parsing even
6417 // if the operands are not supported with the current feature set. In this
6418 // case, the instruction matcher will output a "instruction requires a CPU
6419 // feature not currently enabled" error. If this were false, the parser would
6420 // stop here and output a less useful "invalid operand" error.
6421 ParseStatus Res = MatchOperandParserImpl(Operands, Mnemonic, true);
6422 if (Res.isSuccess())
6423 return false;
6424 // If there wasn't a custom match, try the generic matcher below. Otherwise,
6425 // there was a match, but an error occurred, in which case, just return that
6426 // the operand parsing failed.
6427 if (Res.isFailure())
6428 return true;
6429
6430 LLVM_DEBUG(dbgs() << ".. Generic Parser\n");
6431
6432 switch (getLexer().getKind()) {
6433 case AsmToken::Dollar: {
6434 // Parse the register.
6435 SMLoc S = Parser.getTok().getLoc();
6436
6437 // Almost all registers have been parsed by custom parsers. There is only
6438 // one exception to this. $zero (and it's alias $0) will reach this point
6439 // for div, divu, and similar instructions because it is not an operand
6440 // to the instruction definition but an explicit register. Special case
6441 // this situation for now.
6442 if (!parseAnyRegister(Operands).isNoMatch())
6443 return false;
6444
6445 // Maybe it is a symbol reference.
6447 if (Parser.parseIdentifier(Identifier))
6448 return true;
6449
6451 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
6452 // Otherwise create a symbol reference.
6453 const MCExpr *SymRef =
6455
6456 Operands.push_back(MipsOperand::CreateImm(SymRef, S, E, *this));
6457 return false;
6458 }
6459 default: {
6460 LLVM_DEBUG(dbgs() << ".. generic integer expression\n");
6461
6462 const MCExpr *Expr;
6463 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
6464 if (getParser().parseExpression(Expr))
6465 return true;
6466
6468
6469 Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));
6470 return false;
6471 }
6472 } // switch(getLexer().getKind())
6473 return true;
6474}
6475
6476bool MipsAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
6477 SMLoc &EndLoc) {
6478 return !tryParseRegister(Reg, StartLoc, EndLoc).isSuccess();
6479}
6480
6481ParseStatus MipsAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
6482 SMLoc &EndLoc) {
6484 ParseStatus Res = parseAnyRegister(Operands);
6485 if (Res.isSuccess()) {
6486 assert(Operands.size() == 1);
6487 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
6488 StartLoc = Operand.getStartLoc();
6489 EndLoc = Operand.getEndLoc();
6490
6491 // AFAIK, we only support numeric registers and named GPR's in CFI
6492 // directives.
6493 // Don't worry about eating tokens before failing. Using an unrecognised
6494 // register is a parse error.
6495 if (Operand.isGPRAsmReg()) {
6496 // Resolve to GPR32 or GPR64 appropriately.
6497 Reg = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
6498 }
6499
6500 return (Reg == (unsigned)-1) ? ParseStatus::NoMatch : ParseStatus::Success;
6501 }
6502
6503 assert(Operands.size() == 0);
6504 return (Reg == (unsigned)-1) ? ParseStatus::NoMatch : ParseStatus::Success;
6505}
6506
6507bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
6508 SMLoc S;
6509
6510 if (isParenExpr)
6511 return getParser().parseParenExprOfDepth(0, Res, S);
6512 return getParser().parseExpression(Res);
6513}
6514
6515ParseStatus MipsAsmParser::parseMemOperand(OperandVector &Operands) {
6516 MCAsmParser &Parser = getParser();
6517 LLVM_DEBUG(dbgs() << "parseMemOperand\n");
6518 const MCExpr *IdVal = nullptr;
6519 SMLoc S;
6520 bool isParenExpr = false;
6522 // First operand is the offset.
6523 S = Parser.getTok().getLoc();
6524
6525 if (getLexer().getKind() == AsmToken::LParen) {
6526 Parser.Lex();
6527 isParenExpr = true;
6528 }
6529
6530 if (getLexer().getKind() != AsmToken::Dollar) {
6531 if (parseMemOffset(IdVal, isParenExpr))
6532 return ParseStatus::Failure;
6533
6534 const AsmToken &Tok = Parser.getTok(); // Get the next token.
6535 if (Tok.isNot(AsmToken::LParen)) {
6536 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
6537 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
6538 SMLoc E =
6540 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
6541 return ParseStatus::Success;
6542 }
6543 if (Tok.is(AsmToken::EndOfStatement)) {
6544 SMLoc E =
6546
6547 // Zero register assumed, add a memory operand with ZERO as its base.
6548 // "Base" will be managed by k_Memory.
6549 auto Base = MipsOperand::createGPRReg(
6550 0, "0", getContext().getRegisterInfo(), S, E, *this);
6551 Operands.push_back(
6552 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
6553 return ParseStatus::Success;
6554 }
6555 MCBinaryExpr::Opcode Opcode;
6556 // GAS and LLVM treat comparison operators different. GAS will generate -1
6557 // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is
6558 // highly unlikely to be found in a memory offset expression, we don't
6559 // handle them.
6560 switch (Tok.getKind()) {
6561 case AsmToken::Plus:
6562 Opcode = MCBinaryExpr::Add;
6563 Parser.Lex();
6564 break;
6565 case AsmToken::Minus:
6566 Opcode = MCBinaryExpr::Sub;
6567 Parser.Lex();
6568 break;
6569 case AsmToken::Star:
6570 Opcode = MCBinaryExpr::Mul;
6571 Parser.Lex();
6572 break;
6573 case AsmToken::Pipe:
6574 Opcode = MCBinaryExpr::Or;
6575 Parser.Lex();
6576 break;
6577 case AsmToken::Amp:
6578 Opcode = MCBinaryExpr::And;
6579 Parser.Lex();
6580 break;
6581 case AsmToken::LessLess:
6582 Opcode = MCBinaryExpr::Shl;
6583 Parser.Lex();
6584 break;
6586 Opcode = MCBinaryExpr::LShr;
6587 Parser.Lex();
6588 break;
6589 case AsmToken::Caret:
6590 Opcode = MCBinaryExpr::Xor;
6591 Parser.Lex();
6592 break;
6593 case AsmToken::Slash:
6594 Opcode = MCBinaryExpr::Div;
6595 Parser.Lex();
6596 break;
6597 case AsmToken::Percent:
6598 Opcode = MCBinaryExpr::Mod;
6599 Parser.Lex();
6600 break;
6601 default:
6602 return Error(Parser.getTok().getLoc(), "'(' or expression expected");
6603 }
6604 const MCExpr * NextExpr;
6605 if (getParser().parseExpression(NextExpr))
6606 return ParseStatus::Failure;
6607 IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext());
6608 }
6609
6610 Parser.Lex(); // Eat the '(' token.
6611 }
6612
6613 Res = parseAnyRegister(Operands);
6614 if (!Res.isSuccess())
6615 return Res;
6616
6617 if (Parser.getTok().isNot(AsmToken::RParen))
6618 return Error(Parser.getTok().getLoc(), "')' expected");
6619
6621
6622 Parser.Lex(); // Eat the ')' token.
6623
6624 if (!IdVal)
6625 IdVal = MCConstantExpr::create(0, getContext());
6626
6627 // Replace the register operand with the memory operand.
6628 std::unique_ptr<MipsOperand> op(
6629 static_cast<MipsOperand *>(Operands.back().release()));
6630 // Remove the register from the operands.
6631 // "op" will be managed by k_Memory.
6632 Operands.pop_back();
6633 // Add the memory operand.
6634 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
6635 int64_t Imm;
6636 if (IdVal->evaluateAsAbsolute(Imm))
6637 IdVal = MCConstantExpr::create(Imm, getContext());
6638 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
6639 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
6640 getContext());
6641 }
6642
6643 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
6644 return ParseStatus::Success;
6645}
6646
6647bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
6648 MCAsmParser &Parser = getParser();
6649 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
6650 if (!Sym)
6651 return false;
6652
6653 SMLoc S = Parser.getTok().getLoc();
6654 if (Sym->isVariable()) {
6655 const MCExpr *Expr = Sym->getVariableValue();
6656 if (Expr->getKind() == MCExpr::SymbolRef) {
6657 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
6658 StringRef DefSymbol = Ref->getSymbol().getName();
6659 if (DefSymbol.starts_with("$")) {
6660 ParseStatus Res =
6661 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
6662 if (Res.isSuccess()) {
6663 Parser.Lex();
6664 return true;
6665 }
6666 if (Res.isFailure())
6667 llvm_unreachable("Should never fail");
6668 }
6669 }
6670 } else if (Sym->isUnset()) {
6671 // If symbol is unset, it might be created in the `parseSetAssignment`
6672 // routine as an alias for a numeric register name.
6673 // Lookup in the aliases list.
6674 auto Entry = RegisterSets.find(Sym->getName());
6675 if (Entry != RegisterSets.end()) {
6676 ParseStatus Res =
6677 matchAnyRegisterWithoutDollar(Operands, Entry->getValue(), S);
6678 if (Res.isSuccess()) {
6679 Parser.Lex();
6680 return true;
6681 }
6682 }
6683 }
6684
6685 return false;
6686}
6687
6688ParseStatus MipsAsmParser::matchAnyRegisterNameWithoutDollar(
6689 OperandVector &Operands, StringRef Identifier, SMLoc S) {
6690 int Index = matchCPURegisterName(Identifier);
6691 if (Index != -1) {
6692 Operands.push_back(MipsOperand::createGPRReg(
6693 Index, Identifier, getContext().getRegisterInfo(), S,
6694 getLexer().getLoc(), *this));
6695 return ParseStatus::Success;
6696 }
6697
6698 Index = matchHWRegsRegisterName(Identifier);
6699 if (Index != -1) {
6700 Operands.push_back(MipsOperand::createHWRegsReg(
6701 Index, Identifier, getContext().getRegisterInfo(), S,
6702 getLexer().getLoc(), *this));
6703 return ParseStatus::Success;
6704 }
6705
6706 Index = matchFPURegisterName(Identifier);
6707 if (Index != -1) {
6708 Operands.push_back(MipsOperand::createFGRReg(
6709 Index, Identifier, getContext().getRegisterInfo(), S,
6710 getLexer().getLoc(), *this));
6711 return ParseStatus::Success;
6712 }
6713
6714 Index = matchFCCRegisterName(Identifier);
6715 if (Index != -1) {
6716 Operands.push_back(MipsOperand::createFCCReg(
6717 Index, Identifier, getContext().getRegisterInfo(), S,
6718 getLexer().getLoc(), *this));
6719 return ParseStatus::Success;
6720 }
6721
6722 Index = matchACRegisterName(Identifier);
6723 if (Index != -1) {
6724 Operands.push_back(MipsOperand::createACCReg(
6725 Index, Identifier, getContext().getRegisterInfo(), S,
6726 getLexer().getLoc(), *this));
6727 return ParseStatus::Success;
6728 }
6729
6730 Index = matchMSA128RegisterName(Identifier);
6731 if (Index != -1) {
6732 Operands.push_back(MipsOperand::createMSA128Reg(
6733 Index, Identifier, getContext().getRegisterInfo(), S,
6734 getLexer().getLoc(), *this));
6735 return ParseStatus::Success;
6736 }
6737
6738 Index = matchMSA128CtrlRegisterName(Identifier);
6739 if (Index != -1) {
6740 Operands.push_back(MipsOperand::createMSACtrlReg(
6741 Index, Identifier, getContext().getRegisterInfo(), S,
6742 getLexer().getLoc(), *this));
6743 return ParseStatus::Success;
6744 }
6745
6746 return ParseStatus::NoMatch;
6747}
6748
6750MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands,
6751 const AsmToken &Token, SMLoc S) {
6752 if (Token.is(AsmToken::Identifier)) {
6753 LLVM_DEBUG(dbgs() << ".. identifier\n");
6755 return matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
6756 }
6757 if (Token.is(AsmToken::Integer)) {
6758 LLVM_DEBUG(dbgs() << ".. integer\n");
6759 int64_t RegNum = Token.getIntVal();
6760 if (RegNum < 0 || RegNum > 31) {
6761 // Show the error, but treat invalid register
6762 // number as a normal one to continue parsing
6763 // and catch other possible errors.
6764 Error(getLexer().getLoc(), "invalid register number");
6765 }
6766 Operands.push_back(MipsOperand::createNumericReg(
6767 RegNum, Token.getString(), getContext().getRegisterInfo(), S,
6768 Token.getLoc(), *this));
6769 return ParseStatus::Success;
6770 }
6771
6772 LLVM_DEBUG(dbgs() << Token.getKind() << "\n");
6773
6774 return ParseStatus::NoMatch;
6775}
6776
6778MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
6779 auto Token = getLexer().peekTok(false);
6780 return matchAnyRegisterWithoutDollar(Operands, Token, S);
6781}
6782
6783ParseStatus MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
6784 MCAsmParser &Parser = getParser();
6785 LLVM_DEBUG(dbgs() << "parseAnyRegister\n");
6786
6787 auto Token = Parser.getTok();
6788
6789 SMLoc S = Token.getLoc();
6790
6791 if (Token.isNot(AsmToken::Dollar)) {
6792 LLVM_DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
6793 if (Token.is(AsmToken::Identifier)) {
6794 if (searchSymbolAlias(Operands))
6795 return ParseStatus::Success;
6796 }
6797 LLVM_DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
6798 return ParseStatus::NoMatch;
6799 }
6800 LLVM_DEBUG(dbgs() << ".. $\n");
6801
6802 ParseStatus Res = matchAnyRegisterWithoutDollar(Operands, S);
6803 if (Res.isSuccess()) {
6804 Parser.Lex(); // $
6805 Parser.Lex(); // identifier
6806 }
6807 return Res;
6808}
6809
6810ParseStatus MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
6811 MCAsmParser &Parser = getParser();
6812 LLVM_DEBUG(dbgs() << "parseJumpTarget\n");
6813
6814 SMLoc S = getLexer().getLoc();
6815
6816 // Registers are a valid target and have priority over symbols.
6817 ParseStatus Res = parseAnyRegister(Operands);
6818 if (!Res.isNoMatch())
6819 return Res;
6820
6821 // Integers and expressions are acceptable
6822 const MCExpr *Expr = nullptr;
6823 if (Parser.parseExpression(Expr)) {
6824 // We have no way of knowing if a symbol was consumed so we must ParseFail
6825 return ParseStatus::Failure;
6826 }
6827 Operands.push_back(
6828 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
6829 return ParseStatus::Success;
6830}
6831
6832ParseStatus MipsAsmParser::parseInvNum(OperandVector &Operands) {
6833 MCAsmParser &Parser = getParser();
6834 const MCExpr *IdVal;
6835 // If the first token is '$' we may have register operand. We have to reject
6836 // cases where it is not a register. Complicating the matter is that
6837 // register names are not reserved across all ABIs.
6838 // Peek past the dollar to see if it's a register name for this ABI.
6839 SMLoc S = Parser.getTok().getLoc();
6840 if (Parser.getTok().is(AsmToken::Dollar)) {
6841 return matchCPURegisterName(Parser.getLexer().peekTok().getString()) == -1
6844 }
6845 if (getParser().parseExpression(IdVal))
6846 return ParseStatus::Failure;
6847 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
6848 if (!MCE)
6849 return ParseStatus::NoMatch;
6850 int64_t Val = MCE->getValue();
6852 Operands.push_back(MipsOperand::CreateImm(
6853 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
6854 return ParseStatus::Success;
6855}
6856
6857ParseStatus MipsAsmParser::parseRegisterList(OperandVector &Operands) {
6858 MCAsmParser &Parser = getParser();
6860 unsigned RegNo;
6861 unsigned PrevReg = Mips::NoRegister;
6862 bool RegRange = false;
6864
6865 if (Parser.getTok().isNot(AsmToken::Dollar))
6866 return ParseStatus::Failure;
6867
6868 SMLoc S = Parser.getTok().getLoc();
6869 while (parseAnyRegister(TmpOperands).isSuccess()) {
6870 SMLoc E = getLexer().getLoc();
6871 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
6872 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
6873 if (RegRange) {
6874 // Remove last register operand because registers from register range
6875 // should be inserted first.
6876 if ((isGP64bit() && RegNo == Mips::RA_64) ||
6877 (!isGP64bit() && RegNo == Mips::RA)) {
6878 Regs.push_back(RegNo);
6879 } else {
6880 unsigned TmpReg = PrevReg + 1;
6881 while (TmpReg <= RegNo) {
6882 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
6883 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
6884 isGP64bit()))
6885 return Error(E, "invalid register operand");
6886
6887 PrevReg = TmpReg;
6888 Regs.push_back(TmpReg++);
6889 }
6890 }
6891
6892 RegRange = false;
6893 } else {
6894 if ((PrevReg == Mips::NoRegister) &&
6895 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
6896 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA))))
6897 return Error(E, "$16 or $31 expected");
6898 if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
6899 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
6900 !isGP64bit()) ||
6901 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
6902 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
6903 isGP64bit())))
6904 return Error(E, "invalid register operand");
6905 if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
6906 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
6907 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 && isGP64bit())))
6908 return Error(E, "consecutive register numbers expected");
6909
6910 Regs.push_back(RegNo);
6911 }
6912
6913 if (Parser.getTok().is(AsmToken::Minus))
6914 RegRange = true;
6915
6916 if (!Parser.getTok().isNot(AsmToken::Minus) &&
6917 !Parser.getTok().isNot(AsmToken::Comma))
6918 return Error(E, "',' or '-' expected");
6919
6920 Lex(); // Consume comma or minus
6921 if (Parser.getTok().isNot(AsmToken::Dollar))
6922 break;
6923
6924 PrevReg = RegNo;
6925 }
6926
6927 SMLoc E = Parser.getTok().getLoc();
6928 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
6929 parseMemOperand(Operands);
6930 return ParseStatus::Success;
6931}
6932
6933/// Sometimes (i.e. load/stores) the operand may be followed immediately by
6934/// either this.
6935/// ::= '(', register, ')'
6936/// handle it before we iterate so we don't get tripped up by the lack of
6937/// a comma.
6938bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
6939 MCAsmParser &Parser = getParser();
6940 if (getLexer().is(AsmToken::LParen)) {
6941 Operands.push_back(
6942 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
6943 Parser.Lex();
6944 if (parseOperand(Operands, Name)) {
6945 SMLoc Loc = getLexer().getLoc();
6946 return Error(Loc, "unexpected token in argument list");
6947 }
6948 if (Parser.getTok().isNot(AsmToken::RParen)) {
6949 SMLoc Loc = getLexer().getLoc();
6950 return Error(Loc, "unexpected token, expected ')'");
6951 }
6952 Operands.push_back(
6953 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
6954 Parser.Lex();
6955 }
6956 return false;
6957}
6958
6959/// Sometimes (i.e. in MSA) the operand may be followed immediately by
6960/// either one of these.
6961/// ::= '[', register, ']'
6962/// ::= '[', integer, ']'
6963/// handle it before we iterate so we don't get tripped up by the lack of
6964/// a comma.
6965bool MipsAsmParser::parseBracketSuffix(StringRef Name,
6967 MCAsmParser &Parser = getParser();
6968 if (getLexer().is(AsmToken::LBrac)) {
6969 Operands.push_back(
6970 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
6971 Parser.Lex();
6972 if (parseOperand(Operands, Name)) {
6973 SMLoc Loc = getLexer().getLoc();
6974 return Error(Loc, "unexpected token in argument list");
6975 }
6976 if (Parser.getTok().isNot(AsmToken::RBrac)) {
6977 SMLoc Loc = getLexer().getLoc();
6978 return Error(Loc, "unexpected token, expected ']'");
6979 }
6980 Operands.push_back(
6981 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
6982 Parser.Lex();
6983 }
6984 return false;
6985}
6986
6987static std::string MipsMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS,
6988 unsigned VariantID = 0);
6989
6990bool MipsAsmParser::areEqualRegs(const MCParsedAsmOperand &Op1,
6991 const MCParsedAsmOperand &Op2) const {
6992 // This target-overriden function exists to maintain current behaviour for
6993 // e.g.
6994 // dahi $3, $3, 0x5678
6995 // as tested in test/MC/Mips/mips64r6/valid.s.
6996 // FIXME: Should this test actually fail with an error? If so, then remove
6997 // this overloaded method.
6998 if (!Op1.isReg() || !Op2.isReg())
6999 return true;
7000 return Op1.getReg() == Op2.getReg();
7001}
7002
7003bool MipsAsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Name,
7004 SMLoc NameLoc, OperandVector &Operands) {
7005 MCAsmParser &Parser = getParser();
7006 LLVM_DEBUG(dbgs() << "parseInstruction\n");
7007
7008 // We have reached first instruction, module directive are now forbidden.
7009 getTargetStreamer().forbidModuleDirective();
7010
7011 // Check if we have valid mnemonic
7012 if (!mnemonicIsValid(Name, 0)) {
7013 FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
7014 std::string Suggestion = MipsMnemonicSpellCheck(Name, FBS);
7015 return Error(NameLoc, "unknown instruction" + Suggestion);
7016 }
7017 // First operand in MCInst is instruction mnemonic.
7018 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
7019
7020 // Read the remaining operands.
7021 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7022 // Read the first operand.
7023 if (parseOperand(Operands, Name)) {
7024 SMLoc Loc = getLexer().getLoc();
7025 return Error(Loc, "unexpected token in argument list");
7026 }
7027 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
7028 return true;
7029 // AFAIK, parenthesis suffixes are never on the first operand
7030
7031 while (getLexer().is(AsmToken::Comma)) {
7032 Parser.Lex(); // Eat the comma.
7033 // Parse and remember the operand.
7034 if (parseOperand(Operands, Name)) {
7035 SMLoc Loc = getLexer().getLoc();
7036 return Error(Loc, "unexpected token in argument list");
7037 }
7038 // Parse bracket and parenthesis suffixes before we iterate
7039 if (getLexer().is(AsmToken::LBrac)) {
7040 if (parseBracketSuffix(Name, Operands))
7041 return true;
7042 } else if (getLexer().is(AsmToken::LParen) &&
7043 parseParenSuffix(Name, Operands))
7044 return true;
7045 }
7046 }
7047 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7048 SMLoc Loc = getLexer().getLoc();
7049 return Error(Loc, "unexpected token in argument list");
7050 }
7051 Parser.Lex(); // Consume the EndOfStatement.
7052 return false;
7053}
7054
7055// FIXME: Given that these have the same name, these should both be
7056// consistent on affecting the Parser.
7057bool MipsAsmParser::reportParseError(const Twine &ErrorMsg) {
7058 SMLoc Loc = getLexer().getLoc();
7059 return Error(Loc, ErrorMsg);
7060}
7061
7062bool MipsAsmParser::reportParseError(SMLoc Loc, const Twine &ErrorMsg) {
7063 return Error(Loc, ErrorMsg);
7064}
7065
7066bool MipsAsmParser::parseSetNoAtDirective() {
7067 MCAsmParser &Parser = getParser();
7068 // Line should look like: ".set noat".
7069
7070 // Set the $at register to $0.
7071 AssemblerOptions.back()->setATRegIndex(0);
7072
7073 Parser.Lex(); // Eat "noat".
7074
7075 // If this is not the end of the statement, report an error.
7076 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7077 reportParseError("unexpected token, expected end of statement");
7078 return false;
7079 }
7080
7081 getTargetStreamer().emitDirectiveSetNoAt();
7082 Parser.Lex(); // Consume the EndOfStatement.
7083 return false;
7084}
7085
7086bool MipsAsmParser::parseSetAtDirective() {
7087 // Line can be: ".set at", which sets $at to $1
7088 // or ".set at=$reg", which sets $at to $reg.
7089 MCAsmParser &Parser = getParser();
7090 Parser.Lex(); // Eat "at".
7091
7092 if (getLexer().is(AsmToken::EndOfStatement)) {
7093 // No register was specified, so we set $at to $1.
7094 AssemblerOptions.back()->setATRegIndex(1);
7095
7096 getTargetStreamer().emitDirectiveSetAt();
7097 Parser.Lex(); // Consume the EndOfStatement.
7098 return false;
7099 }
7100
7101 if (getLexer().isNot(AsmToken::Equal)) {
7102 reportParseError("unexpected token, expected equals sign");
7103 return false;
7104 }
7105 Parser.Lex(); // Eat "=".
7106
7107 if (getLexer().isNot(AsmToken::Dollar)) {
7108 if (getLexer().is(AsmToken::EndOfStatement)) {
7109 reportParseError("no register specified");
7110 return false;
7111 } else {
7112 reportParseError("unexpected token, expected dollar sign '$'");
7113 return false;
7114 }
7115 }
7116 Parser.Lex(); // Eat "$".
7117
7118 // Find out what "reg" is.
7119 unsigned AtRegNo;
7120 const AsmToken &Reg = Parser.getTok();
7121 if (Reg.is(AsmToken::Identifier)) {
7122 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
7123 } else if (Reg.is(AsmToken::Integer)) {
7124 AtRegNo = Reg.getIntVal();
7125 } else {
7126 reportParseError("unexpected token, expected identifier or integer");
7127 return false;
7128 }
7129
7130 // Check if $reg is a valid register. If it is, set $at to $reg.
7131 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
7132 reportParseError("invalid register");
7133 return false;
7134 }
7135 Parser.Lex(); // Eat "reg".
7136
7137 // If this is not the end of the statement, report an error.
7138 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7139 reportParseError("unexpected token, expected end of statement");
7140 return false;
7141 }
7142
7143 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
7144
7145 Parser.Lex(); // Consume the EndOfStatement.
7146 return false;
7147}
7148
7149bool MipsAsmParser::parseSetReorderDirective() {
7150 MCAsmParser &Parser = getParser();
7151 Parser.Lex();
7152 // If this is not the end of the statement, report an error.
7153 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7154 reportParseError("unexpected token, expected end of statement");
7155 return false;
7156 }
7157 AssemblerOptions.back()->setReorder();
7158 getTargetStreamer().emitDirectiveSetReorder();
7159 Parser.Lex(); // Consume the EndOfStatement.
7160 return false;
7161}
7162
7163bool MipsAsmParser::parseSetNoReorderDirective() {
7164 MCAsmParser &Parser = getParser();
7165 Parser.Lex();
7166 // If this is not the end of the statement, report an error.
7167 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7168 reportParseError("unexpected token, expected end of statement");
7169 return false;
7170 }
7171 AssemblerOptions.back()->setNoReorder();
7172 getTargetStreamer().emitDirectiveSetNoReorder();
7173 Parser.Lex(); // Consume the EndOfStatement.
7174 return false;
7175}
7176
7177bool MipsAsmParser::parseSetMacroDirective() {
7178 MCAsmParser &Parser = getParser();
7179 Parser.Lex();
7180 // If this is not the end of the statement, report an error.
7181 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7182 reportParseError("unexpected token, expected end of statement");
7183 return false;
7184 }
7185 AssemblerOptions.back()->setMacro();
7186 getTargetStreamer().emitDirectiveSetMacro();
7187 Parser.Lex(); // Consume the EndOfStatement.
7188 return false;
7189}
7190
7191bool MipsAsmParser::parseSetNoMacroDirective() {
7192 MCAsmParser &Parser = getParser();
7193 Parser.Lex();
7194 // If this is not the end of the statement, report an error.
7195 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7196 reportParseError("unexpected token, expected end of statement");
7197 return false;
7198 }
7199 if (AssemblerOptions.back()->isReorder()) {
7200 reportParseError("`noreorder' must be set before `nomacro'");
7201 return false;
7202 }
7203 AssemblerOptions.back()->setNoMacro();
7204 getTargetStreamer().emitDirectiveSetNoMacro();
7205 Parser.Lex(); // Consume the EndOfStatement.
7206 return false;
7207}
7208
7209bool MipsAsmParser::parseSetMsaDirective() {
7210 MCAsmParser &Parser = getParser();
7211 Parser.Lex();
7212
7213 // If this is not the end of the statement, report an error.
7214 if (getLexer().isNot(AsmToken::EndOfStatement))
7215 return reportParseError("unexpected token, expected end of statement");
7216
7217 setFeatureBits(Mips::FeatureMSA, "msa");
7218 getTargetStreamer().emitDirectiveSetMsa();
7219 return false;
7220}
7221
7222bool MipsAsmParser::parseSetNoMsaDirective() {
7223 MCAsmParser &Parser = getParser();
7224 Parser.Lex();
7225
7226 // If this is not the end of the statement, report an error.
7227 if (getLexer().isNot(AsmToken::EndOfStatement))
7228 return reportParseError("unexpected token, expected end of statement");
7229
7230 clearFeatureBits(Mips::FeatureMSA, "msa");
7231 getTargetStreamer().emitDirectiveSetNoMsa();
7232 return false;
7233}
7234
7235bool MipsAsmParser::parseSetNoDspDirective() {
7236 MCAsmParser &Parser = getParser();
7237 Parser.Lex(); // Eat "nodsp".
7238
7239 // If this is not the end of the statement, report an error.
7240 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7241 reportParseError("unexpected token, expected end of statement");
7242 return false;
7243 }
7244
7245 clearFeatureBits(Mips::FeatureDSP, "dsp");
7246 getTargetStreamer().emitDirectiveSetNoDsp();
7247 return false;
7248}
7249
7250bool MipsAsmParser::parseSetNoMips3DDirective() {
7251 MCAsmParser &Parser = getParser();
7252 Parser.Lex(); // Eat "nomips3d".
7253
7254 // If this is not the end of the statement, report an error.
7255 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7256 reportParseError("unexpected token, expected end of statement");
7257 return false;
7258 }
7259
7260 clearFeatureBits(Mips::FeatureMips3D, "mips3d");
7261 getTargetStreamer().emitDirectiveSetNoMips3D();
7262 return false;
7263}
7264
7265bool MipsAsmParser::parseSetMips16Directive() {
7266 MCAsmParser &Parser = getParser();
7267 Parser.Lex(); // Eat "mips16".
7268
7269 // If this is not the end of the statement, report an error.
7270 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7271 reportParseError("unexpected token, expected end of statement");
7272 return false;
7273 }
7274
7275 setFeatureBits(Mips::FeatureMips16, "mips16");
7276 getTargetStreamer().emitDirectiveSetMips16();
7277 Parser.Lex(); // Consume the EndOfStatement.
7278 return false;
7279}
7280
7281bool MipsAsmParser::parseSetNoMips16Directive() {
7282 MCAsmParser &Parser = getParser();
7283 Parser.Lex(); // Eat "nomips16".
7284
7285 // If this is not the end of the statement, report an error.
7286 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7287 reportParseError("unexpected token, expected end of statement");
7288 return false;
7289 }
7290
7291 clearFeatureBits(Mips::FeatureMips16, "mips16");
7292 getTargetStreamer().emitDirectiveSetNoMips16();
7293 Parser.Lex(); // Consume the EndOfStatement.
7294 return false;
7295}
7296
7297bool MipsAsmParser::parseSetFpDirective() {
7298 MCAsmParser &Parser = getParser();
7300 // Line can be: .set fp=32
7301 // .set fp=xx
7302 // .set fp=64
7303 Parser.Lex(); // Eat fp token
7304 AsmToken Tok = Parser.getTok();
7305 if (Tok.isNot(AsmToken::Equal)) {
7306 reportParseError("unexpected token, expected equals sign '='");
7307 return false;
7308 }
7309 Parser.Lex(); // Eat '=' token.
7310 Tok = Parser.getTok();
7311
7312 if (!parseFpABIValue(FpAbiVal, ".set"))
7313 return false;
7314
7315 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7316 reportParseError("unexpected token, expected end of statement");
7317 return false;
7318 }
7319 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
7320 Parser.Lex(); // Consume the EndOfStatement.
7321 return false;
7322}
7323
7324bool MipsAsmParser::parseSetOddSPRegDirective() {
7325 MCAsmParser &Parser = getParser();
7326
7327 Parser.Lex(); // Eat "oddspreg".
7328 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7329 reportParseError("unexpected token, expected end of statement");
7330 return false;
7331 }
7332
7333 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
7334 getTargetStreamer().emitDirectiveSetOddSPReg();
7335 return false;
7336}
7337
7338bool MipsAsmParser::parseSetNoOddSPRegDirective() {
7339 MCAsmParser &Parser = getParser();
7340
7341 Parser.Lex(); // Eat "nooddspreg".
7342 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7343 reportParseError("unexpected token, expected end of statement");
7344 return false;
7345 }
7346
7347 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
7348 getTargetStreamer().emitDirectiveSetNoOddSPReg();
7349 return false;
7350}
7351
7352bool MipsAsmParser::parseSetMtDirective() {
7353 MCAsmParser &Parser = getParser();
7354 Parser.Lex(); // Eat "mt".
7355
7356 // If this is not the end of the statement, report an error.
7357 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7358 reportParseError("unexpected token, expected end of statement");
7359 return false;
7360 }
7361
7362 setFeatureBits(Mips::FeatureMT, "mt");
7363 getTargetStreamer().emitDirectiveSetMt();
7364 Parser.Lex(); // Consume the EndOfStatement.
7365 return false;
7366}
7367
7368bool MipsAsmParser::parseSetNoMtDirective() {
7369 MCAsmParser &Parser = getParser();
7370 Parser.Lex(); // Eat "nomt".
7371
7372 // If this is not the end of the statement, report an error.
7373 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7374 reportParseError("unexpected token, expected end of statement");
7375 return false;
7376 }
7377
7378 clearFeatureBits(Mips::FeatureMT, "mt");
7379
7380 getTargetStreamer().emitDirectiveSetNoMt();
7381 Parser.Lex(); // Consume the EndOfStatement.
7382 return false;
7383}
7384
7385bool MipsAsmParser::parseSetNoCRCDirective() {
7386 MCAsmParser &Parser = getParser();
7387 Parser.Lex(); // Eat "nocrc".
7388
7389 // If this is not the end of the statement, report an error.
7390 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7391 reportParseError("unexpected token, expected end of statement");
7392 return false;
7393 }
7394
7395 clearFeatureBits(Mips::FeatureCRC, "crc");
7396
7397 getTargetStreamer().emitDirectiveSetNoCRC();
7398 Parser.Lex(); // Consume the EndOfStatement.
7399 return false;
7400}
7401
7402bool MipsAsmParser::parseSetNoVirtDirective() {
7403 MCAsmParser &Parser = getParser();
7404 Parser.Lex(); // Eat "novirt".
7405
7406 // If this is not the end of the statement, report an error.
7407 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7408 reportParseError("unexpected token, expected end of statement");
7409 return false;
7410 }
7411
7412 clearFeatureBits(Mips::FeatureVirt, "virt");
7413
7414 getTargetStreamer().emitDirectiveSetNoVirt();
7415 Parser.Lex(); // Consume the EndOfStatement.
7416 return false;
7417}
7418
7419bool MipsAsmParser::parseSetNoGINVDirective() {
7420 MCAsmParser &Parser = getParser();
7421 Parser.Lex(); // Eat "noginv".
7422
7423 // If this is not the end of the statement, report an error.
7424 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7425 reportParseError("unexpected token, expected end of statement");
7426 return false;
7427 }
7428
7429 clearFeatureBits(Mips::FeatureGINV, "ginv");
7430
7431 getTargetStreamer().emitDirectiveSetNoGINV();
7432 Parser.Lex(); // Consume the EndOfStatement.
7433 return false;
7434}
7435
7436bool MipsAsmParser::parseSetPopDirective() {
7437 MCAsmParser &Parser = getParser();
7438 SMLoc Loc = getLexer().getLoc();
7439
7440 Parser.Lex();
7441 if (getLexer().isNot(AsmToken::EndOfStatement))
7442 return reportParseError("unexpected token, expected end of statement");
7443
7444 // Always keep an element on the options "stack" to prevent the user
7445 // from changing the initial options. This is how we remember them.
7446 if (AssemblerOptions.size() == 2)
7447 return reportParseError(Loc, ".set pop with no .set push");
7448
7449 MCSubtargetInfo &STI = copySTI();
7450 AssemblerOptions.pop_back();
7451 setAvailableFeatures(
7452 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
7453 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
7454
7455 getTargetStreamer().emitDirectiveSetPop();
7456 return false;
7457}
7458
7459bool MipsAsmParser::parseSetPushDirective() {
7460 MCAsmParser &Parser = getParser();
7461 Parser.Lex();
7462 if (getLexer().isNot(AsmToken::EndOfStatement))
7463 return reportParseError("unexpected token, expected end of statement");
7464
7465 // Create a copy of the current assembler options environment and push it.
7466 AssemblerOptions.push_back(
7467 std::make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
7468
7469 getTargetStreamer().emitDirectiveSetPush();
7470 return false;
7471}
7472
7473bool MipsAsmParser::parseSetSoftFloatDirective() {
7474 MCAsmParser &Parser = getParser();
7475 Parser.Lex();
7476 if (getLexer().isNot(AsmToken::EndOfStatement))
7477 return reportParseError("unexpected token, expected end of statement");
7478
7479 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7480 getTargetStreamer().emitDirectiveSetSoftFloat();
7481 return false;
7482}
7483
7484bool MipsAsmParser::parseSetHardFloatDirective() {
7485 MCAsmParser &Parser = getParser();
7486 Parser.Lex();
7487 if (getLexer().isNot(AsmToken::EndOfStatement))
7488 return reportParseError("unexpected token, expected end of statement");
7489
7490 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7491 getTargetStreamer().emitDirectiveSetHardFloat();
7492 return false;
7493}
7494
7495bool MipsAsmParser::parseSetAssignment() {
7497 MCAsmParser &Parser = getParser();
7498
7499 if (Parser.parseIdentifier(Name))
7500 return reportParseError("expected identifier after .set");
7501
7502 if (getLexer().isNot(AsmToken::Comma))
7503 return reportParseError("unexpected token, expected comma");
7504 Lex(); // Eat comma
7505
7506 if (getLexer().is(AsmToken::Dollar) &&
7507 getLexer().peekTok().is(AsmToken::Integer)) {
7508 // Parse assignment of a numeric register:
7509 // .set r1,$1
7510 Parser.Lex(); // Eat $.
7511 RegisterSets[Name] = Parser.getTok();
7512 Parser.Lex(); // Eat identifier.
7513 getContext().getOrCreateSymbol(Name);
7514 return false;
7515 }
7516
7517 MCSymbol *Sym;
7518 const MCExpr *Value;
7519 if (MCParserUtils::parseAssignmentExpression(Name, /* allow_redef */ true,
7520 Parser, Sym, Value))
7521 return true;
7522 Sym->setVariableValue(Value);
7523
7524 return false;
7525}
7526
7527bool MipsAsmParser::parseSetMips0Directive() {
7528 MCAsmParser &Parser = getParser();
7529 Parser.Lex();
7530 if (getLexer().isNot(AsmToken::EndOfStatement))
7531 return reportParseError("unexpected token, expected end of statement");
7532
7533 // Reset assembler options to their initial values.
7534 MCSubtargetInfo &STI = copySTI();
7535 setAvailableFeatures(
7536 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
7537 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
7538 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
7539
7540 getTargetStreamer().emitDirectiveSetMips0();
7541 return false;
7542}
7543
7544bool MipsAsmParser::parseSetArchDirective() {
7545 MCAsmParser &Parser = getParser();
7546 Parser.Lex();
7547 if (getLexer().isNot(AsmToken::Equal))
7548 return reportParseError("unexpected token, expected equals sign");
7549
7550 Parser.Lex();
7551 StringRef Arch = getParser().parseStringToEndOfStatement().trim();
7552 if (Arch.empty())
7553 return reportParseError("expected arch identifier");
7554
7555 StringRef ArchFeatureName =
7557 .Case("mips1", "mips1")
7558 .Case("mips2", "mips2")
7559 .Case("mips3", "mips3")
7560 .Case("mips4", "mips4")
7561 .Case("mips5", "mips5")
7562 .Case("mips32", "mips32")
7563 .Case("mips32r2", "mips32r2")
7564 .Case("mips32r3", "mips32r3")
7565 .Case("mips32r5", "mips32r5")
7566 .Case("mips32r6", "mips32r6")
7567 .Case("mips64", "mips64")
7568 .Case("mips64r2", "mips64r2")
7569 .Case("mips64r3", "mips64r3")
7570 .Case("mips64r5", "mips64r5")
7571 .Case("mips64r6", "mips64r6")
7572 .Case("octeon", "cnmips")
7573 .Case("octeon+", "cnmipsp")
7574 .Case("r4000", "mips3") // This is an implementation of Mips3.
7575 .Default("");
7576
7577 if (ArchFeatureName.empty())
7578 return reportParseError("unsupported architecture");
7579
7580 if (ArchFeatureName == "mips64r6" && inMicroMipsMode())
7581 return reportParseError("mips64r6 does not support microMIPS");
7582
7583 selectArch(ArchFeatureName);
7584 getTargetStreamer().emitDirectiveSetArch(Arch);
7585 return false;
7586}
7587
7588bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
7589 MCAsmParser &Parser = getParser();
7590 Parser.Lex();
7591 if (getLexer().isNot(AsmToken::EndOfStatement))
7592 return reportParseError("unexpected token, expected end of statement");
7593
7594 switch (Feature) {
7595 default:
7596 llvm_unreachable("Unimplemented feature");
7597 case Mips::FeatureMips3D:
7598 setFeatureBits(Mips::FeatureMips3D, "mips3d");
7599 getTargetStreamer().emitDirectiveSetMips3D();
7600 break;
7601 case Mips::FeatureDSP:
7602 setFeatureBits(Mips::FeatureDSP, "dsp");
7603 getTargetStreamer().emitDirectiveSetDsp();
7604 break;
7605 case Mips::FeatureDSPR2:
7606 setFeatureBits(Mips::FeatureDSPR2, "dspr2");
7607 getTargetStreamer().emitDirectiveSetDspr2();
7608 break;
7609 case Mips::FeatureMicroMips:
7610 setFeatureBits(Mips::FeatureMicroMips, "micromips");
7611 getTargetStreamer().emitDirectiveSetMicroMips();
7612 break;
7613 case Mips::FeatureMips1:
7614 selectArch("mips1");
7615 getTargetStreamer().emitDirectiveSetMips1();
7616 break;
7617 case Mips::FeatureMips2:
7618 selectArch("mips2");
7619 getTargetStreamer().emitDirectiveSetMips2();
7620 break;
7621 case Mips::FeatureMips3:
7622 selectArch("mips3");
7623 getTargetStreamer().emitDirectiveSetMips3();
7624 break;
7625 case Mips::FeatureMips4:
7626 selectArch("mips4");
7627 getTargetStreamer().emitDirectiveSetMips4();
7628 break;
7629 case Mips::FeatureMips5:
7630 selectArch("mips5");
7631 getTargetStreamer().emitDirectiveSetMips5();
7632 break;
7633 case Mips::FeatureMips32:
7634 selectArch("mips32");
7635 getTargetStreamer().emitDirectiveSetMips32();
7636 break;
7637 case Mips::FeatureMips32r2:
7638 selectArch("mips32r2");
7639 getTargetStreamer().emitDirectiveSetMips32R2();
7640 break;
7641 case Mips::FeatureMips32r3:
7642 selectArch("mips32r3");
7643 getTargetStreamer().emitDirectiveSetMips32R3();
7644 break;
7645 case Mips::FeatureMips32r5:
7646 selectArch("mips32r5");
7647 getTargetStreamer().emitDirectiveSetMips32R5();
7648 break;
7649 case Mips::FeatureMips32r6:
7650 selectArch("mips32r6");
7651 getTargetStreamer().emitDirectiveSetMips32R6();
7652 break;
7653 case Mips::FeatureMips64:
7654 selectArch("mips64");
7655 getTargetStreamer().emitDirectiveSetMips64();
7656 break;
7657 case Mips::FeatureMips64r2:
7658 selectArch("mips64r2");
7659 getTargetStreamer().emitDirectiveSetMips64R2();
7660 break;
7661 case Mips::FeatureMips64r3:
7662 selectArch("mips64r3");
7663 getTargetStreamer().emitDirectiveSetMips64R3();
7664 break;
7665 case Mips::FeatureMips64r5:
7666 selectArch("mips64r5");
7667 getTargetStreamer().emitDirectiveSetMips64R5();
7668 break;
7669 case Mips::FeatureMips64r6:
7670 selectArch("mips64r6");
7671 getTargetStreamer().emitDirectiveSetMips64R6();
7672 break;
7673 case Mips::FeatureCRC:
7674 setFeatureBits(Mips::FeatureCRC, "crc");
7675 getTargetStreamer().emitDirectiveSetCRC();
7676 break;
7677 case Mips::FeatureVirt:
7678 setFeatureBits(Mips::FeatureVirt, "virt");
7679 getTargetStreamer().emitDirectiveSetVirt();
7680 break;
7681 case Mips::FeatureGINV:
7682 setFeatureBits(Mips::FeatureGINV, "ginv");
7683 getTargetStreamer().emitDirectiveSetGINV();
7684 break;
7685 }
7686 return false;
7687}
7688
7689bool MipsAsmParser::eatComma(StringRef ErrorStr) {
7690 MCAsmParser &Parser = getParser();
7691 if (getLexer().isNot(AsmToken::Comma)) {
7692 SMLoc Loc = getLexer().getLoc();
7693 return Error(Loc, ErrorStr);
7694 }
7695
7696 Parser.Lex(); // Eat the comma.
7697 return true;
7698}
7699
7700// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
7701// In this class, it is only used for .cprestore.
7702// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
7703// MipsTargetELFStreamer and MipsAsmParser.
7704bool MipsAsmParser::isPicAndNotNxxAbi() {
7705 return inPicMode() && !(isABI_N32() || isABI_N64());
7706}
7707
7708bool MipsAsmParser::parseDirectiveCpAdd(SMLoc Loc) {
7710 ParseStatus Res = parseAnyRegister(Reg);
7711 if (Res.isNoMatch() || Res.isFailure()) {
7712 reportParseError("expected register");
7713 return false;
7714 }
7715
7716 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
7717 if (!RegOpnd.isGPRAsmReg()) {
7718 reportParseError(RegOpnd.getStartLoc(), "invalid register");
7719 return false;
7720 }
7721
7722 // If this is not the end of the statement, report an error.
7723 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7724 reportParseError("unexpected token, expected end of statement");
7725 return false;
7726 }
7727 getParser().Lex(); // Consume the EndOfStatement.
7728
7729 getTargetStreamer().emitDirectiveCpAdd(RegOpnd.getGPR32Reg());
7730 return false;
7731}
7732
7733bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
7734 if (AssemblerOptions.back()->isReorder())
7735 Warning(Loc, ".cpload should be inside a noreorder section");
7736
7737 if (inMips16Mode()) {
7738 reportParseError(".cpload is not supported in Mips16 mode");
7739 return false;
7740 }
7741
7743 ParseStatus Res = parseAnyRegister(Reg);
7744 if (Res.isNoMatch() || Res.isFailure()) {
7745 reportParseError("expected register containing function address");
7746 return false;
7747 }
7748
7749 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
7750 if (!RegOpnd.isGPRAsmReg()) {
7751 reportParseError(RegOpnd.getStartLoc(), "invalid register");
7752 return false;
7753 }
7754
7755 // If this is not the end of the statement, report an error.
7756 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7757 reportParseError("unexpected token, expected end of statement");
7758 return false;
7759 }
7760
7761 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
7762 return false;
7763}
7764
7765bool MipsAsmParser::parseDirectiveCpLocal(SMLoc Loc) {
7766 if (!isABI_N32() && !isABI_N64()) {
7767 reportParseError(".cplocal is allowed only in N32 or N64 mode");
7768 return false;
7769 }
7770
7772 ParseStatus Res = parseAnyRegister(Reg);
7773 if (Res.isNoMatch() || Res.isFailure()) {
7774 reportParseError("expected register containing global pointer");
7775 return false;
7776 }
7777
7778 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
7779 if (!RegOpnd.isGPRAsmReg()) {
7780 reportParseError(RegOpnd.getStartLoc(), "invalid register");
7781 return false;
7782 }
7783
7784 // If this is not the end of the statement, report an error.
7785 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7786 reportParseError("unexpected token, expected end of statement");
7787 return false;
7788 }
7789 getParser().Lex(); // Consume the EndOfStatement.
7790
7791 unsigned NewReg = RegOpnd.getGPR32Reg();
7792 if (IsPicEnabled)
7793 GPReg = NewReg;
7794
7795 getTargetStreamer().emitDirectiveCpLocal(NewReg);
7796 return false;
7797}
7798
7799bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
7800 MCAsmParser &Parser = getParser();
7801
7802 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
7803 // is used in non-PIC mode.
7804
7805 if (inMips16Mode()) {
7806 reportParseError(".cprestore is not supported in Mips16 mode");
7807 return false;
7808 }
7809
7810 // Get the stack offset value.
7811 const MCExpr *StackOffset;
7812 int64_t StackOffsetVal;
7813 if (Parser.parseExpression(StackOffset)) {
7814 reportParseError("expected stack offset value");
7815 return false;
7816 }
7817
7818 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
7819 reportParseError("stack offset is not an absolute expression");
7820 return false;
7821 }
7822
7823 if (StackOffsetVal < 0) {
7824 Warning(Loc, ".cprestore with negative stack offset has no effect");
7825 IsCpRestoreSet = false;
7826 } else {
7827 IsCpRestoreSet = true;
7828 CpRestoreOffset = StackOffsetVal;
7829 }
7830
7831 // If this is not the end of the statement, report an error.
7832 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7833 reportParseError("unexpected token, expected end of statement");
7834 return false;
7835 }
7836
7837 if (!getTargetStreamer().emitDirectiveCpRestore(
7838 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
7839 return true;
7840 Parser.Lex(); // Consume the EndOfStatement.
7841 return false;
7842}
7843
7844bool MipsAsmParser::parseDirectiveCPSetup() {
7845 MCAsmParser &Parser = getParser();
7846 unsigned FuncReg;
7847 unsigned Save;
7848 bool SaveIsReg = true;
7849
7851 ParseStatus Res = parseAnyRegister(TmpReg);
7852 if (Res.isNoMatch()) {
7853 reportParseError("expected register containing function address");
7854 return false;
7855 }
7856
7857 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7858 if (!FuncRegOpnd.isGPRAsmReg()) {
7859 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
7860 return false;
7861 }
7862
7863 FuncReg = FuncRegOpnd.getGPR32Reg();
7864 TmpReg.clear();
7865
7866 if (!eatComma("unexpected token, expected comma"))
7867 return true;
7868
7869 Res = parseAnyRegister(TmpReg);
7870 if (Res.isNoMatch()) {
7871 const MCExpr *OffsetExpr;
7872 int64_t OffsetVal;
7873 SMLoc ExprLoc = getLexer().getLoc();
7874
7875 if (Parser.parseExpression(OffsetExpr) ||
7876 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
7877 reportParseError(ExprLoc, "expected save register or stack offset");
7878 return false;
7879 }
7880
7881 Save = OffsetVal;
7882 SaveIsReg = false;
7883 } else {
7884 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7885 if (!SaveOpnd.isGPRAsmReg()) {
7886 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
7887 return false;
7888 }
7889 Save = SaveOpnd.getGPR32Reg();
7890 }
7891
7892 if (!eatComma("unexpected token, expected comma"))
7893 return true;
7894
7895 const MCExpr *Expr;
7896 if (Parser.parseExpression(Expr)) {
7897 reportParseError("expected expression");
7898 return false;
7899 }
7900
7901 if (Expr->getKind() != MCExpr::SymbolRef) {
7902 reportParseError("expected symbol");
7903 return false;
7904 }
7905 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
7906
7907 CpSaveLocation = Save;
7908 CpSaveLocationIsRegister = SaveIsReg;
7909
7910 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
7911 SaveIsReg);
7912 return false;
7913}
7914
7915bool MipsAsmParser::parseDirectiveCPReturn() {
7916 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
7917 CpSaveLocationIsRegister);
7918 return false;
7919}
7920
7921bool MipsAsmParser::parseDirectiveNaN() {
7922 MCAsmParser &Parser = getParser();
7923 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7924 const AsmToken &Tok = Parser.getTok();
7925
7926 if (Tok.getString() == "2008") {
7927 Parser.Lex();
7928 getTargetStreamer().emitDirectiveNaN2008();
7929 return false;
7930 } else if (Tok.getString() == "legacy") {
7931 Parser.Lex();
7932 getTargetStreamer().emitDirectiveNaNLegacy();
7933 return false;
7934 }
7935 }
7936 // If we don't recognize the option passed to the .nan
7937 // directive (e.g. no option or unknown option), emit an error.
7938 reportParseError("invalid option in .nan directive");
7939 return false;
7940}
7941
7942bool MipsAsmParser::parseDirectiveSet() {
7943 const AsmToken &Tok = getParser().getTok();
7944 StringRef IdVal = Tok.getString();
7945 SMLoc Loc = Tok.getLoc();
7946
7947 if (IdVal == "noat")
7948 return parseSetNoAtDirective();
7949 if (IdVal == "at")
7950 return parseSetAtDirective();
7951 if (IdVal == "arch")
7952 return parseSetArchDirective();
7953 if (IdVal == "bopt") {
7954 Warning(Loc, "'bopt' feature is unsupported");
7955 getParser().Lex();
7956 return false;
7957 }
7958 if (IdVal == "nobopt") {
7959 // We're already running in nobopt mode, so nothing to do.
7960 getParser().Lex();
7961 return false;
7962 }
7963 if (IdVal == "fp")
7964 return parseSetFpDirective();
7965 if (IdVal == "oddspreg")
7966 return parseSetOddSPRegDirective();
7967 if (IdVal == "nooddspreg")
7968 return parseSetNoOddSPRegDirective();
7969 if (IdVal == "pop")
7970 return parseSetPopDirective();
7971 if (IdVal == "push")
7972 return parseSetPushDirective();
7973 if (IdVal == "reorder")
7974 return parseSetReorderDirective();
7975 if (IdVal == "noreorder")
7976 return parseSetNoReorderDirective();
7977 if (IdVal == "macro")
7978 return parseSetMacroDirective();
7979 if (IdVal == "nomacro")
7980 return parseSetNoMacroDirective();
7981 if (IdVal == "mips16")
7982 return parseSetMips16Directive();
7983 if (IdVal == "nomips16")
7984 return parseSetNoMips16Directive();
7985 if (IdVal == "nomicromips") {
7986 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
7987 getTargetStreamer().emitDirectiveSetNoMicroMips();
7988 getParser().eatToEndOfStatement();
7989 return false;
7990 }
7991 if (IdVal == "micromips") {
7992 if (hasMips64r6()) {
7993 Error(Loc, ".set micromips directive is not supported with MIPS64R6");
7994 return false;
7995 }
7996 return parseSetFeature(Mips::FeatureMicroMips);
7997 }
7998 if (IdVal == "mips0")
7999 return parseSetMips0Directive();
8000 if (IdVal == "mips1")
8001 return parseSetFeature(Mips::FeatureMips1);
8002 if (IdVal == "mips2")
8003 return parseSetFeature(Mips::FeatureMips2);
8004 if (IdVal == "mips3")
8005 return parseSetFeature(Mips::FeatureMips3);
8006 if (IdVal == "mips4")
8007 return parseSetFeature(Mips::FeatureMips4);
8008 if (IdVal == "mips5")
8009 return parseSetFeature(Mips::FeatureMips5);
8010 if (IdVal == "mips32")
8011 return parseSetFeature(Mips::FeatureMips32);
8012 if (IdVal == "mips32r2")
8013 return parseSetFeature(Mips::FeatureMips32r2);
8014 if (IdVal == "mips32r3")
8015 return parseSetFeature(Mips::FeatureMips32r3);
8016 if (IdVal == "mips32r5")
8017 return parseSetFeature(Mips::FeatureMips32r5);
8018 if (IdVal == "mips32r6")
8019 return parseSetFeature(Mips::FeatureMips32r6);
8020 if (IdVal == "mips64")
8021 return parseSetFeature(Mips::FeatureMips64);
8022 if (IdVal == "mips64r2")
8023 return parseSetFeature(Mips::FeatureMips64r2);
8024 if (IdVal == "mips64r3")
8025 return parseSetFeature(Mips::FeatureMips64r3);
8026 if (IdVal == "mips64r5")
8027 return parseSetFeature(Mips::FeatureMips64r5);
8028 if (IdVal == "mips64r6") {
8029 if (inMicroMipsMode()) {
8030 Error(Loc, "MIPS64R6 is not supported with microMIPS");
8031 return false;
8032 }
8033 return parseSetFeature(Mips::FeatureMips64r6);
8034 }
8035 if (IdVal == "dsp")
8036 return parseSetFeature(Mips::FeatureDSP);
8037 if (IdVal == "dspr2")
8038 return parseSetFeature(Mips::FeatureDSPR2);
8039 if (IdVal == "nodsp")
8040 return parseSetNoDspDirective();
8041 if (IdVal == "mips3d")
8042 return parseSetFeature(Mips::FeatureMips3D);
8043 if (IdVal == "nomips3d")
8044 return parseSetNoMips3DDirective();
8045 if (IdVal == "msa")
8046 return parseSetMsaDirective();
8047 if (IdVal == "nomsa")
8048 return parseSetNoMsaDirective();
8049 if (IdVal == "mt")
8050 return parseSetMtDirective();
8051 if (IdVal == "nomt")
8052 return parseSetNoMtDirective();
8053 if (IdVal == "softfloat")
8054 return parseSetSoftFloatDirective();
8055 if (IdVal == "hardfloat")
8056 return parseSetHardFloatDirective();
8057 if (IdVal == "crc")
8058 return parseSetFeature(Mips::FeatureCRC);
8059 if (IdVal == "nocrc")
8060 return parseSetNoCRCDirective();
8061 if (IdVal == "virt")
8062 return parseSetFeature(Mips::FeatureVirt);
8063 if (IdVal == "novirt")
8064 return parseSetNoVirtDirective();
8065 if (IdVal == "ginv")
8066 return parseSetFeature(Mips::FeatureGINV);
8067 if (IdVal == "noginv")
8068 return parseSetNoGINVDirective();
8069
8070 // It is just an identifier, look for an assignment.
8071 return parseSetAssignment();
8072}
8073
8074/// parseDirectiveGpWord
8075/// ::= .gpword local_sym
8076bool MipsAsmParser::parseDirectiveGpWord() {
8077 MCAsmParser &Parser = getParser();
8078 const MCExpr *Value;
8079 // EmitGPRel32Value requires an expression, so we are using base class
8080 // method to evaluate the expression.
8081 if (getParser().parseExpression(Value))
8082 return true;
8083 getParser().getStreamer().emitGPRel32Value(Value);
8084
8085 if (getLexer().isNot(AsmToken::EndOfStatement))
8086 return Error(getLexer().getLoc(),
8087 "unexpected token, expected end of statement");
8088 Parser.Lex(); // Eat EndOfStatement token.
8089 return false;
8090}
8091
8092/// parseDirectiveGpDWord
8093/// ::= .gpdword local_sym
8094bool MipsAsmParser::parseDirectiveGpDWord() {
8095 MCAsmParser &Parser = getParser();
8096 const MCExpr *Value;
8097 // EmitGPRel64Value requires an expression, so we are using base class
8098 // method to evaluate the expression.
8099 if (getParser().parseExpression(Value))
8100 return true;
8101 getParser().getStreamer().emitGPRel64Value(Value);
8102
8103 if (getLexer().isNot(AsmToken::EndOfStatement))
8104 return Error(getLexer().getLoc(),
8105 "unexpected token, expected end of statement");
8106 Parser.Lex(); // Eat EndOfStatement token.
8107 return false;
8108}
8109
8110/// parseDirectiveDtpRelWord
8111/// ::= .dtprelword tls_sym
8112bool MipsAsmParser::parseDirectiveDtpRelWord() {
8113 MCAsmParser &Parser = getParser();
8114 const MCExpr *Value;
8115 // EmitDTPRel32Value requires an expression, so we are using base class
8116 // method to evaluate the expression.
8117 if (getParser().parseExpression(Value))
8118 return true;
8119 getParser().getStreamer().emitDTPRel32Value(Value);
8120
8121 if (getLexer().isNot(AsmToken::EndOfStatement))
8122 return Error(getLexer().getLoc(),
8123 "unexpected token, expected end of statement");
8124 Parser.Lex(); // Eat EndOfStatement token.
8125 return false;
8126}
8127
8128/// parseDirectiveDtpRelDWord
8129/// ::= .dtpreldword tls_sym
8130bool MipsAsmParser::parseDirectiveDtpRelDWord() {
8131 MCAsmParser &Parser = getParser();
8132 const MCExpr *Value;
8133 // EmitDTPRel64Value requires an expression, so we are using base class
8134 // method to evaluate the expression.
8135 if (getParser().parseExpression(Value))
8136 return true;
8137 getParser().getStreamer().emitDTPRel64Value(Value);
8138
8139 if (getLexer().isNot(AsmToken::EndOfStatement))
8140 return Error(getLexer().getLoc(),
8141 "unexpected token, expected end of statement");
8142 Parser.Lex(); // Eat EndOfStatement token.
8143 return false;
8144}
8145
8146/// parseDirectiveTpRelWord
8147/// ::= .tprelword tls_sym
8148bool MipsAsmParser::parseDirectiveTpRelWord() {
8149 MCAsmParser &Parser = getParser();
8150 const MCExpr *Value;
8151 // EmitTPRel32Value requires an expression, so we are using base class
8152 // method to evaluate the expression.
8153 if (getParser().parseExpression(Value))
8154 return true;
8155 getParser().getStreamer().emitTPRel32Value(Value);
8156
8157 if (getLexer().isNot(AsmToken::EndOfStatement))
8158 return Error(getLexer().getLoc(),
8159 "unexpected token, expected end of statement");
8160 Parser.Lex(); // Eat EndOfStatement token.
8161 return false;
8162}
8163
8164/// parseDirectiveTpRelDWord
8165/// ::= .tpreldword tls_sym
8166bool MipsAsmParser::parseDirectiveTpRelDWord() {
8167 MCAsmParser &Parser = getParser();
8168 const MCExpr *Value;
8169 // EmitTPRel64Value requires an expression, so we are using base class
8170 // method to evaluate the expression.
8171 if (getParser().parseExpression(Value))
8172 return true;
8173 getParser().getStreamer().emitTPRel64Value(Value);
8174
8175 if (getLexer().isNot(AsmToken::EndOfStatement))
8176 return Error(getLexer().getLoc(),
8177 "unexpected token, expected end of statement");
8178 Parser.Lex(); // Eat EndOfStatement token.
8179 return false;
8180}
8181
8182bool MipsAsmParser::parseDirectiveOption() {
8183 MCAsmParser &Parser = getParser();
8184 // Get the option token.
8185 AsmToken Tok = Parser.getTok();
8186 // At the moment only identifiers are supported.
8187 if (Tok.isNot(AsmToken::Identifier)) {
8188 return Error(Parser.getTok().getLoc(),
8189 "unexpected token, expected identifier");
8190 }
8191
8193
8194 if (Option == "pic0") {
8195 // MipsAsmParser needs to know if the current PIC mode changes.
8196 IsPicEnabled = false;
8197
8198 getTargetStreamer().emitDirectiveOptionPic0();
8199 Parser.Lex();
8200 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
8201 return Error(Parser.getTok().getLoc(),
8202 "unexpected token, expected end of statement");
8203 }
8204 return false;
8205 }
8206
8207 if (Option == "pic2") {
8208 // MipsAsmParser needs to know if the current PIC mode changes.
8209 IsPicEnabled = true;
8210
8211 getTargetStreamer().emitDirectiveOptionPic2();
8212 Parser.Lex();
8213 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
8214 return Error(Parser.getTok().getLoc(),
8215 "unexpected token, expected end of statement");
8216 }
8217 return false;
8218 }
8219
8220 // Unknown option.
8221 Warning(Parser.getTok().getLoc(),
8222 "unknown option, expected 'pic0' or 'pic2'");
8223 Parser.eatToEndOfStatement();
8224 return false;
8225}
8226
8227/// parseInsnDirective
8228/// ::= .insn
8229bool MipsAsmParser::parseInsnDirective() {
8230 // If this is not the end of the statement, report an error.
8231 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8232 reportParseError("unexpected token, expected end of statement");
8233 return false;
8234 }
8235
8236 // The actual label marking happens in
8237 // MipsELFStreamer::createPendingLabelRelocs().
8238 getTargetStreamer().emitDirectiveInsn();
8239
8240 getParser().Lex(); // Eat EndOfStatement token.
8241 return false;
8242}
8243
8244/// parseRSectionDirective
8245/// ::= .rdata
8246bool MipsAsmParser::parseRSectionDirective(StringRef Section) {
8247 // If this is not the end of the statement, report an error.
8248 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8249 reportParseError("unexpected token, expected end of statement");
8250 return false;
8251 }
8252
8253 MCSection *ELFSection = getContext().getELFSection(
8255 getParser().getStreamer().switchSection(ELFSection);
8256
8257 getParser().Lex(); // Eat EndOfStatement token.
8258 return false;
8259}
8260
8261/// parseSSectionDirective
8262/// ::= .sbss
8263/// ::= .sdata
8264bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
8265 // If this is not the end of the statement, report an error.
8266 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8267 reportParseError("unexpected token, expected end of statement");
8268 return false;
8269 }
8270
8271 MCSection *ELFSection = getContext().getELFSection(
8273 getParser().getStreamer().switchSection(ELFSection);
8274
8275 getParser().Lex(); // Eat EndOfStatement token.
8276 return false;
8277}
8278
8279/// parseDirectiveModule
8280/// ::= .module oddspreg
8281/// ::= .module nooddspreg
8282/// ::= .module fp=value
8283/// ::= .module softfloat
8284/// ::= .module hardfloat
8285/// ::= .module mt
8286/// ::= .module crc
8287/// ::= .module nocrc
8288/// ::= .module virt
8289/// ::= .module novirt
8290/// ::= .module ginv
8291/// ::= .module noginv
8292bool MipsAsmParser::parseDirectiveModule() {
8293 MCAsmParser &Parser = getParser();
8294 MCAsmLexer &Lexer = getLexer();
8295 SMLoc L = Lexer.getLoc();
8296
8297 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
8298 // TODO : get a better message.
8299 reportParseError(".module directive must appear before any code");
8300 return false;
8301 }
8302
8304 if (Parser.parseIdentifier(Option)) {
8305 reportParseError("expected .module option identifier");
8306 return false;
8307 }
8308
8309 if (Option == "oddspreg") {
8310 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
8311
8312 // Synchronize the abiflags information with the FeatureBits information we
8313 // changed above.
8314 getTargetStreamer().updateABIInfo(*this);
8315
8316 // If printing assembly, use the recently updated abiflags information.
8317 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
8318 // emitted at the end).
8319 getTargetStreamer().emitDirectiveModuleOddSPReg();
8320
8321 // If this is not the end of the statement, report an error.
8322 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8323 reportParseError("unexpected token, expected end of statement");
8324 return false;
8325 }
8326
8327 return false; // parseDirectiveModule has finished successfully.
8328 } else if (Option == "nooddspreg") {
8329 if (!isABI_O32()) {
8330 return Error(L, "'.module nooddspreg' requires the O32 ABI");
8331 }
8332
8333 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
8334
8335 // Synchronize the abiflags information with the FeatureBits information we
8336 // changed above.
8337 getTargetStreamer().updateABIInfo(*this);
8338
8339 // If printing assembly, use the recently updated abiflags information.
8340 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
8341 // emitted at the end).
8342 getTargetStreamer().emitDirectiveModuleOddSPReg();
8343
8344 // If this is not the end of the statement, report an error.
8345 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8346 reportParseError("unexpected token, expected end of statement");
8347 return false;
8348 }
8349
8350 return false; // parseDirectiveModule has finished successfully.
8351 } else if (Option == "fp") {
8352 return parseDirectiveModuleFP();
8353 } else if (Option == "softfloat") {
8354 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
8355
8356 // Synchronize the ABI Flags information with the FeatureBits information we
8357 // updated above.
8358 getTargetStreamer().updateABIInfo(*this);
8359
8360 // If printing assembly, use the recently updated ABI Flags information.
8361 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
8362 // emitted later).
8363 getTargetStreamer().emitDirectiveModuleSoftFloat();
8364
8365 // If this is not the end of the statement, report an error.
8366 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8367 reportParseError("unexpected token, expected end of statement");
8368 return false;
8369 }
8370
8371 return false; // parseDirectiveModule has finished successfully.
8372 } else if (Option == "hardfloat") {
8373 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
8374
8375 // Synchronize the ABI Flags information with the FeatureBits information we
8376 // updated above.
8377 getTargetStreamer().updateABIInfo(*this);
8378
8379 // If printing assembly, use the recently updated ABI Flags information.
8380 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
8381 // emitted later).
8382 getTargetStreamer().emitDirectiveModuleHardFloat();
8383
8384 // If this is not the end of the statement, report an error.
8385 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8386 reportParseError("unexpected token, expected end of statement");
8387 return false;
8388 }
8389
8390 return false; // parseDirectiveModule has finished successfully.
8391 } else if (Option == "mt") {
8392 setModuleFeatureBits(Mips::FeatureMT, "mt");
8393
8394 // Synchronize the ABI Flags information with the FeatureBits information we
8395 // updated above.
8396 getTargetStreamer().updateABIInfo(*this);
8397
8398 // If printing assembly, use the recently updated ABI Flags information.
8399 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
8400 // emitted later).
8401 getTargetStreamer().emitDirectiveModuleMT();
8402
8403 // If this is not the end of the statement, report an error.
8404 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8405 reportParseError("unexpected token, expected end of statement");
8406 return false;
8407 }
8408
8409 return false; // parseDirectiveModule has finished successfully.
8410 } else if (Option == "crc") {
8411 setModuleFeatureBits(Mips::FeatureCRC, "crc");
8412
8413 // Synchronize the ABI Flags information with the FeatureBits information we
8414 // updated above.
8415 getTargetStreamer().updateABIInfo(*this);
8416
8417 // If printing assembly, use the recently updated ABI Flags information.
8418 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
8419 // emitted later).
8420 getTargetStreamer().emitDirectiveModuleCRC();
8421
8422 // If this is not the end of the statement, report an error.
8423 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8424 reportParseError("unexpected token, expected end of statement");
8425 return false;
8426 }
8427
8428 return false; // parseDirectiveModule has finished successfully.
8429 } else if (Option == "nocrc") {
8430 clearModuleFeatureBits(Mips::FeatureCRC, "crc");
8431
8432 // Synchronize the ABI Flags information with the FeatureBits information we
8433 // updated above.
8434 getTargetStreamer().updateABIInfo(*this);
8435
8436 // If printing assembly, use the recently updated ABI Flags information.
8437 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
8438 // emitted later).
8439 getTargetStreamer().emitDirectiveModuleNoCRC();
8440
8441 // If this is not the end of the statement, report an error.
8442 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8443 reportParseError("unexpected token, expected end of statement");
8444 return false;
8445 }
8446
8447 return false; // parseDirectiveModule has finished successfully.
8448 } else if (Option == "virt") {
8449 setModuleFeatureBits(Mips::FeatureVirt, "virt");
8450
8451 // Synchronize the ABI Flags information with the FeatureBits information we
8452 // updated above.
8453 getTargetStreamer().updateABIInfo(*this);
8454
8455 // If printing assembly, use the recently updated ABI Flags information.
8456 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
8457 // emitted later).
8458 getTargetStreamer().emitDirectiveModuleVirt();
8459
8460 // If this is not the end of the statement, report an error.
8461 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8462 reportParseError("unexpected token, expected end of statement");
8463 return false;
8464 }
8465
8466 return false; // parseDirectiveModule has finished successfully.
8467 } else if (Option == "novirt") {
8468 clearModuleFeatureBits(Mips::FeatureVirt, "virt");
8469
8470 // Synchronize the ABI Flags information with the FeatureBits information we
8471 // updated above.
8472 getTargetStreamer().updateABIInfo(*this);
8473
8474 // If printing assembly, use the recently updated ABI Flags information.
8475 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
8476 // emitted later).
8477 getTargetStreamer().emitDirectiveModuleNoVirt();
8478
8479 // If this is not the end of the statement, report an error.
8480 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8481 reportParseError("unexpected token, expected end of statement");
8482 return false;
8483 }
8484
8485 return false; // parseDirectiveModule has finished successfully.
8486 } else if (Option == "ginv") {
8487 setModuleFeatureBits(Mips::FeatureGINV, "ginv");
8488
8489 // Synchronize the ABI Flags information with the FeatureBits information we
8490 // updated above.
8491 getTargetStreamer().updateABIInfo(*this);
8492
8493 // If printing assembly, use the recently updated ABI Flags information.
8494 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
8495 // emitted later).
8496 getTargetStreamer().emitDirectiveModuleGINV();
8497
8498 // If this is not the end of the statement, report an error.
8499 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8500 reportParseError("unexpected token, expected end of statement");
8501 return false;
8502 }
8503
8504 return false; // parseDirectiveModule has finished successfully.
8505 } else if (Option == "noginv") {
8506 clearModuleFeatureBits(Mips::FeatureGINV, "ginv");
8507
8508 // Synchronize the ABI Flags information with the FeatureBits information we
8509 // updated above.
8510 getTargetStreamer().updateABIInfo(*this);
8511
8512 // If printing assembly, use the recently updated ABI Flags information.
8513 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
8514 // emitted later).
8515 getTargetStreamer().emitDirectiveModuleNoGINV();
8516
8517 // If this is not the end of the statement, report an error.
8518 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8519 reportParseError("unexpected token, expected end of statement");
8520 return false;
8521 }
8522
8523 return false; // parseDirectiveModule has finished successfully.
8524 } else {
8525 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
8526 }
8527}
8528
8529/// parseDirectiveModuleFP
8530/// ::= =32
8531/// ::= =xx
8532/// ::= =64
8533bool MipsAsmParser::parseDirectiveModuleFP() {
8534 MCAsmParser &Parser = getParser();
8535 MCAsmLexer &Lexer = getLexer();
8536
8537 if (Lexer.isNot(AsmToken::Equal)) {
8538 reportParseError("unexpected token, expected equals sign '='");
8539 return false;
8540 }
8541 Parser.Lex(); // Eat '=' token.
8542
8544 if (!parseFpABIValue(FpABI, ".module"))
8545 return false;
8546
8547 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8548 reportParseError("unexpected token, expected end of statement");
8549 return false;
8550 }
8551
8552 // Synchronize the abiflags information with the FeatureBits information we
8553 // changed above.
8554 getTargetStreamer().updateABIInfo(*this);
8555
8556 // If printing assembly, use the recently updated abiflags information.
8557 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
8558 // emitted at the end).
8559 getTargetStreamer().emitDirectiveModuleFP();
8560
8561 Parser.Lex(); // Consume the EndOfStatement.
8562 return false;
8563}
8564
8565bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
8567 MCAsmParser &Parser = getParser();
8568 MCAsmLexer &Lexer = getLexer();
8569 bool ModuleLevelOptions = Directive == ".module";
8570
8571 if (Lexer.is(AsmToken::Identifier)) {
8572 StringRef Value = Parser.getTok().getString();
8573 Parser.Lex();
8574
8575 if (Value != "xx") {
8576 reportParseError("unsupported value, expected 'xx', '32' or '64'");
8577 return false;
8578 }
8579
8580 if (!isABI_O32()) {
8581 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
8582 return false;
8583 }
8584
8585 FpABI = MipsABIFlagsSection::FpABIKind::XX;
8586 if (ModuleLevelOptions) {
8587 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
8588 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
8589 } else {
8590 setFeatureBits(Mips::FeatureFPXX, "fpxx");
8591 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
8592 }
8593 return true;
8594 }
8595
8596 if (Lexer.is(AsmToken::Integer)) {
8597 unsigned Value = Parser.getTok().getIntVal();
8598 Parser.Lex();
8599
8600 if (Value != 32 && Value != 64) {
8601 reportParseError("unsupported value, expected 'xx', '32' or '64'");
8602 return false;
8603 }
8604
8605 if (Value == 32) {
8606 if (!isABI_O32()) {
8607 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
8608 return false;
8609 }
8610
8611 FpABI = MipsABIFlagsSection::FpABIKind::S32;
8612 if (ModuleLevelOptions) {
8613 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
8614 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
8615 } else {
8616 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
8617 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
8618 }
8619 } else {
8620 FpABI = MipsABIFlagsSection::FpABIKind::S64;
8621 if (ModuleLevelOptions) {
8622 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
8623 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
8624 } else {
8625 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
8626 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
8627 }
8628 }
8629
8630 return true;
8631 }
8632
8633 return false;
8634}
8635
8636bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
8637 // This returns false if this function recognizes the directive
8638 // regardless of whether it is successfully handles or reports an
8639 // error. Otherwise it returns true to give the generic parser a
8640 // chance at recognizing it.
8641
8642 MCAsmParser &Parser = getParser();
8643 StringRef IDVal = DirectiveID.getString();
8644
8645 if (IDVal == ".cpadd") {
8646 parseDirectiveCpAdd(DirectiveID.getLoc());
8647 return false;
8648 }
8649 if (IDVal == ".cpload") {
8650 parseDirectiveCpLoad(DirectiveID.getLoc());
8651 return false;
8652 }
8653 if (IDVal == ".cprestore") {
8654 parseDirectiveCpRestore(DirectiveID.getLoc());
8655 return false;
8656 }
8657 if (IDVal == ".cplocal") {
8658 parseDirectiveCpLocal(DirectiveID.getLoc());
8659 return false;
8660 }
8661 if (IDVal == ".ent") {
8663
8664 if (Parser.parseIdentifier(SymbolName)) {
8665 reportParseError("expected identifier after .ent");
8666 return false;
8667 }
8668
8669 // There's an undocumented extension that allows an integer to
8670 // follow the name of the procedure which AFAICS is ignored by GAS.
8671 // Example: .ent foo,2
8672 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8673 if (getLexer().isNot(AsmToken::Comma)) {
8674 // Even though we accept this undocumented extension for compatibility
8675 // reasons, the additional integer argument does not actually change
8676 // the behaviour of the '.ent' directive, so we would like to discourage
8677 // its use. We do this by not referring to the extended version in
8678 // error messages which are not directly related to its use.
8679 reportParseError("unexpected token, expected end of statement");
8680 return false;
8681 }
8682 Parser.Lex(); // Eat the comma.
8683 const MCExpr *DummyNumber;
8684 int64_t DummyNumberVal;
8685 // If the user was explicitly trying to use the extended version,
8686 // we still give helpful extension-related error messages.
8687 if (Parser.parseExpression(DummyNumber)) {
8688 reportParseError("expected number after comma");
8689 return false;
8690 }
8691 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
8692 reportParseError("expected an absolute expression after comma");
8693 return false;
8694 }
8695 }
8696
8697 // If this is not the end of the statement, report an error.
8698 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8699 reportParseError("unexpected token, expected end of statement");
8700 return false;
8701 }
8702
8703 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
8704
8705 getTargetStreamer().emitDirectiveEnt(*Sym);
8706 CurrentFn = Sym;
8707 IsCpRestoreSet = false;
8708 return false;
8709 }
8710
8711 if (IDVal == ".end") {
8713
8714 if (Parser.parseIdentifier(SymbolName)) {
8715 reportParseError("expected identifier after .end");
8716 return false;
8717 }
8718
8719 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8720 reportParseError("unexpected token, expected end of statement");
8721 return false;
8722 }
8723
8724 if (CurrentFn == nullptr) {
8725 reportParseError(".end used without .ent");
8726 return false;
8727 }
8728
8729 if ((SymbolName != CurrentFn->getName())) {
8730 reportParseError(".end symbol does not match .ent symbol");
8731 return false;
8732 }
8733
8734 getTargetStreamer().emitDirectiveEnd(SymbolName);
8735 CurrentFn = nullptr;
8736 IsCpRestoreSet = false;
8737 return false;
8738 }
8739
8740 if (IDVal == ".frame") {
8741 // .frame $stack_reg, frame_size_in_bytes, $return_reg
8743 ParseStatus Res = parseAnyRegister(TmpReg);
8744 if (Res.isNoMatch() || Res.isFailure()) {
8745 reportParseError("expected stack register");
8746 return false;
8747 }
8748
8749 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
8750 if (!StackRegOpnd.isGPRAsmReg()) {
8751 reportParseError(StackRegOpnd.getStartLoc(),
8752 "expected general purpose register");
8753 return false;
8754 }
8755 unsigned StackReg = StackRegOpnd.getGPR32Reg();
8756
8757 if (Parser.getTok().is(AsmToken::Comma))
8758 Parser.Lex();
8759 else {
8760 reportParseError("unexpected token, expected comma");
8761 return false;
8762 }
8763
8764 // Parse the frame size.
8765 const MCExpr *FrameSize;
8766 int64_t FrameSizeVal;
8767
8768 if (Parser.parseExpression(FrameSize)) {
8769 reportParseError("expected frame size value");
8770 return false;
8771 }
8772
8773 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
8774 reportParseError("frame size not an absolute expression");
8775 return false;
8776 }
8777
8778 if (Parser.getTok().is(AsmToken::Comma))
8779 Parser.Lex();
8780 else {
8781 reportParseError("unexpected token, expected comma");
8782 return false;
8783 }
8784
8785 // Parse the return register.
8786 TmpReg.clear();
8787 Res = parseAnyRegister(TmpReg);
8788 if (Res.isNoMatch() || Res.isFailure()) {
8789 reportParseError("expected return register");
8790 return false;
8791 }
8792
8793 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
8794 if (!ReturnRegOpnd.isGPRAsmReg()) {
8795 reportParseError(ReturnRegOpnd.getStartLoc(),
8796 "expected general purpose register");
8797 return false;
8798 }
8799
8800 // If this is not the end of the statement, report an error.
8801 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8802 reportParseError("unexpected token, expected end of statement");
8803 return false;
8804 }
8805
8806 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
8807 ReturnRegOpnd.getGPR32Reg());
8808 IsCpRestoreSet = false;
8809 return false;
8810 }
8811
8812 if (IDVal == ".set") {
8813 parseDirectiveSet();
8814 return false;
8815 }
8816
8817 if (IDVal == ".mask" || IDVal == ".fmask") {
8818 // .mask bitmask, frame_offset
8819 // bitmask: One bit for each register used.
8820 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
8821 // first register is expected to be saved.
8822 // Examples:
8823 // .mask 0x80000000, -4
8824 // .fmask 0x80000000, -4
8825 //
8826
8827 // Parse the bitmask
8828 const MCExpr *BitMask;
8829 int64_t BitMaskVal;
8830
8831 if (Parser.parseExpression(BitMask)) {
8832 reportParseError("expected bitmask value");
8833 return false;
8834 }
8835
8836 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
8837 reportParseError("bitmask not an absolute expression");
8838 return false;
8839 }
8840
8841 if (Parser.getTok().is(AsmToken::Comma))
8842 Parser.Lex();
8843 else {
8844 reportParseError("unexpected token, expected comma");
8845 return false;
8846 }
8847
8848 // Parse the frame_offset
8849 const MCExpr *FrameOffset;
8850 int64_t FrameOffsetVal;
8851
8852 if (Parser.parseExpression(FrameOffset)) {
8853 reportParseError("expected frame offset value");
8854 return false;
8855 }
8856
8857 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
8858 reportParseError("frame offset not an absolute expression");
8859 return false;
8860 }
8861
8862 // If this is not the end of the statement, report an error.
8863 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8864 reportParseError("unexpected token, expected end of statement");
8865 return false;
8866 }
8867
8868 if (IDVal == ".mask")
8869 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
8870 else
8871 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
8872 return false;
8873 }
8874
8875 if (IDVal == ".nan")
8876 return parseDirectiveNaN();
8877
8878 if (IDVal == ".gpword") {
8879 parseDirectiveGpWord();
8880 return false;
8881 }
8882
8883 if (IDVal == ".gpdword") {
8884 parseDirectiveGpDWord();
8885 return false;
8886 }
8887
8888 if (IDVal == ".dtprelword") {
8889 parseDirectiveDtpRelWord();
8890 return false;
8891 }
8892
8893 if (IDVal == ".dtpreldword") {
8894 parseDirectiveDtpRelDWord();
8895 return false;
8896 }
8897
8898 if (IDVal == ".tprelword") {
8899 parseDirectiveTpRelWord();
8900 return false;
8901 }
8902
8903 if (IDVal == ".tpreldword") {
8904 parseDirectiveTpRelDWord();
8905 return false;
8906 }
8907
8908 if (IDVal == ".option") {
8909 parseDirectiveOption();
8910 return false;
8911 }
8912
8913 if (IDVal == ".abicalls") {
8914 getTargetStreamer().emitDirectiveAbiCalls();
8915 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
8916 Error(Parser.getTok().getLoc(),
8917 "unexpected token, expected end of statement");
8918 }
8919 return false;
8920 }
8921
8922 if (IDVal == ".cpsetup") {
8923 parseDirectiveCPSetup();
8924 return false;
8925 }
8926 if (IDVal == ".cpreturn") {
8927 parseDirectiveCPReturn();
8928 return false;
8929 }
8930 if (IDVal == ".module") {
8931 parseDirectiveModule();
8932 return false;
8933 }
8934 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
8935 parseInternalDirectiveReallowModule();
8936 return false;
8937 }
8938 if (IDVal == ".insn") {
8939 parseInsnDirective();
8940 return false;
8941 }
8942 if (IDVal == ".rdata") {
8943 parseRSectionDirective(".rodata");
8944 return false;
8945 }
8946 if (IDVal == ".sbss") {
8947 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
8948 return false;
8949 }
8950 if (IDVal == ".sdata") {
8951 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
8952 return false;
8953 }
8954
8955 return true;
8956}
8957
8958bool MipsAsmParser::parseInternalDirectiveReallowModule() {
8959 // If this is not the end of the statement, report an error.
8960 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8961 reportParseError("unexpected token, expected end of statement");
8962 return false;
8963 }
8964
8965 getTargetStreamer().reallowModuleDirective();
8966
8967 getParser().Lex(); // Eat EndOfStatement token.
8968 return false;
8969}
8970
8976}
8977
8978#define GET_REGISTER_MATCHER
8979#define GET_MATCHER_IMPLEMENTATION
8980#define GET_MNEMONIC_SPELL_CHECKER
8981#include "MipsGenAsmMatcher.inc"
8982
8983bool MipsAsmParser::mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {
8984 // Find the appropriate table for this asm variant.
8985 const MatchEntry *Start, *End;
8986 switch (VariantID) {
8987 default: llvm_unreachable("invalid variant!");
8988 case 0: Start = std::begin(MatchTable0); End = std::end(MatchTable0); break;
8989 }
8990 // Search the table.
8991 auto MnemonicRange = std::equal_range(Start, End, Mnemonic, LessOpcode());
8992 return MnemonicRange.first != MnemonicRange.second;
8993}
#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:1315
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:1095
@ SHT_NOBITS
Definition: ELF.h:1102
@ SHF_ALLOC
Definition: ELF.h:1193
@ SHF_MIPS_GPREL
Definition: ELF.h:1276
@ SHF_WRITE
Definition: ELF.h:1190
@ STB_LOCAL
Definition: ELF.h:1346
@ 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:6424
@ 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,...