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