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