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