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

source code of llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp