1//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "MCTargetDesc/MipsABIFlagsSection.h"
10#include "MCTargetDesc/MipsABIInfo.h"
11#include "MCTargetDesc/MipsBaseInfo.h"
12#include "MCTargetDesc/MipsMCAsmInfo.h"
13#include "MCTargetDesc/MipsMCTargetDesc.h"
14#include "MCTargetDesc/MipsTargetStreamer.h"
15#include "TargetInfo/MipsTargetInfo.h"
16#include "llvm/ADT/APFloat.h"
17#include "llvm/ADT/SmallVector.h"
18#include "llvm/ADT/StringRef.h"
19#include "llvm/ADT/StringSwitch.h"
20#include "llvm/ADT/Twine.h"
21#include "llvm/BinaryFormat/ELF.h"
22#include "llvm/MC/MCContext.h"
23#include "llvm/MC/MCExpr.h"
24#include "llvm/MC/MCInst.h"
25#include "llvm/MC/MCInstrDesc.h"
26#include "llvm/MC/MCInstrInfo.h"
27#include "llvm/MC/MCObjectFileInfo.h"
28#include "llvm/MC/MCParser/AsmLexer.h"
29#include "llvm/MC/MCParser/MCAsmParser.h"
30#include "llvm/MC/MCParser/MCAsmParserExtension.h"
31#include "llvm/MC/MCParser/MCAsmParserUtils.h"
32#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
33#include "llvm/MC/MCParser/MCTargetAsmParser.h"
34#include "llvm/MC/MCSectionELF.h"
35#include "llvm/MC/MCStreamer.h"
36#include "llvm/MC/MCSubtargetInfo.h"
37#include "llvm/MC/MCSymbol.h"
38#include "llvm/MC/MCSymbolELF.h"
39#include "llvm/MC/MCValue.h"
40#include "llvm/MC/TargetRegistry.h"
41#include "llvm/Support/Alignment.h"
42#include "llvm/Support/Casting.h"
43#include "llvm/Support/CommandLine.h"
44#include "llvm/Support/Compiler.h"
45#include "llvm/Support/Debug.h"
46#include "llvm/Support/ErrorHandling.h"
47#include "llvm/Support/MathExtras.h"
48#include "llvm/Support/SMLoc.h"
49#include "llvm/Support/SourceMgr.h"
50#include "llvm/Support/raw_ostream.h"
51#include "llvm/TargetParser/SubtargetFeature.h"
52#include "llvm/TargetParser/Triple.h"
53#include <algorithm>
54#include <cassert>
55#include <cstdint>
56#include <memory>
57#include <string>
58#include <utility>
59
60using namespace llvm;
61
62#define DEBUG_TYPE "mips-asm-parser"
63
64namespace llvm {
65
66class MCInstrInfo;
67
68} // end namespace llvm
69
70extern cl::opt<bool> EmitJalrReloc;
71extern cl::opt<bool> NoZeroDivCheck;
72
73namespace {
74
75class MipsAssemblerOptions {
76public:
77 MipsAssemblerOptions(const FeatureBitset &Features_) : Features(Features_) {}
78
79 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
80 ATReg = Opts->getATRegIndex();
81 Reorder = Opts->isReorder();
82 Macro = Opts->isMacro();
83 Features = Opts->getFeatures();
84 }
85
86 unsigned getATRegIndex() const { return ATReg; }
87 bool setATRegIndex(unsigned Reg) {
88 if (Reg > 31)
89 return false;
90
91 ATReg = Reg;
92 return true;
93 }
94
95 bool isReorder() const { return Reorder; }
96 void setReorder() { Reorder = true; }
97 void setNoReorder() { Reorder = false; }
98
99 bool isMacro() const { return Macro; }
100 void setMacro() { Macro = true; }
101 void setNoMacro() { Macro = false; }
102
103 const FeatureBitset &getFeatures() const { return Features; }
104 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
105
106 // Set of features that are either architecture features or referenced
107 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
108 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
109 // The reason we need this mask is explained in the selectArch function.
110 // FIXME: Ideally we would like TableGen to generate this information.
111 static const FeatureBitset AllArchRelatedMask;
112
113private:
114 unsigned ATReg = 1;
115 bool Reorder = true;
116 bool Macro = true;
117 FeatureBitset Features;
118};
119
120} // end anonymous namespace
121
122const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
123 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
124 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
125 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
126 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
127 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
128 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
129 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
130 Mips::FeatureCnMipsP, Mips::FeatureFP64Bit, Mips::FeatureGP64Bit,
131 Mips::FeatureNaN2008
132};
133
134namespace {
135
136class MipsAsmParser : public MCTargetAsmParser {
137 MipsTargetStreamer &getTargetStreamer() {
138 assert(getParser().getStreamer().getTargetStreamer() &&
139 "do not have a target streamer");
140 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
141 return static_cast<MipsTargetStreamer &>(TS);
142 }
143
144 MipsABIInfo ABI;
145 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
146 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
147 // nullptr, which indicates that no function is currently
148 // selected. This usually happens after an '.end func'
149 // directive.
150 bool IsLittleEndian;
151 bool IsPicEnabled;
152 bool IsCpRestoreSet;
153 bool CurForbiddenSlotAttr;
154 int CpRestoreOffset;
155 MCRegister GPReg;
156 unsigned CpSaveLocation;
157 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
158 bool CpSaveLocationIsRegister;
159
160 // Map of register aliases created via the .set directive.
161 StringMap<AsmToken> RegisterSets;
162
163 // Print a warning along with its fix-it message at the given range.
164 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
165 SMRange Range, bool ShowColors = true);
166
167 void ConvertXWPOperands(MCInst &Inst, const OperandVector &Operands);
168
169#define GET_ASSEMBLER_HEADER
170#include "MipsGenAsmMatcher.inc"
171
172 unsigned
173 checkEarlyTargetMatchPredicate(MCInst &Inst,
174 const OperandVector &Operands) override;
175 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
176
177 bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
178 OperandVector &Operands, MCStreamer &Out,
179 uint64_t &ErrorInfo,
180 bool MatchingInlineAsm) override;
181
182 /// Parse a register as used in CFI directives
183 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
184 ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
185 SMLoc &EndLoc) override;
186
187 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
188
189 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
190
191 bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);
192
193 bool parseInstruction(ParseInstructionInfo &Info, StringRef Name,
194 SMLoc NameLoc, OperandVector &Operands) override;
195
196 bool ParseDirective(AsmToken DirectiveID) override;
197
198 ParseStatus parseMemOperand(OperandVector &Operands);
199 ParseStatus matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
200 StringRef Identifier, SMLoc S);
201 ParseStatus matchAnyRegisterWithoutDollar(OperandVector &Operands,
202 const AsmToken &Token, SMLoc S);
203 ParseStatus matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
204 ParseStatus parseAnyRegister(OperandVector &Operands);
205 ParseStatus parseImm(OperandVector &Operands);
206 ParseStatus parseJumpTarget(OperandVector &Operands);
207 ParseStatus parseInvNum(OperandVector &Operands);
208 ParseStatus parseRegisterList(OperandVector &Operands);
209 const MCExpr *parseRelocExpr();
210
211 bool searchSymbolAlias(OperandVector &Operands);
212
213 bool parseOperand(OperandVector &, StringRef Mnemonic);
214
215 enum MacroExpanderResultTy {
216 MER_NotAMacro,
217 MER_Success,
218 MER_Fail,
219 };
220
221 // Expands assembly pseudo instructions.
222 MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
223 MCStreamer &Out,
224 const MCSubtargetInfo *STI);
225
226 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
227 const MCSubtargetInfo *STI);
228
229 bool loadImmediate(int64_t ImmValue, MCRegister DstReg, MCRegister SrcReg,
230 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
231 MCStreamer &Out, const MCSubtargetInfo *STI);
232
233 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, MCRegister DstReg,
234 MCRegister SrcReg, bool Is32BitSym, SMLoc IDLoc,
235 MCStreamer &Out, const MCSubtargetInfo *STI);
236
237 bool emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc, MCSymbol *Sym);
238
239 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
240 MCStreamer &Out, const MCSubtargetInfo *STI);
241
242 bool expandLoadSingleImmToGPR(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
243 const MCSubtargetInfo *STI);
244 bool expandLoadSingleImmToFPR(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
245 const MCSubtargetInfo *STI);
246 bool expandLoadDoubleImmToGPR(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
247 const MCSubtargetInfo *STI);
248 bool expandLoadDoubleImmToFPR(MCInst &Inst, bool Is64FPU, SMLoc IDLoc,
249 MCStreamer &Out, const MCSubtargetInfo *STI);
250
251 bool expandLoadAddress(MCRegister DstReg, MCRegister BaseReg,
252 const MCOperand &Offset, bool Is32BitAddress,
253 SMLoc IDLoc, MCStreamer &Out,
254 const MCSubtargetInfo *STI);
255
256 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
257 const MCSubtargetInfo *STI);
258
259 void expandMem16Inst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
260 const MCSubtargetInfo *STI, bool IsLoad);
261 void expandMem9Inst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
262 const MCSubtargetInfo *STI, bool IsLoad);
263
264 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
265 const MCSubtargetInfo *STI);
266
267 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
268 const MCSubtargetInfo *STI);
269
270 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
271 const MCSubtargetInfo *STI);
272
273 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
274 const MCSubtargetInfo *STI);
275
276 bool expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
277 const MCSubtargetInfo *STI, const bool IsMips64,
278 const bool Signed);
279
280 bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
281 MCStreamer &Out, const MCSubtargetInfo *STI);
282
283 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out,
284 const MCSubtargetInfo *STI);
285
286 bool expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
287 const MCSubtargetInfo *STI);
288
289 bool expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
290 const MCSubtargetInfo *STI);
291
292 bool expandSge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
293 const MCSubtargetInfo *STI);
294
295 bool expandSgeImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
296 const MCSubtargetInfo *STI);
297
298 bool expandSgtImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
299 const MCSubtargetInfo *STI);
300
301 bool expandSle(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
302 const MCSubtargetInfo *STI);
303
304 bool expandSleImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
305 const MCSubtargetInfo *STI);
306
307 bool expandRotation(MCInst &Inst, SMLoc IDLoc,
308 MCStreamer &Out, const MCSubtargetInfo *STI);
309 bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
310 const MCSubtargetInfo *STI);
311 bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
312 const MCSubtargetInfo *STI);
313 bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
314 const MCSubtargetInfo *STI);
315
316 bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
317 const MCSubtargetInfo *STI);
318
319 bool expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
320 const MCSubtargetInfo *STI);
321
322 bool expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
323 const MCSubtargetInfo *STI);
324
325 bool expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
326 const MCSubtargetInfo *STI);
327
328 bool expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
329 const MCSubtargetInfo *STI);
330
331 bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
332 const MCSubtargetInfo *STI, bool IsLoad);
333
334 bool expandStoreDM1Macro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
335 const MCSubtargetInfo *STI);
336
337 bool expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
338 const MCSubtargetInfo *STI);
339
340 bool expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
341 const MCSubtargetInfo *STI);
342
343 bool expandSne(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
344 const MCSubtargetInfo *STI);
345
346 bool expandSneI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
347 const MCSubtargetInfo *STI);
348
349 bool expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
350 const MCSubtargetInfo *STI);
351
352 bool expandSaaAddr(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
353 const MCSubtargetInfo *STI);
354
355 bool reportParseError(const Twine &ErrorMsg);
356 bool reportParseError(SMLoc Loc, const Twine &ErrorMsg);
357
358 bool parseSetMips0Directive();
359 bool parseSetArchDirective();
360 bool parseSetFeature(uint64_t Feature);
361 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
362 bool parseDirectiveCpAdd(SMLoc Loc);
363 bool parseDirectiveCpLoad(SMLoc Loc);
364 bool parseDirectiveCpLocal(SMLoc Loc);
365 bool parseDirectiveCpRestore(SMLoc Loc);
366 bool parseDirectiveCPSetup();
367 bool parseDirectiveCPReturn();
368 bool parseDirectiveNaN();
369 bool parseDirectiveSet();
370 bool parseDirectiveOption();
371 bool parseInsnDirective();
372 bool parseRSectionDirective(StringRef Section);
373 bool parseSSectionDirective(StringRef Section, unsigned Type);
374
375 bool parseSetAtDirective();
376 bool parseSetNoAtDirective();
377 bool parseSetMacroDirective();
378 bool parseSetNoMacroDirective();
379 bool parseSetMsaDirective();
380 bool parseSetNoMsaDirective();
381 bool parseSetNoDspDirective();
382 bool parseSetNoMips3DDirective();
383 bool parseSetReorderDirective();
384 bool parseSetNoReorderDirective();
385 bool parseSetMips16Directive();
386 bool parseSetNoMips16Directive();
387 bool parseSetFpDirective();
388 bool parseSetOddSPRegDirective();
389 bool parseSetNoOddSPRegDirective();
390 bool parseSetPopDirective();
391 bool parseSetPushDirective();
392 bool parseSetSoftFloatDirective();
393 bool parseSetHardFloatDirective();
394 bool parseSetMtDirective();
395 bool parseSetNoMtDirective();
396 bool parseSetNoCRCDirective();
397 bool parseSetNoVirtDirective();
398 bool parseSetNoGINVDirective();
399
400 bool parseSetAssignment();
401
402 bool parseDirectiveGpWord();
403 bool parseDirectiveGpDWord();
404 bool parseDirectiveDtpRelWord();
405 bool parseDirectiveDtpRelDWord();
406 bool parseDirectiveTpRelWord();
407 bool parseDirectiveTpRelDWord();
408 bool parseDirectiveModule();
409 bool parseDirectiveModuleFP();
410 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
411 StringRef Directive);
412
413 bool parseInternalDirectiveReallowModule();
414
415 bool eatComma(StringRef ErrorStr);
416
417 int matchCPURegisterName(StringRef Symbol);
418
419 int matchHWRegsRegisterName(StringRef Symbol);
420
421 int matchFPURegisterName(StringRef Name);
422
423 int matchFCCRegisterName(StringRef Name);
424
425 int matchACRegisterName(StringRef Name);
426
427 int matchMSA128RegisterName(StringRef Name);
428
429 int matchMSA128CtrlRegisterName(StringRef Name);
430
431 MCRegister getReg(int RC, int RegNo);
432
433 /// Returns the internal register number for the current AT. Also checks if
434 /// the current AT is unavailable (set to $0) and gives an error if it is.
435 /// This should be used in pseudo-instruction expansions which need AT.
436 MCRegister getATReg(SMLoc Loc);
437
438 bool canUseATReg();
439
440 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
441 const MCSubtargetInfo *STI);
442
443 // Helper function that checks if the value of a vector index is within the
444 // boundaries of accepted values for each RegisterKind
445 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
446 bool validateMSAIndex(int Val, int RegKind);
447
448 // Selects a new architecture by updating the FeatureBits with the necessary
449 // info including implied dependencies.
450 // Internally, it clears all the feature bits related to *any* architecture
451 // and selects the new one using the ToggleFeature functionality of the
452 // MCSubtargetInfo object that handles implied dependencies. The reason we
453 // clear all the arch related bits manually is because ToggleFeature only
454 // clears the features that imply the feature being cleared and not the
455 // features implied by the feature being cleared. This is easier to see
456 // with an example:
457 // --------------------------------------------------
458 // | Feature | Implies |
459 // | -------------------------------------------------|
460 // | FeatureMips1 | None |
461 // | FeatureMips2 | FeatureMips1 |
462 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
463 // | FeatureMips4 | FeatureMips3 |
464 // | ... | |
465 // --------------------------------------------------
466 //
467 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
468 // FeatureMipsGP64 | FeatureMips1)
469 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
470 void selectArch(StringRef ArchFeature) {
471 MCSubtargetInfo &STI = copySTI();
472 FeatureBitset FeatureBits = STI.getFeatureBits();
473 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
474 STI.setFeatureBits(FeatureBits);
475 setAvailableFeatures(
476 ComputeAvailableFeatures(FB: STI.ToggleFeature(FS: ArchFeature)));
477 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
478 }
479
480 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
481 if (!(getSTI().hasFeature(Feature))) {
482 MCSubtargetInfo &STI = copySTI();
483 setAvailableFeatures(
484 ComputeAvailableFeatures(FB: STI.ToggleFeature(FS: FeatureString)));
485 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
486 }
487 }
488
489 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
490 if (getSTI().hasFeature(Feature)) {
491 MCSubtargetInfo &STI = copySTI();
492 setAvailableFeatures(
493 ComputeAvailableFeatures(FB: STI.ToggleFeature(FS: FeatureString)));
494 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
495 }
496 }
497
498 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
499 setFeatureBits(Feature, FeatureString);
500 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
501 }
502
503 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
504 clearFeatureBits(Feature, FeatureString);
505 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
506 }
507
508public:
509 enum MipsMatchResultTy {
510 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
511 Match_RequiresDifferentOperands,
512 Match_RequiresNoZeroRegister,
513 Match_RequiresSameSrcAndDst,
514 Match_NoFCCRegisterForCurrentISA,
515 Match_NonZeroOperandForSync,
516 Match_NonZeroOperandForMTCX,
517 Match_RequiresPosSizeRange0_32,
518 Match_RequiresPosSizeRange33_64,
519 Match_RequiresPosSizeUImm6,
520#define GET_OPERAND_DIAGNOSTIC_TYPES
521#include "MipsGenAsmMatcher.inc"
522#undef GET_OPERAND_DIAGNOSTIC_TYPES
523 };
524
525 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
526 const MCInstrInfo &MII, const MCTargetOptions &Options)
527 : MCTargetAsmParser(Options, sti, MII),
528 ABI(MipsABIInfo::computeTargetABI(TT: sti.getTargetTriple(),
529 ABIName: Options.getABIName())) {
530 MCAsmParserExtension::Initialize(Parser&: parser);
531
532 parser.addAliasForDirective(Directive: ".asciiz", Alias: ".asciz");
533 parser.addAliasForDirective(Directive: ".hword", Alias: ".2byte");
534 parser.addAliasForDirective(Directive: ".word", Alias: ".4byte");
535 parser.addAliasForDirective(Directive: ".dword", Alias: ".8byte");
536
537 // Initialize the set of available features.
538 setAvailableFeatures(ComputeAvailableFeatures(FB: getSTI().getFeatureBits()));
539
540 // Remember the initial assembler options. The user can not modify these.
541 AssemblerOptions.push_back(
542 Elt: std::make_unique<MipsAssemblerOptions>(args: getSTI().getFeatureBits()));
543
544 // Create an assembler options environment for the user to modify.
545 AssemblerOptions.push_back(
546 Elt: std::make_unique<MipsAssemblerOptions>(args: getSTI().getFeatureBits()));
547
548 getTargetStreamer().updateABIInfo(P: *this);
549
550 if (!isABI_O32() && !useOddSPReg() != 0)
551 report_fatal_error(reason: "-mno-odd-spreg requires the O32 ABI");
552
553 CurrentFn = nullptr;
554
555 CurForbiddenSlotAttr = false;
556 IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
557
558 IsCpRestoreSet = false;
559 CpRestoreOffset = -1;
560 GPReg = ABI.GetGlobalPtr();
561
562 const Triple &TheTriple = sti.getTargetTriple();
563 IsLittleEndian = TheTriple.isLittleEndian();
564
565 if (getSTI().getCPU() == "mips64r6" && inMicroMipsMode())
566 report_fatal_error(reason: "microMIPS64R6 is not supported", gen_crash_diag: false);
567
568 if (!isABI_O32() && inMicroMipsMode())
569 report_fatal_error(reason: "microMIPS64 is not supported", gen_crash_diag: false);
570 }
571
572 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
573 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
574
575 bool isGP64bit() const {
576 return getSTI().hasFeature(Feature: Mips::FeatureGP64Bit);
577 }
578
579 bool isFP64bit() const {
580 return getSTI().hasFeature(Feature: Mips::FeatureFP64Bit);
581 }
582
583 bool isJalrRelocAvailable(const MCExpr *JalExpr) {
584 if (!EmitJalrReloc)
585 return false;
586 MCValue Res;
587 if (!JalExpr->evaluateAsRelocatable(Res, Asm: nullptr))
588 return false;
589 if (Res.getSubSym())
590 return false;
591 if (Res.getConstant() != 0)
592 return ABI.IsN32() || ABI.IsN64();
593 return true;
594 }
595
596 const MipsABIInfo &getABI() const { return ABI; }
597 bool isABI_N32() const { return ABI.IsN32(); }
598 bool isABI_N64() const { return ABI.IsN64(); }
599 bool isABI_O32() const { return ABI.IsO32(); }
600 bool isABI_FPXX() const {
601 return getSTI().hasFeature(Feature: Mips::FeatureFPXX);
602 }
603
604 bool useOddSPReg() const {
605 return !(getSTI().hasFeature(Feature: Mips::FeatureNoOddSPReg));
606 }
607
608 bool inMicroMipsMode() const {
609 return getSTI().hasFeature(Feature: Mips::FeatureMicroMips);
610 }
611
612 bool hasMips1() const {
613 return getSTI().hasFeature(Feature: Mips::FeatureMips1);
614 }
615
616 bool hasMips2() const {
617 return getSTI().hasFeature(Feature: Mips::FeatureMips2);
618 }
619
620 bool hasMips3() const {
621 return getSTI().hasFeature(Feature: Mips::FeatureMips3);
622 }
623
624 bool hasMips4() const {
625 return getSTI().hasFeature(Feature: Mips::FeatureMips4);
626 }
627
628 bool hasMips5() const {
629 return getSTI().hasFeature(Feature: Mips::FeatureMips5);
630 }
631
632 bool hasMips32() const {
633 return getSTI().hasFeature(Feature: Mips::FeatureMips32);
634 }
635
636 bool hasMips64() const {
637 return getSTI().hasFeature(Feature: Mips::FeatureMips64);
638 }
639
640 bool hasMips32r2() const {
641 return getSTI().hasFeature(Feature: Mips::FeatureMips32r2);
642 }
643
644 bool hasMips64r2() const {
645 return getSTI().hasFeature(Feature: Mips::FeatureMips64r2);
646 }
647
648 bool hasMips32r3() const {
649 return (getSTI().hasFeature(Feature: Mips::FeatureMips32r3));
650 }
651
652 bool hasMips64r3() const {
653 return (getSTI().hasFeature(Feature: Mips::FeatureMips64r3));
654 }
655
656 bool hasMips32r5() const {
657 return (getSTI().hasFeature(Feature: Mips::FeatureMips32r5));
658 }
659
660 bool hasMips64r5() const {
661 return (getSTI().hasFeature(Feature: Mips::FeatureMips64r5));
662 }
663
664 bool hasMips32r6() const {
665 return getSTI().hasFeature(Feature: Mips::FeatureMips32r6);
666 }
667
668 bool hasMips64r6() const {
669 return getSTI().hasFeature(Feature: Mips::FeatureMips64r6);
670 }
671
672 bool hasDSP() const {
673 return getSTI().hasFeature(Feature: Mips::FeatureDSP);
674 }
675
676 bool hasDSPR2() const {
677 return getSTI().hasFeature(Feature: Mips::FeatureDSPR2);
678 }
679
680 bool hasDSPR3() const {
681 return getSTI().hasFeature(Feature: Mips::FeatureDSPR3);
682 }
683
684 bool hasMSA() const {
685 return getSTI().hasFeature(Feature: Mips::FeatureMSA);
686 }
687
688 bool hasCnMips() const {
689 return (getSTI().hasFeature(Feature: Mips::FeatureCnMips));
690 }
691
692 bool hasCnMipsP() const {
693 return (getSTI().hasFeature(Feature: Mips::FeatureCnMipsP));
694 }
695
696 bool isR5900() const { return (getSTI().hasFeature(Feature: Mips::FeatureR5900)); }
697
698 bool inPicMode() {
699 return IsPicEnabled;
700 }
701
702 bool inMips16Mode() const {
703 return getSTI().hasFeature(Feature: Mips::FeatureMips16);
704 }
705
706 bool useTraps() const {
707 return getSTI().hasFeature(Feature: Mips::FeatureUseTCCInDIV);
708 }
709
710 bool useSoftFloat() const {
711 return getSTI().hasFeature(Feature: Mips::FeatureSoftFloat);
712 }
713
714 bool isSingleFloat() const {
715 return getSTI().hasFeature(Feature: Mips::FeatureSingleFloat);
716 }
717
718 bool hasMT() const {
719 return getSTI().hasFeature(Feature: Mips::FeatureMT);
720 }
721
722 bool hasCRC() const {
723 return getSTI().hasFeature(Feature: Mips::FeatureCRC);
724 }
725
726 bool hasVirt() const {
727 return getSTI().hasFeature(Feature: Mips::FeatureVirt);
728 }
729
730 bool hasGINV() const {
731 return getSTI().hasFeature(Feature: Mips::FeatureGINV);
732 }
733
734 bool hasForbiddenSlot(const MCInstrDesc &MCID) const {
735 return !inMicroMipsMode() && (MCID.TSFlags & MipsII::HasForbiddenSlot);
736 }
737
738 bool SafeInForbiddenSlot(const MCInstrDesc &MCID) const {
739 return !(MCID.TSFlags & MipsII::IsCTI);
740 }
741
742 void onEndOfFile() override;
743
744 /// Warn if RegIndex is the same as the current AT.
745 void warnIfRegIndexIsAT(MCRegister RegIndex, SMLoc Loc);
746
747 void warnIfNoMacro(SMLoc Loc);
748
749 bool isLittle() const { return IsLittleEndian; }
750
751 bool areEqualRegs(const MCParsedAsmOperand &Op1,
752 const MCParsedAsmOperand &Op2) const override;
753};
754
755/// MipsOperand - Instances of this class represent a parsed Mips machine
756/// instruction.
757class MipsOperand : public MCParsedAsmOperand {
758public:
759 /// Broad categories of register classes
760 /// The exact class is finalized by the render method.
761 enum RegKind {
762 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
763 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
764 /// isFP64bit())
765 RegKind_FCC = 4, /// FCC
766 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
767 RegKind_MSACtrl = 16, /// MSA control registers
768 RegKind_COP2 = 32, /// COP2
769 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
770 /// context).
771 RegKind_CCR = 128, /// CCR
772 RegKind_HWRegs = 256, /// HWRegs
773 RegKind_COP3 = 512, /// COP3
774 RegKind_COP0 = 1024, /// COP0
775 /// Potentially any (e.g. $1)
776 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
777 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
778 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
779 };
780
781private:
782 enum KindTy {
783 k_Immediate, /// An immediate (possibly involving symbol references)
784 k_Memory, /// Base + Offset Memory Address
785 k_RegisterIndex, /// A register index in one or more RegKind.
786 k_Token, /// A simple token
787 k_RegList, /// A physical register list
788 } Kind;
789
790public:
791 MipsOperand(KindTy K, MipsAsmParser &Parser) : Kind(K), AsmParser(Parser) {}
792
793 ~MipsOperand() override {
794 switch (Kind) {
795 case k_Memory:
796 delete Mem.Base;
797 break;
798 case k_RegList:
799 delete RegList.List;
800 break;
801 case k_Immediate:
802 case k_RegisterIndex:
803 case k_Token:
804 break;
805 }
806 }
807
808private:
809 /// For diagnostics, and checking the assembler temporary
810 MipsAsmParser &AsmParser;
811
812 struct Token {
813 const char *Data;
814 unsigned Length;
815 };
816
817 struct RegIdxOp {
818 unsigned Index; /// Index into the register class
819 RegKind Kind; /// Bitfield of the kinds it could possibly be
820 struct Token Tok; /// The input token this operand originated from.
821 const MCRegisterInfo *RegInfo;
822 };
823
824 struct ImmOp {
825 const MCExpr *Val;
826 };
827
828 struct MemOp {
829 MipsOperand *Base;
830 const MCExpr *Off;
831 };
832
833 struct RegListOp {
834 SmallVector<MCRegister, 10> *List;
835 };
836
837 union {
838 struct Token Tok;
839 struct RegIdxOp RegIdx;
840 struct ImmOp Imm;
841 struct MemOp Mem;
842 struct RegListOp RegList;
843 };
844
845 SMLoc StartLoc, EndLoc;
846
847 /// Internal constructor for register kinds
848 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str,
849 RegKind RegKind,
850 const MCRegisterInfo *RegInfo,
851 SMLoc S, SMLoc E,
852 MipsAsmParser &Parser) {
853 auto Op = std::make_unique<MipsOperand>(args: k_RegisterIndex, args&: Parser);
854 Op->RegIdx.Index = Index;
855 Op->RegIdx.RegInfo = RegInfo;
856 Op->RegIdx.Kind = RegKind;
857 Op->RegIdx.Tok.Data = Str.data();
858 Op->RegIdx.Tok.Length = Str.size();
859 Op->StartLoc = S;
860 Op->EndLoc = E;
861 return Op;
862 }
863
864public:
865 /// Coerce the register to GPR32 and return the real register for the current
866 /// target.
867 MCRegister getGPR32Reg() const {
868 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
869 AsmParser.warnIfRegIndexIsAT(RegIndex: RegIdx.Index, Loc: StartLoc);
870 unsigned ClassID = Mips::GPR32RegClassID;
871 return RegIdx.RegInfo->getRegClass(i: ClassID).getRegister(i: RegIdx.Index);
872 }
873
874 /// Coerce the register to GPR32 and return the real register for the current
875 /// target.
876 MCRegister getGPRMM16Reg() const {
877 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
878 unsigned ClassID = Mips::GPR32RegClassID;
879 return RegIdx.RegInfo->getRegClass(i: ClassID).getRegister(i: RegIdx.Index);
880 }
881
882 /// Coerce the register to GPR64 and return the real register for the current
883 /// target.
884 MCRegister getGPR64Reg() const {
885 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
886 unsigned ClassID = Mips::GPR64RegClassID;
887 return RegIdx.RegInfo->getRegClass(i: ClassID).getRegister(i: RegIdx.Index);
888 }
889
890private:
891 /// Coerce the register to AFGR64 and return the real register for the current
892 /// target.
893 MCRegister getAFGR64Reg() const {
894 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
895 if (RegIdx.Index % 2 != 0)
896 AsmParser.Warning(L: StartLoc, Msg: "Float register should be even.");
897 return RegIdx.RegInfo->getRegClass(i: Mips::AFGR64RegClassID)
898 .getRegister(i: RegIdx.Index / 2);
899 }
900
901 /// Coerce the register to FGR64 and return the real register for the current
902 /// target.
903 MCRegister getFGR64Reg() const {
904 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
905 return RegIdx.RegInfo->getRegClass(i: Mips::FGR64RegClassID)
906 .getRegister(i: RegIdx.Index);
907 }
908
909 /// Coerce the register to FGR32 and return the real register for the current
910 /// target.
911 MCRegister getFGR32Reg() const {
912 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
913 return RegIdx.RegInfo->getRegClass(i: Mips::FGR32RegClassID)
914 .getRegister(i: RegIdx.Index);
915 }
916
917 /// Coerce the register to FCC and return the real register for the current
918 /// target.
919 MCRegister getFCCReg() const {
920 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
921 return RegIdx.RegInfo->getRegClass(i: Mips::FCCRegClassID)
922 .getRegister(i: RegIdx.Index);
923 }
924
925 /// Coerce the register to MSA128 and return the real register for the current
926 /// target.
927 MCRegister getMSA128Reg() const {
928 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
929 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
930 // identical
931 unsigned ClassID = Mips::MSA128BRegClassID;
932 return RegIdx.RegInfo->getRegClass(i: ClassID).getRegister(i: RegIdx.Index);
933 }
934
935 /// Coerce the register to MSACtrl and return the real register for the
936 /// current target.
937 MCRegister getMSACtrlReg() const {
938 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
939 unsigned ClassID = Mips::MSACtrlRegClassID;
940 return RegIdx.RegInfo->getRegClass(i: ClassID).getRegister(i: RegIdx.Index);
941 }
942
943 /// Coerce the register to COP0 and return the real register for the
944 /// current target.
945 MCRegister getCOP0Reg() const {
946 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
947 unsigned ClassID = Mips::COP0RegClassID;
948 return RegIdx.RegInfo->getRegClass(i: ClassID).getRegister(i: RegIdx.Index);
949 }
950
951 /// Coerce the register to COP2 and return the real register for the
952 /// current target.
953 MCRegister getCOP2Reg() const {
954 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
955 unsigned ClassID = Mips::COP2RegClassID;
956 return RegIdx.RegInfo->getRegClass(i: ClassID).getRegister(i: RegIdx.Index);
957 }
958
959 /// Coerce the register to COP3 and return the real register for the
960 /// current target.
961 MCRegister getCOP3Reg() const {
962 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
963 unsigned ClassID = Mips::COP3RegClassID;
964 return RegIdx.RegInfo->getRegClass(i: ClassID).getRegister(i: RegIdx.Index);
965 }
966
967 /// Coerce the register to ACC64DSP and return the real register for the
968 /// current target.
969 MCRegister getACC64DSPReg() const {
970 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
971 unsigned ClassID = Mips::ACC64DSPRegClassID;
972 return RegIdx.RegInfo->getRegClass(i: ClassID).getRegister(i: RegIdx.Index);
973 }
974
975 /// Coerce the register to HI32DSP and return the real register for the
976 /// current target.
977 MCRegister getHI32DSPReg() const {
978 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
979 unsigned ClassID = Mips::HI32DSPRegClassID;
980 return RegIdx.RegInfo->getRegClass(i: ClassID).getRegister(i: RegIdx.Index);
981 }
982
983 /// Coerce the register to LO32DSP and return the real register for the
984 /// current target.
985 MCRegister getLO32DSPReg() const {
986 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
987 unsigned ClassID = Mips::LO32DSPRegClassID;
988 return RegIdx.RegInfo->getRegClass(i: ClassID).getRegister(i: RegIdx.Index);
989 }
990
991 /// Coerce the register to CCR and return the real register for the
992 /// current target.
993 MCRegister getCCRReg() const {
994 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
995 unsigned ClassID = Mips::CCRRegClassID;
996 return RegIdx.RegInfo->getRegClass(i: ClassID).getRegister(i: RegIdx.Index);
997 }
998
999 /// Coerce the register to HWRegs and return the real register for the
1000 /// current target.
1001 MCRegister getHWRegsReg() const {
1002 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
1003 unsigned ClassID = Mips::HWRegsRegClassID;
1004 return RegIdx.RegInfo->getRegClass(i: ClassID).getRegister(i: RegIdx.Index);
1005 }
1006
1007public:
1008 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1009 // Add as immediate when possible. Null MCExpr = 0.
1010 if (!Expr)
1011 Inst.addOperand(Op: MCOperand::createImm(Val: 0));
1012 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val: Expr))
1013 Inst.addOperand(Op: MCOperand::createImm(Val: CE->getValue()));
1014 else
1015 Inst.addOperand(Op: MCOperand::createExpr(Val: Expr));
1016 }
1017
1018 void addRegOperands(MCInst &Inst, unsigned N) const {
1019 llvm_unreachable("Use a custom parser instead");
1020 }
1021
1022 /// Render the operand to an MCInst as a GPR32
1023 /// Asserts if the wrong number of operands are requested, or the operand
1024 /// is not a k_RegisterIndex compatible with RegKind_GPR
1025 void addGPR32ZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
1026 assert(N == 1 && "Invalid number of operands!");
1027 Inst.addOperand(Op: MCOperand::createReg(Reg: getGPR32Reg()));
1028 }
1029
1030 void addGPR32NonZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
1031 assert(N == 1 && "Invalid number of operands!");
1032 Inst.addOperand(Op: MCOperand::createReg(Reg: getGPR32Reg()));
1033 }
1034
1035 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1036 assert(N == 1 && "Invalid number of operands!");
1037 Inst.addOperand(Op: MCOperand::createReg(Reg: getGPR32Reg()));
1038 }
1039
1040 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
1041 assert(N == 1 && "Invalid number of operands!");
1042 Inst.addOperand(Op: MCOperand::createReg(Reg: getGPRMM16Reg()));
1043 }
1044
1045 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
1046 assert(N == 1 && "Invalid number of operands!");
1047 Inst.addOperand(Op: MCOperand::createReg(Reg: getGPRMM16Reg()));
1048 }
1049
1050 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
1051 assert(N == 1 && "Invalid number of operands!");
1052 Inst.addOperand(Op: MCOperand::createReg(Reg: getGPRMM16Reg()));
1053 }
1054
1055 void addGPRMM16AsmRegMovePPairFirstOperands(MCInst &Inst, unsigned N) const {
1056 assert(N == 1 && "Invalid number of operands!");
1057 Inst.addOperand(Op: MCOperand::createReg(Reg: getGPRMM16Reg()));
1058 }
1059
1060 void addGPRMM16AsmRegMovePPairSecondOperands(MCInst &Inst,
1061 unsigned N) const {
1062 assert(N == 1 && "Invalid number of operands!");
1063 Inst.addOperand(Op: MCOperand::createReg(Reg: getGPRMM16Reg()));
1064 }
1065
1066 /// Render the operand to an MCInst as a GPR64
1067 /// Asserts if the wrong number of operands are requested, or the operand
1068 /// is not a k_RegisterIndex compatible with RegKind_GPR
1069 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1070 assert(N == 1 && "Invalid number of operands!");
1071 Inst.addOperand(Op: MCOperand::createReg(Reg: getGPR64Reg()));
1072 }
1073
1074 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1075 assert(N == 1 && "Invalid number of operands!");
1076 Inst.addOperand(Op: MCOperand::createReg(Reg: getAFGR64Reg()));
1077 }
1078
1079 void addStrictlyAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1080 assert(N == 1 && "Invalid number of operands!");
1081 Inst.addOperand(Op: MCOperand::createReg(Reg: getAFGR64Reg()));
1082 }
1083
1084 void addStrictlyFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1085 assert(N == 1 && "Invalid number of operands!");
1086 Inst.addOperand(Op: MCOperand::createReg(Reg: getFGR64Reg()));
1087 }
1088
1089 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1090 assert(N == 1 && "Invalid number of operands!");
1091 Inst.addOperand(Op: MCOperand::createReg(Reg: getFGR64Reg()));
1092 }
1093
1094 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1095 assert(N == 1 && "Invalid number of operands!");
1096 Inst.addOperand(Op: MCOperand::createReg(Reg: getFGR32Reg()));
1097 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
1098 // FIXME: This should propagate failure up to parseStatement.
1099 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
1100 AsmParser.getParser().printError(
1101 L: StartLoc, Msg: "-mno-odd-spreg prohibits the use of odd FPU "
1102 "registers");
1103 }
1104
1105 void addStrictlyFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1106 assert(N == 1 && "Invalid number of operands!");
1107 Inst.addOperand(Op: MCOperand::createReg(Reg: getFGR32Reg()));
1108 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
1109 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
1110 AsmParser.Error(L: StartLoc, Msg: "-mno-odd-spreg prohibits the use of odd FPU "
1111 "registers");
1112 }
1113
1114 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
1115 assert(N == 1 && "Invalid number of operands!");
1116 Inst.addOperand(Op: MCOperand::createReg(Reg: getFCCReg()));
1117 }
1118
1119 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
1120 assert(N == 1 && "Invalid number of operands!");
1121 Inst.addOperand(Op: MCOperand::createReg(Reg: getMSA128Reg()));
1122 }
1123
1124 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
1125 assert(N == 1 && "Invalid number of operands!");
1126 Inst.addOperand(Op: MCOperand::createReg(Reg: getMSACtrlReg()));
1127 }
1128
1129 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
1130 assert(N == 1 && "Invalid number of operands!");
1131 Inst.addOperand(Op: MCOperand::createReg(Reg: getCOP0Reg()));
1132 }
1133
1134 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
1135 assert(N == 1 && "Invalid number of operands!");
1136 Inst.addOperand(Op: MCOperand::createReg(Reg: getCOP2Reg()));
1137 }
1138
1139 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
1140 assert(N == 1 && "Invalid number of operands!");
1141 Inst.addOperand(Op: MCOperand::createReg(Reg: getCOP3Reg()));
1142 }
1143
1144 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1145 assert(N == 1 && "Invalid number of operands!");
1146 Inst.addOperand(Op: MCOperand::createReg(Reg: getACC64DSPReg()));
1147 }
1148
1149 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1150 assert(N == 1 && "Invalid number of operands!");
1151 Inst.addOperand(Op: MCOperand::createReg(Reg: getHI32DSPReg()));
1152 }
1153
1154 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1155 assert(N == 1 && "Invalid number of operands!");
1156 Inst.addOperand(Op: MCOperand::createReg(Reg: getLO32DSPReg()));
1157 }
1158
1159 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
1160 assert(N == 1 && "Invalid number of operands!");
1161 Inst.addOperand(Op: MCOperand::createReg(Reg: getCCRReg()));
1162 }
1163
1164 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
1165 assert(N == 1 && "Invalid number of operands!");
1166 Inst.addOperand(Op: MCOperand::createReg(Reg: getHWRegsReg()));
1167 }
1168
1169 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
1170 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
1171 assert(N == 1 && "Invalid number of operands!");
1172 uint64_t Imm = getConstantImm() - Offset;
1173 Imm &= (1ULL << Bits) - 1;
1174 Imm += Offset;
1175 Imm += AdjustOffset;
1176 Inst.addOperand(Op: MCOperand::createImm(Val: Imm));
1177 }
1178
1179 template <unsigned Bits>
1180 void addSImmOperands(MCInst &Inst, unsigned N) const {
1181 if (isImm() && !isConstantImm()) {
1182 addExpr(Inst, Expr: getImm());
1183 return;
1184 }
1185 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
1186 }
1187
1188 template <unsigned Bits>
1189 void addUImmOperands(MCInst &Inst, unsigned N) const {
1190 if (isImm() && !isConstantImm()) {
1191 addExpr(Inst, Expr: getImm());
1192 return;
1193 }
1194 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
1195 }
1196
1197 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
1198 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
1199 assert(N == 1 && "Invalid number of operands!");
1200 int64_t Imm = getConstantImm() - Offset;
1201 Imm = SignExtend64<Bits>(Imm);
1202 Imm += Offset;
1203 Imm += AdjustOffset;
1204 Inst.addOperand(Op: MCOperand::createImm(Val: Imm));
1205 }
1206
1207 void addImmOperands(MCInst &Inst, unsigned N) const {
1208 assert(N == 1 && "Invalid number of operands!");
1209 const MCExpr *Expr = getImm();
1210 addExpr(Inst, Expr);
1211 }
1212
1213 void addMemOperands(MCInst &Inst, unsigned N) const {
1214 assert(N == 2 && "Invalid number of operands!");
1215
1216 Inst.addOperand(Op: MCOperand::createReg(Reg: AsmParser.getABI().ArePtrs64bit()
1217 ? getMemBase()->getGPR64Reg()
1218 : getMemBase()->getGPR32Reg()));
1219
1220 const MCExpr *Expr = getMemOff();
1221 addExpr(Inst, Expr);
1222 }
1223
1224 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
1225 assert(N == 2 && "Invalid number of operands!");
1226
1227 Inst.addOperand(Op: MCOperand::createReg(Reg: getMemBase()->getGPRMM16Reg()));
1228
1229 const MCExpr *Expr = getMemOff();
1230 addExpr(Inst, Expr);
1231 }
1232
1233 void addRegListOperands(MCInst &Inst, unsigned N) const {
1234 assert(N == 1 && "Invalid number of operands!");
1235
1236 for (auto RegNo : getRegList())
1237 Inst.addOperand(Op: MCOperand::createReg(Reg: RegNo));
1238 }
1239
1240 bool isReg() const override {
1241 // As a special case until we sort out the definition of div/divu, accept
1242 // $0/$zero here so that MCK_ZERO works correctly.
1243 return isGPRAsmReg() && RegIdx.Index == 0;
1244 }
1245
1246 bool isRegIdx() const { return Kind == k_RegisterIndex; }
1247 bool isImm() const override { return Kind == k_Immediate; }
1248
1249 bool isConstantImm() const {
1250 int64_t Res;
1251 return isImm() && getImm()->evaluateAsAbsolute(Res);
1252 }
1253
1254 bool isConstantImmz() const {
1255 return isConstantImm() && getConstantImm() == 0;
1256 }
1257
1258 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1259 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1260 }
1261
1262 template <unsigned Bits> bool isSImm() const {
1263 if (!isImm())
1264 return false;
1265 int64_t Res;
1266 if (getImm()->evaluateAsAbsolute(Res))
1267 return isInt<Bits>(Res);
1268 // Allow conservatively if not a parse-time constant.
1269 return true;
1270 }
1271
1272 template <unsigned Bits> bool isUImm() const {
1273 if (!isImm())
1274 return false;
1275 int64_t Res;
1276 if (getImm()->evaluateAsAbsolute(Res))
1277 return isUInt<Bits>(Res);
1278 // Allow conservatively if not a parse-time constant.
1279 return true;
1280 }
1281
1282 template <unsigned Bits> bool isAnyImm() const {
1283 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1284 isUInt<Bits>(getConstantImm()))
1285 : isImm();
1286 }
1287
1288 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1289 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
1290 }
1291
1292 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1293 return isConstantImm() && getConstantImm() >= Bottom &&
1294 getConstantImm() <= Top;
1295 }
1296
1297 bool isToken() const override {
1298 // Note: It's not possible to pretend that other operand kinds are tokens.
1299 // The matcher emitter checks tokens first.
1300 return Kind == k_Token;
1301 }
1302
1303 bool isMem() const override { return Kind == k_Memory; }
1304
1305 bool isConstantMemOff() const {
1306 return isMem() && isa<MCConstantExpr>(Val: getMemOff());
1307 }
1308
1309 // Allow relocation operators.
1310 template <unsigned Bits, unsigned ShiftAmount = 0>
1311 bool isMemWithSimmOffset() const {
1312 if (!isMem())
1313 return false;
1314 if (!getMemBase()->isGPRAsmReg())
1315 return false;
1316 if (isa<MCSpecifierExpr>(Val: getMemOff()) ||
1317 (isConstantMemOff() &&
1318 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
1319 return true;
1320 MCValue Res;
1321 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, Asm: nullptr);
1322 return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
1323 }
1324
1325 bool isMemWithPtrSizeOffset() const {
1326 if (!isMem())
1327 return false;
1328 if (!getMemBase()->isGPRAsmReg())
1329 return false;
1330 const unsigned PtrBits = AsmParser.getABI().ArePtrs64bit() ? 64 : 32;
1331 if (isa<MCSpecifierExpr>(Val: getMemOff()) ||
1332 (isConstantMemOff() && isIntN(N: PtrBits, x: getConstantMemOff())))
1333 return true;
1334 MCValue Res;
1335 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, Asm: nullptr);
1336 return IsReloc && isIntN(N: PtrBits, x: Res.getConstant());
1337 }
1338
1339 bool isMemWithGRPMM16Base() const {
1340 return isMem() && getMemBase()->isMM16AsmReg();
1341 }
1342
1343 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1344 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1345 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1346 }
1347
1348 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1349 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1350 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1351 && (getMemBase()->getGPR32Reg() == Mips::SP);
1352 }
1353
1354 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
1355 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1356 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1357 && (getMemBase()->getGPR32Reg() == Mips::GP);
1358 }
1359
1360 template <unsigned Bits, unsigned ShiftLeftAmount>
1361 bool isScaledUImm() const {
1362 return isConstantImm() &&
1363 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
1364 }
1365
1366 template <unsigned Bits, unsigned ShiftLeftAmount>
1367 bool isScaledSImm() const {
1368 if (isConstantImm() &&
1369 isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
1370 return true;
1371 // Operand can also be a symbol or symbol plus
1372 // offset in case of relocations.
1373 if (Kind != k_Immediate)
1374 return false;
1375 MCValue Res;
1376 bool Success = getImm()->evaluateAsRelocatable(Res, Asm: nullptr);
1377 return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
1378 }
1379
1380 bool isRegList16() const {
1381 if (!isRegList())
1382 return false;
1383
1384 int Size = RegList.List->size();
1385 if (Size < 2 || Size > 5)
1386 return false;
1387
1388 MCRegister R0 = RegList.List->front();
1389 MCRegister R1 = RegList.List->back();
1390 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1391 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
1392 return false;
1393
1394 MCRegister PrevReg = RegList.List->front();
1395 for (int i = 1; i < Size - 1; i++) {
1396 MCRegister Reg = (*(RegList.List))[i];
1397 if ( Reg != PrevReg + 1)
1398 return false;
1399 PrevReg = Reg;
1400 }
1401
1402 return true;
1403 }
1404
1405 bool isInvNum() const { return Kind == k_Immediate; }
1406
1407 bool isLSAImm() const {
1408 if (!isConstantImm())
1409 return false;
1410 int64_t Val = getConstantImm();
1411 return 1 <= Val && Val <= 4;
1412 }
1413
1414 bool isRegList() const { return Kind == k_RegList; }
1415
1416 StringRef getToken() const {
1417 assert(Kind == k_Token && "Invalid access!");
1418 return StringRef(Tok.Data, Tok.Length);
1419 }
1420
1421 MCRegister getReg() const override {
1422 // As a special case until we sort out the definition of div/divu, accept
1423 // $0/$zero here so that MCK_ZERO works correctly.
1424 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1425 RegIdx.Kind & RegKind_GPR)
1426 return getGPR32Reg(); // FIXME: GPR64 too
1427
1428 llvm_unreachable("Invalid access!");
1429 return 0;
1430 }
1431
1432 const MCExpr *getImm() const {
1433 assert((Kind == k_Immediate) && "Invalid access!");
1434 return Imm.Val;
1435 }
1436
1437 int64_t getConstantImm() const {
1438 const MCExpr *Val = getImm();
1439 int64_t Value = 0;
1440 (void)Val->evaluateAsAbsolute(Res&: Value);
1441 return Value;
1442 }
1443
1444 MipsOperand *getMemBase() const {
1445 assert((Kind == k_Memory) && "Invalid access!");
1446 return Mem.Base;
1447 }
1448
1449 const MCExpr *getMemOff() const {
1450 assert((Kind == k_Memory) && "Invalid access!");
1451 return Mem.Off;
1452 }
1453
1454 int64_t getConstantMemOff() const {
1455 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1456 }
1457
1458 const SmallVectorImpl<MCRegister> &getRegList() const {
1459 assert((Kind == k_RegList) && "Invalid access!");
1460 return *(RegList.List);
1461 }
1462
1463 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1464 MipsAsmParser &Parser) {
1465 auto Op = std::make_unique<MipsOperand>(args: k_Token, args&: Parser);
1466 Op->Tok.Data = Str.data();
1467 Op->Tok.Length = Str.size();
1468 Op->StartLoc = S;
1469 Op->EndLoc = S;
1470 return Op;
1471 }
1472
1473 /// Create a numeric register (e.g. $1). The exact register remains
1474 /// unresolved until an instruction successfully matches
1475 static std::unique_ptr<MipsOperand>
1476 createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1477 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1478 LLVM_DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
1479 return CreateReg(Index, Str, RegKind: RegKind_Numeric, RegInfo, S, E, Parser);
1480 }
1481
1482 /// Create a register that is definitely a GPR.
1483 /// This is typically only used for named registers such as $gp.
1484 static std::unique_ptr<MipsOperand>
1485 createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1486 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1487 return CreateReg(Index, Str, RegKind: RegKind_GPR, RegInfo, S, E, Parser);
1488 }
1489
1490 /// Create a register that is definitely a FGR.
1491 /// This is typically only used for named registers such as $f0.
1492 static std::unique_ptr<MipsOperand>
1493 createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1494 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1495 return CreateReg(Index, Str, RegKind: RegKind_FGR, RegInfo, S, E, Parser);
1496 }
1497
1498 /// Create a register that is definitely a HWReg.
1499 /// This is typically only used for named registers such as $hwr_cpunum.
1500 static std::unique_ptr<MipsOperand>
1501 createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1502 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1503 return CreateReg(Index, Str, RegKind: RegKind_HWRegs, RegInfo, S, E, Parser);
1504 }
1505
1506 /// Create a register that is definitely an FCC.
1507 /// This is typically only used for named registers such as $fcc0.
1508 static std::unique_ptr<MipsOperand>
1509 createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1510 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1511 return CreateReg(Index, Str, RegKind: RegKind_FCC, RegInfo, S, E, Parser);
1512 }
1513
1514 /// Create a register that is definitely an ACC.
1515 /// This is typically only used for named registers such as $ac0.
1516 static std::unique_ptr<MipsOperand>
1517 createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1518 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1519 return CreateReg(Index, Str, RegKind: RegKind_ACC, RegInfo, S, E, Parser);
1520 }
1521
1522 /// Create a register that is definitely an MSA128.
1523 /// This is typically only used for named registers such as $w0.
1524 static std::unique_ptr<MipsOperand>
1525 createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1526 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1527 return CreateReg(Index, Str, RegKind: RegKind_MSA128, RegInfo, S, E, Parser);
1528 }
1529
1530 /// Create a register that is definitely an MSACtrl.
1531 /// This is typically only used for named registers such as $msaaccess.
1532 static std::unique_ptr<MipsOperand>
1533 createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1534 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1535 return CreateReg(Index, Str, RegKind: RegKind_MSACtrl, RegInfo, S, E, Parser);
1536 }
1537
1538 static std::unique_ptr<MipsOperand>
1539 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1540 auto Op = std::make_unique<MipsOperand>(args: k_Immediate, args&: Parser);
1541 Op->Imm.Val = Val;
1542 Op->StartLoc = S;
1543 Op->EndLoc = E;
1544 return Op;
1545 }
1546
1547 static std::unique_ptr<MipsOperand>
1548 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1549 SMLoc E, MipsAsmParser &Parser) {
1550 auto Op = std::make_unique<MipsOperand>(args: k_Memory, args&: Parser);
1551 Op->Mem.Base = Base.release();
1552 Op->Mem.Off = Off;
1553 Op->StartLoc = S;
1554 Op->EndLoc = E;
1555 return Op;
1556 }
1557
1558 static std::unique_ptr<MipsOperand>
1559 CreateRegList(SmallVectorImpl<MCRegister> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1560 MipsAsmParser &Parser) {
1561 assert(!Regs.empty() && "Empty list not allowed");
1562
1563 auto Op = std::make_unique<MipsOperand>(args: k_RegList, args&: Parser);
1564 Op->RegList.List =
1565 new SmallVector<MCRegister, 10>(Regs.begin(), Regs.end());
1566 Op->StartLoc = StartLoc;
1567 Op->EndLoc = EndLoc;
1568 return Op;
1569 }
1570
1571 bool isGPRZeroAsmReg() const {
1572 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index == 0;
1573 }
1574
1575 bool isGPRNonZeroAsmReg() const {
1576 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index > 0 &&
1577 RegIdx.Index <= 31;
1578 }
1579
1580 bool isGPRAsmReg() const {
1581 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
1582 }
1583
1584 bool isMM16AsmReg() const {
1585 if (!(isRegIdx() && RegIdx.Kind))
1586 return false;
1587 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1588 || RegIdx.Index == 16 || RegIdx.Index == 17);
1589
1590 }
1591 bool isMM16AsmRegZero() const {
1592 if (!(isRegIdx() && RegIdx.Kind))
1593 return false;
1594 return (RegIdx.Index == 0 ||
1595 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1596 RegIdx.Index == 17);
1597 }
1598
1599 bool isMM16AsmRegMoveP() const {
1600 if (!(isRegIdx() && RegIdx.Kind))
1601 return false;
1602 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1603 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1604 }
1605
1606 bool isMM16AsmRegMovePPairFirst() const {
1607 if (!(isRegIdx() && RegIdx.Kind))
1608 return false;
1609 return RegIdx.Index >= 4 && RegIdx.Index <= 6;
1610 }
1611
1612 bool isMM16AsmRegMovePPairSecond() const {
1613 if (!(isRegIdx() && RegIdx.Kind))
1614 return false;
1615 return (RegIdx.Index == 21 || RegIdx.Index == 22 ||
1616 (RegIdx.Index >= 5 && RegIdx.Index <= 7));
1617 }
1618
1619 bool isFGRAsmReg() const {
1620 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1621 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
1622 }
1623
1624 bool isStrictlyFGRAsmReg() const {
1625 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1626 return isRegIdx() && RegIdx.Kind == RegKind_FGR && RegIdx.Index <= 31;
1627 }
1628
1629 bool isHWRegsAsmReg() const {
1630 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
1631 }
1632
1633 bool isCCRAsmReg() const {
1634 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
1635 }
1636
1637 bool isFCCAsmReg() const {
1638 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1639 return false;
1640 return RegIdx.Index <= 7;
1641 }
1642
1643 bool isACCAsmReg() const {
1644 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
1645 }
1646
1647 bool isCOP0AsmReg() const {
1648 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1649 }
1650
1651 bool isCOP2AsmReg() const {
1652 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
1653 }
1654
1655 bool isCOP3AsmReg() const {
1656 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1657 }
1658
1659 bool isMSA128AsmReg() const {
1660 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
1661 }
1662
1663 bool isMSACtrlAsmReg() const {
1664 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
1665 }
1666
1667 /// getStartLoc - Get the location of the first token of this operand.
1668 SMLoc getStartLoc() const override { return StartLoc; }
1669 /// getEndLoc - Get the location of the last token of this operand.
1670 SMLoc getEndLoc() const override { return EndLoc; }
1671
1672 void print(raw_ostream &OS, const MCAsmInfo &MAI) const override {
1673 switch (Kind) {
1674 case k_Immediate:
1675 OS << "Imm<";
1676 MAI.printExpr(OS, *Imm.Val);
1677 OS << ">";
1678 break;
1679 case k_Memory:
1680 OS << "Mem<";
1681 Mem.Base->print(OS, MAI);
1682 OS << ", ";
1683 MAI.printExpr(OS, *Mem.Off);
1684 OS << ">";
1685 break;
1686 case k_RegisterIndex:
1687 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "
1688 << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";
1689 break;
1690 case k_Token:
1691 OS << getToken();
1692 break;
1693 case k_RegList:
1694 OS << "RegList< ";
1695 for (auto Reg : (*RegList.List))
1696 OS << Reg.id() << " ";
1697 OS << ">";
1698 break;
1699 }
1700 }
1701
1702 bool isValidForTie(const MipsOperand &Other) const {
1703 if (Kind != Other.Kind)
1704 return false;
1705
1706 switch (Kind) {
1707 default:
1708 llvm_unreachable("Unexpected kind");
1709 return false;
1710 case k_RegisterIndex: {
1711 StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);
1712 StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);
1713 return Token == OtherToken;
1714 }
1715 }
1716 }
1717}; // class MipsOperand
1718
1719} // end anonymous namespace
1720
1721static bool hasShortDelaySlot(MCInst &Inst) {
1722 switch (Inst.getOpcode()) {
1723 case Mips::BEQ_MM:
1724 case Mips::BNE_MM:
1725 case Mips::BLTZ_MM:
1726 case Mips::BGEZ_MM:
1727 case Mips::BLEZ_MM:
1728 case Mips::BGTZ_MM:
1729 case Mips::JRC16_MM:
1730 case Mips::JALS_MM:
1731 case Mips::JALRS_MM:
1732 case Mips::JALRS16_MM:
1733 case Mips::BGEZALS_MM:
1734 case Mips::BLTZALS_MM:
1735 return true;
1736 case Mips::J_MM:
1737 return !Inst.getOperand(i: 0).isReg();
1738 default:
1739 return false;
1740 }
1741}
1742
1743static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1744 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Val: Expr)) {
1745 return &SRExpr->getSymbol();
1746 }
1747
1748 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Val: Expr)) {
1749 const MCSymbol *LHSSym = getSingleMCSymbol(Expr: BExpr->getLHS());
1750 const MCSymbol *RHSSym = getSingleMCSymbol(Expr: BExpr->getRHS());
1751
1752 if (LHSSym)
1753 return LHSSym;
1754
1755 if (RHSSym)
1756 return RHSSym;
1757
1758 return nullptr;
1759 }
1760
1761 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Val: Expr))
1762 return getSingleMCSymbol(Expr: UExpr->getSubExpr());
1763
1764 return nullptr;
1765}
1766
1767static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1768 if (isa<MCSymbolRefExpr>(Val: Expr))
1769 return 1;
1770
1771 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Val: Expr))
1772 return countMCSymbolRefExpr(Expr: BExpr->getLHS()) +
1773 countMCSymbolRefExpr(Expr: BExpr->getRHS());
1774
1775 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Val: Expr))
1776 return countMCSymbolRefExpr(Expr: UExpr->getSubExpr());
1777
1778 return 0;
1779}
1780
1781static bool isEvaluated(const MCExpr *Expr) {
1782 switch (Expr->getKind()) {
1783 case MCExpr::Constant:
1784 return true;
1785 case MCExpr::SymbolRef:
1786 return (cast<MCSymbolRefExpr>(Val: Expr)->getSpecifier());
1787 case MCExpr::Binary: {
1788 const MCBinaryExpr *BE = cast<MCBinaryExpr>(Val: Expr);
1789 if (!isEvaluated(Expr: BE->getLHS()))
1790 return false;
1791 return isEvaluated(Expr: BE->getRHS());
1792 }
1793 case MCExpr::Unary:
1794 return isEvaluated(Expr: cast<MCUnaryExpr>(Val: Expr)->getSubExpr());
1795 case MCExpr::Specifier:
1796 return true;
1797 case MCExpr::Target:
1798 llvm_unreachable("unused by this backend");
1799 }
1800 return false;
1801}
1802
1803static bool needsExpandMemInst(MCInst &Inst, const MCInstrDesc &MCID) {
1804 unsigned NumOp = MCID.getNumOperands();
1805 if (NumOp != 3 && NumOp != 4)
1806 return false;
1807
1808 const MCOperandInfo &OpInfo = MCID.operands()[NumOp - 1];
1809 if (OpInfo.OperandType != MCOI::OPERAND_MEMORY &&
1810 OpInfo.OperandType != MCOI::OPERAND_UNKNOWN &&
1811 OpInfo.OperandType != MipsII::OPERAND_MEM_SIMM9)
1812 return false;
1813
1814 MCOperand &Op = Inst.getOperand(i: NumOp - 1);
1815 if (Op.isImm()) {
1816 if (OpInfo.OperandType == MipsII::OPERAND_MEM_SIMM9)
1817 return !isInt<9>(x: Op.getImm());
1818 // Offset can't exceed 16bit value.
1819 return !isInt<16>(x: Op.getImm());
1820 }
1821
1822 if (Op.isExpr()) {
1823 const MCExpr *Expr = Op.getExpr();
1824 if (Expr->getKind() != MCExpr::SymbolRef)
1825 return !isEvaluated(Expr);
1826
1827 // Expand symbol.
1828 const MCSymbolRefExpr *SR = static_cast<const MCSymbolRefExpr *>(Expr);
1829 return SR->getSpecifier() == 0;
1830 }
1831
1832 return false;
1833}
1834
1835bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
1836 MCStreamer &Out,
1837 const MCSubtargetInfo *STI) {
1838 MipsTargetStreamer &TOut = getTargetStreamer();
1839 const unsigned Opcode = Inst.getOpcode();
1840 const MCInstrDesc &MCID = MII.get(Opcode);
1841 bool ExpandedJalSym = false;
1842
1843 Inst.setLoc(IDLoc);
1844
1845 if (MCID.isBranch() || MCID.isCall()) {
1846 MCOperand Offset;
1847
1848 switch (Opcode) {
1849 default:
1850 break;
1851 case Mips::BBIT0:
1852 case Mips::BBIT032:
1853 case Mips::BBIT1:
1854 case Mips::BBIT132:
1855 assert(hasCnMips() && "instruction only valid for octeon cpus");
1856 [[fallthrough]];
1857
1858 case Mips::BEQ:
1859 case Mips::BNE:
1860 case Mips::BEQ_MM:
1861 case Mips::BNE_MM:
1862 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1863 Offset = Inst.getOperand(i: 2);
1864 if (!Offset.isImm())
1865 break; // We'll deal with this situation later on when applying fixups.
1866 if (!isIntN(N: inMicroMipsMode() ? 17 : 18, x: Offset.getImm()))
1867 return Error(L: IDLoc, Msg: "branch target out of range");
1868 if (offsetToAlignment(Value: Offset.getImm(),
1869 Alignment: (inMicroMipsMode() ? Align(2) : Align(4))))
1870 return Error(L: IDLoc, Msg: "branch to misaligned address");
1871 break;
1872 case Mips::BGEZ:
1873 case Mips::BGTZ:
1874 case Mips::BLEZ:
1875 case Mips::BLTZ:
1876 case Mips::BGEZAL:
1877 case Mips::BLTZAL:
1878 case Mips::BC1F:
1879 case Mips::BC1T:
1880 case Mips::BGEZ_MM:
1881 case Mips::BGTZ_MM:
1882 case Mips::BLEZ_MM:
1883 case Mips::BLTZ_MM:
1884 case Mips::BGEZAL_MM:
1885 case Mips::BLTZAL_MM:
1886 case Mips::BC1F_MM:
1887 case Mips::BC1T_MM:
1888 case Mips::BC1EQZC_MMR6:
1889 case Mips::BC1NEZC_MMR6:
1890 case Mips::BC2EQZC_MMR6:
1891 case Mips::BC2NEZC_MMR6:
1892 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1893 Offset = Inst.getOperand(i: 1);
1894 if (!Offset.isImm())
1895 break; // We'll deal with this situation later on when applying fixups.
1896 if (!isIntN(N: inMicroMipsMode() ? 17 : 18, x: Offset.getImm()))
1897 return Error(L: IDLoc, Msg: "branch target out of range");
1898 if (offsetToAlignment(Value: Offset.getImm(),
1899 Alignment: (inMicroMipsMode() ? Align(2) : Align(4))))
1900 return Error(L: IDLoc, Msg: "branch to misaligned address");
1901 break;
1902 case Mips::BGEC: case Mips::BGEC_MMR6:
1903 case Mips::BLTC: case Mips::BLTC_MMR6:
1904 case Mips::BGEUC: case Mips::BGEUC_MMR6:
1905 case Mips::BLTUC: case Mips::BLTUC_MMR6:
1906 case Mips::BEQC: case Mips::BEQC_MMR6:
1907 case Mips::BNEC: case Mips::BNEC_MMR6:
1908 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1909 Offset = Inst.getOperand(i: 2);
1910 if (!Offset.isImm())
1911 break; // We'll deal with this situation later on when applying fixups.
1912 if (!isIntN(N: 18, x: Offset.getImm()))
1913 return Error(L: IDLoc, Msg: "branch target out of range");
1914 if (offsetToAlignment(Value: Offset.getImm(), Alignment: Align(4)))
1915 return Error(L: IDLoc, Msg: "branch to misaligned address");
1916 break;
1917 case Mips::BLEZC: case Mips::BLEZC_MMR6:
1918 case Mips::BGEZC: case Mips::BGEZC_MMR6:
1919 case Mips::BGTZC: case Mips::BGTZC_MMR6:
1920 case Mips::BLTZC: case Mips::BLTZC_MMR6:
1921 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1922 Offset = Inst.getOperand(i: 1);
1923 if (!Offset.isImm())
1924 break; // We'll deal with this situation later on when applying fixups.
1925 if (!isIntN(N: 18, x: Offset.getImm()))
1926 return Error(L: IDLoc, Msg: "branch target out of range");
1927 if (offsetToAlignment(Value: Offset.getImm(), Alignment: Align(4)))
1928 return Error(L: IDLoc, Msg: "branch to misaligned address");
1929 break;
1930 case Mips::BEQZC: case Mips::BEQZC_MMR6:
1931 case Mips::BNEZC: case Mips::BNEZC_MMR6:
1932 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1933 Offset = Inst.getOperand(i: 1);
1934 if (!Offset.isImm())
1935 break; // We'll deal with this situation later on when applying fixups.
1936 if (!isIntN(N: 23, x: Offset.getImm()))
1937 return Error(L: IDLoc, Msg: "branch target out of range");
1938 if (offsetToAlignment(Value: Offset.getImm(), Alignment: Align(4)))
1939 return Error(L: IDLoc, Msg: "branch to misaligned address");
1940 break;
1941 case Mips::BEQZ16_MM:
1942 case Mips::BEQZC16_MMR6:
1943 case Mips::BNEZ16_MM:
1944 case Mips::BNEZC16_MMR6:
1945 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1946 Offset = Inst.getOperand(i: 1);
1947 if (!Offset.isImm())
1948 break; // We'll deal with this situation later on when applying fixups.
1949 if (!isInt<8>(x: Offset.getImm()))
1950 return Error(L: IDLoc, Msg: "branch target out of range");
1951 if (offsetToAlignment(Value: Offset.getImm(), Alignment: Align(2)))
1952 return Error(L: IDLoc, Msg: "branch to misaligned address");
1953 break;
1954 }
1955 }
1956
1957 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1958 // We still accept it but it is a normal nop.
1959 if (hasMips32r6() && Opcode == Mips::SSNOP) {
1960 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1961 Warning(L: IDLoc, Msg: "ssnop is deprecated for " + ISA + " and is equivalent to a "
1962 "nop instruction");
1963 }
1964
1965 if (hasCnMips()) {
1966 MCOperand Opnd;
1967 int Imm;
1968
1969 switch (Opcode) {
1970 default:
1971 break;
1972
1973 case Mips::BBIT0:
1974 case Mips::BBIT032:
1975 case Mips::BBIT1:
1976 case Mips::BBIT132:
1977 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1978 // The offset is handled above
1979 Opnd = Inst.getOperand(i: 1);
1980 if (!Opnd.isImm())
1981 return Error(L: IDLoc, Msg: "expected immediate operand kind");
1982 Imm = Opnd.getImm();
1983 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1984 Opcode == Mips::BBIT1 ? 63 : 31))
1985 return Error(L: IDLoc, Msg: "immediate operand value out of range");
1986 if (Imm > 31) {
1987 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1988 : Mips::BBIT132);
1989 Inst.getOperand(i: 1).setImm(Imm - 32);
1990 }
1991 break;
1992
1993 case Mips::SEQi:
1994 case Mips::SNEi:
1995 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1996 Opnd = Inst.getOperand(i: 2);
1997 if (!Opnd.isImm())
1998 return Error(L: IDLoc, Msg: "expected immediate operand kind");
1999 Imm = Opnd.getImm();
2000 if (!isInt<10>(x: Imm))
2001 return Error(L: IDLoc, Msg: "immediate operand value out of range");
2002 break;
2003 }
2004 }
2005
2006 // Warn on division by zero. We're checking here as all instructions get
2007 // processed here, not just the macros that need expansion.
2008 //
2009 // The MIPS backend models most of the divison instructions and macros as
2010 // three operand instructions. The pre-R6 divide instructions however have
2011 // two operands and explicitly define HI/LO as part of the instruction,
2012 // not in the operands.
2013 unsigned FirstOp = 1;
2014 unsigned SecondOp = 2;
2015 switch (Opcode) {
2016 default:
2017 break;
2018 case Mips::SDivIMacro:
2019 case Mips::UDivIMacro:
2020 case Mips::DSDivIMacro:
2021 case Mips::DUDivIMacro:
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 (MCID.mayLoad() && Opcode != Mips::LWP_MM) {
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 =
2959 Res.getAddSym()->isInSection() || Res.getAddSym()->isTemporary() ||
2960 (getContext().isELF() &&
2961 static_cast<const MCSymbolELF *>(Res.getAddSym())->getBinding() ==
2962 ELF::STB_LOCAL);
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 (MipsMCRegisterClasses[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_SImm19_Lsl2:
6052 return Error(L: RefineErrorLoc(Loc: IDLoc, Operands, ErrorInfo),
6053 Msg: "expected both 19-bit signed immediate and multiple of 4");
6054 case Match_UImm20_0:
6055 return Error(L: RefineErrorLoc(Loc: IDLoc, Operands, ErrorInfo),
6056 Msg: "expected 20-bit unsigned immediate");
6057 case Match_UImm26_0:
6058 return Error(L: RefineErrorLoc(Loc: IDLoc, Operands, ErrorInfo),
6059 Msg: "expected 26-bit unsigned immediate");
6060 case Match_SImm32:
6061 case Match_SImm32_Relaxed:
6062 return Error(L: RefineErrorLoc(Loc: IDLoc, Operands, ErrorInfo),
6063 Msg: "expected 32-bit signed immediate");
6064 case Match_UImm32_Coerced:
6065 return Error(L: RefineErrorLoc(Loc: IDLoc, Operands, ErrorInfo),
6066 Msg: "expected 32-bit immediate");
6067 case Match_MemSImm9:
6068 return Error(L: RefineErrorLoc(Loc: IDLoc, Operands, ErrorInfo),
6069 Msg: "expected memory with 9-bit signed offset");
6070 case Match_MemSImm10:
6071 return Error(L: RefineErrorLoc(Loc: IDLoc, Operands, ErrorInfo),
6072 Msg: "expected memory with 10-bit signed offset");
6073 case Match_MemSImm10Lsl1:
6074 return Error(L: RefineErrorLoc(Loc: IDLoc, Operands, ErrorInfo),
6075 Msg: "expected memory with 11-bit signed offset and multiple of 2");
6076 case Match_MemSImm10Lsl2:
6077 return Error(L: RefineErrorLoc(Loc: IDLoc, Operands, ErrorInfo),
6078 Msg: "expected memory with 12-bit signed offset and multiple of 4");
6079 case Match_MemSImm10Lsl3:
6080 return Error(L: RefineErrorLoc(Loc: IDLoc, Operands, ErrorInfo),
6081 Msg: "expected memory with 13-bit signed offset and multiple of 8");
6082 case Match_MemSImm11:
6083 return Error(L: RefineErrorLoc(Loc: IDLoc, Operands, ErrorInfo),
6084 Msg: "expected memory with 11-bit signed offset");
6085 case Match_MemSImm12:
6086 return Error(L: RefineErrorLoc(Loc: IDLoc, Operands, ErrorInfo),
6087 Msg: "expected memory with 12-bit signed offset");
6088 case Match_MemSImm16:
6089 return Error(L: RefineErrorLoc(Loc: IDLoc, Operands, ErrorInfo),
6090 Msg: "expected memory with 16-bit signed offset");
6091 case Match_MemSImmPtr:
6092 return Error(L: RefineErrorLoc(Loc: IDLoc, Operands, ErrorInfo),
6093 Msg: "expected memory with 32-bit signed offset");
6094 case Match_RequiresPosSizeRange0_32: {
6095 SMLoc ErrorStart = Operands[3]->getStartLoc();
6096 SMLoc ErrorEnd = Operands[4]->getEndLoc();
6097 return Error(L: ErrorStart, Msg: "size plus position are not in the range 0 .. 32",
6098 Range: SMRange(ErrorStart, ErrorEnd));
6099 }
6100 case Match_RequiresPosSizeUImm6: {
6101 SMLoc ErrorStart = Operands[3]->getStartLoc();
6102 SMLoc ErrorEnd = Operands[4]->getEndLoc();
6103 return Error(L: ErrorStart, Msg: "size plus position are not in the range 1 .. 63",
6104 Range: SMRange(ErrorStart, ErrorEnd));
6105 }
6106 case Match_RequiresPosSizeRange33_64: {
6107 SMLoc ErrorStart = Operands[3]->getStartLoc();
6108 SMLoc ErrorEnd = Operands[4]->getEndLoc();
6109 return Error(L: ErrorStart, Msg: "size plus position are not in the range 33 .. 64",
6110 Range: SMRange(ErrorStart, ErrorEnd));
6111 }
6112 }
6113
6114 llvm_unreachable("Implement any new match types added!");
6115}
6116
6117void MipsAsmParser::warnIfRegIndexIsAT(MCRegister RegIndex, SMLoc Loc) {
6118 if (RegIndex && AssemblerOptions.back()->getATRegIndex() == RegIndex)
6119 Warning(L: Loc, Msg: "used $at (currently $" + Twine(RegIndex.id()) +
6120 ") without \".set noat\"");
6121}
6122
6123void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
6124 if (!AssemblerOptions.back()->isMacro())
6125 Warning(L: Loc, Msg: "macro instruction expanded into multiple instructions");
6126}
6127
6128void MipsAsmParser::ConvertXWPOperands(MCInst &Inst,
6129 const OperandVector &Operands) {
6130 assert(
6131 (Inst.getOpcode() == Mips::LWP_MM || Inst.getOpcode() == Mips::SWP_MM) &&
6132 "Unexpected instruction!");
6133 ((MipsOperand &)*Operands[1]).addGPR32ZeroAsmRegOperands(Inst, N: 1);
6134 MCRegister NextReg = nextReg(Reg: ((MipsOperand &)*Operands[1]).getGPR32Reg());
6135 Inst.addOperand(Op: MCOperand::createReg(Reg: NextReg));
6136 ((MipsOperand &)*Operands[2]).addMemOperands(Inst, N: 2);
6137}
6138
6139void
6140MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
6141 SMRange Range, bool ShowColors) {
6142 getSourceManager().PrintMessage(Loc: Range.Start, Kind: SourceMgr::DK_Warning, Msg,
6143 Ranges: Range, FixIts: SMFixIt(Range, FixMsg),
6144 ShowColors);
6145}
6146
6147int MipsAsmParser::matchCPURegisterName(StringRef Name) {
6148 int CC;
6149
6150 CC = StringSwitch<unsigned>(Name)
6151 .Case(S: "zero", Value: 0)
6152 .Cases(CaseStrings: {"at", "AT"}, Value: 1)
6153 .Case(S: "a0", Value: 4)
6154 .Case(S: "a1", Value: 5)
6155 .Case(S: "a2", Value: 6)
6156 .Case(S: "a3", Value: 7)
6157 .Case(S: "v0", Value: 2)
6158 .Case(S: "v1", Value: 3)
6159 .Case(S: "s0", Value: 16)
6160 .Case(S: "s1", Value: 17)
6161 .Case(S: "s2", Value: 18)
6162 .Case(S: "s3", Value: 19)
6163 .Case(S: "s4", Value: 20)
6164 .Case(S: "s5", Value: 21)
6165 .Case(S: "s6", Value: 22)
6166 .Case(S: "s7", Value: 23)
6167 .Case(S: "k0", Value: 26)
6168 .Case(S: "k1", Value: 27)
6169 .Case(S: "gp", Value: 28)
6170 .Case(S: "sp", Value: 29)
6171 .Case(S: "fp", Value: 30)
6172 .Case(S: "s8", Value: 30)
6173 .Case(S: "ra", Value: 31)
6174 .Case(S: "t0", Value: 8)
6175 .Case(S: "t1", Value: 9)
6176 .Case(S: "t2", Value: 10)
6177 .Case(S: "t3", Value: 11)
6178 .Case(S: "t4", Value: 12)
6179 .Case(S: "t5", Value: 13)
6180 .Case(S: "t6", Value: 14)
6181 .Case(S: "t7", Value: 15)
6182 .Case(S: "t8", Value: 24)
6183 .Case(S: "t9", Value: 25)
6184 .Default(Value: -1);
6185
6186 if (!(isABI_N32() || isABI_N64()))
6187 return CC;
6188
6189 if (12 <= CC && CC <= 15) {
6190 // Name is one of t4-t7
6191 AsmToken RegTok = getLexer().peekTok();
6192 SMRange RegRange = RegTok.getLocRange();
6193
6194 StringRef FixedName = StringSwitch<StringRef>(Name)
6195 .Case(S: "t4", Value: "t0")
6196 .Case(S: "t5", Value: "t1")
6197 .Case(S: "t6", Value: "t2")
6198 .Case(S: "t7", Value: "t3")
6199 .Default(Value: "");
6200 assert(FixedName != "" && "Register name is not one of t4-t7.");
6201
6202 printWarningWithFixIt(Msg: "register names $t4-$t7 are only available in O32.",
6203 FixMsg: "Did you mean $" + FixedName + "?", Range: RegRange);
6204 }
6205
6206 // Although SGI documentation just cuts out t0-t3 for n32/n64,
6207 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
6208 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
6209 if (8 <= CC && CC <= 11)
6210 CC += 4;
6211
6212 if (CC == -1)
6213 CC = StringSwitch<unsigned>(Name)
6214 .Case(S: "a4", Value: 8)
6215 .Case(S: "a5", Value: 9)
6216 .Case(S: "a6", Value: 10)
6217 .Case(S: "a7", Value: 11)
6218 .Case(S: "kt0", Value: 26)
6219 .Case(S: "kt1", Value: 27)
6220 .Default(Value: -1);
6221
6222 return CC;
6223}
6224
6225int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
6226 int CC;
6227
6228 CC = StringSwitch<unsigned>(Name)
6229 .Case(S: "hwr_cpunum", Value: 0)
6230 .Case(S: "hwr_synci_step", Value: 1)
6231 .Case(S: "hwr_cc", Value: 2)
6232 .Case(S: "hwr_ccres", Value: 3)
6233 .Case(S: "hwr_ulr", Value: 29)
6234 .Default(Value: -1);
6235
6236 return CC;
6237}
6238
6239int MipsAsmParser::matchFPURegisterName(StringRef Name) {
6240 if (Name[0] == 'f') {
6241 StringRef NumString = Name.substr(Start: 1);
6242 unsigned IntVal;
6243 if (NumString.getAsInteger(Radix: 10, Result&: IntVal))
6244 return -1; // This is not an integer.
6245 if (IntVal > 31) // Maximum index for fpu register.
6246 return -1;
6247 return IntVal;
6248 }
6249 return -1;
6250}
6251
6252int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
6253 if (Name.starts_with(Prefix: "fcc")) {
6254 StringRef NumString = Name.substr(Start: 3);
6255 unsigned IntVal;
6256 if (NumString.getAsInteger(Radix: 10, Result&: IntVal))
6257 return -1; // This is not an integer.
6258 if (IntVal > 7) // There are only 8 fcc registers.
6259 return -1;
6260 return IntVal;
6261 }
6262 return -1;
6263}
6264
6265int MipsAsmParser::matchACRegisterName(StringRef Name) {
6266 if (Name.starts_with(Prefix: "ac")) {
6267 StringRef NumString = Name.substr(Start: 2);
6268 unsigned IntVal;
6269 if (NumString.getAsInteger(Radix: 10, Result&: IntVal))
6270 return -1; // This is not an integer.
6271 if (IntVal > 3) // There are only 3 acc registers.
6272 return -1;
6273 return IntVal;
6274 }
6275 return -1;
6276}
6277
6278int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
6279 unsigned IntVal;
6280
6281 if (Name.front() != 'w' || Name.drop_front(N: 1).getAsInteger(Radix: 10, Result&: IntVal))
6282 return -1;
6283
6284 if (IntVal > 31)
6285 return -1;
6286
6287 return IntVal;
6288}
6289
6290int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
6291 int CC;
6292
6293 CC = StringSwitch<unsigned>(Name)
6294 .Case(S: "msair", Value: 0)
6295 .Case(S: "msacsr", Value: 1)
6296 .Case(S: "msaaccess", Value: 2)
6297 .Case(S: "msasave", Value: 3)
6298 .Case(S: "msamodify", Value: 4)
6299 .Case(S: "msarequest", Value: 5)
6300 .Case(S: "msamap", Value: 6)
6301 .Case(S: "msaunmap", Value: 7)
6302 .Default(Value: -1);
6303
6304 return CC;
6305}
6306
6307bool MipsAsmParser::canUseATReg() {
6308 return AssemblerOptions.back()->getATRegIndex() != 0;
6309}
6310
6311MCRegister MipsAsmParser::getATReg(SMLoc Loc) {
6312 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
6313 if (ATIndex == 0) {
6314 reportParseError(Loc,
6315 ErrorMsg: "pseudo-instruction requires $at, which is not available");
6316 return 0;
6317 }
6318 MCRegister AT = getReg(
6319 RC: (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, RegNo: ATIndex);
6320 return AT;
6321}
6322
6323MCRegister MipsAsmParser::getReg(int RC, int RegNo) {
6324 return getContext().getRegisterInfo()->getRegClass(i: RC).getRegister(i: RegNo);
6325}
6326
6327// Parse an expression with optional relocation operator prefixes (e.g. %lo).
6328// Some weird expressions allowed by gas are not supported for simplicity,
6329// e.g. "%lo foo", "(%lo(foo))", "%lo(foo)+1".
6330const MCExpr *MipsAsmParser::parseRelocExpr() {
6331 auto getOp = [](StringRef Op) {
6332 return StringSwitch<Mips::Specifier>(Op)
6333 .Case(S: "call16", Value: Mips::S_GOT_CALL)
6334 .Case(S: "call_hi", Value: Mips::S_CALL_HI16)
6335 .Case(S: "call_lo", Value: Mips::S_CALL_LO16)
6336 .Case(S: "dtprel_hi", Value: Mips::S_DTPREL_HI)
6337 .Case(S: "dtprel_lo", Value: Mips::S_DTPREL_LO)
6338 .Case(S: "got", Value: Mips::S_GOT)
6339 .Case(S: "got_disp", Value: Mips::S_GOT_DISP)
6340 .Case(S: "got_hi", Value: Mips::S_GOT_HI16)
6341 .Case(S: "got_lo", Value: Mips::S_GOT_LO16)
6342 .Case(S: "got_ofst", Value: Mips::S_GOT_OFST)
6343 .Case(S: "got_page", Value: Mips::S_GOT_PAGE)
6344 .Case(S: "gottprel", Value: Mips::S_GOTTPREL)
6345 .Case(S: "gp_rel", Value: Mips::S_GPREL)
6346 .Case(S: "hi", Value: Mips::S_HI)
6347 .Case(S: "higher", Value: Mips::S_HIGHER)
6348 .Case(S: "highest", Value: Mips::S_HIGHEST)
6349 .Case(S: "lo", Value: Mips::S_LO)
6350 .Case(S: "neg", Value: Mips::S_NEG)
6351 .Case(S: "pcrel_hi", Value: Mips::S_PCREL_HI16)
6352 .Case(S: "pcrel_lo", Value: Mips::S_PCREL_LO16)
6353 .Case(S: "tlsgd", Value: Mips::S_TLSGD)
6354 .Case(S: "tlsldm", Value: Mips::S_TLSLDM)
6355 .Case(S: "tprel_hi", Value: Mips::S_TPREL_HI)
6356 .Case(S: "tprel_lo", Value: Mips::S_TPREL_LO)
6357 .Default(Value: Mips::S_None);
6358 };
6359
6360 MCAsmParser &Parser = getParser();
6361 StringRef Name;
6362 const MCExpr *Res = nullptr;
6363 SmallVector<Mips::Specifier, 0> Ops;
6364 while (parseOptionalToken(T: AsmToken::Percent)) {
6365 if (Parser.parseIdentifier(Res&: Name) ||
6366 Parser.parseToken(T: AsmToken::LParen, Msg: "expected '('"))
6367 return nullptr;
6368 auto Op = getOp(Name);
6369 if (Op == Mips::S_None) {
6370 Error(L: Parser.getTok().getLoc(), Msg: "invalid relocation operator");
6371 return nullptr;
6372 }
6373 Ops.push_back(Elt: Op);
6374 }
6375 if (Parser.parseExpression(Res))
6376 return nullptr;
6377 while (Ops.size()) {
6378 if (Parser.parseToken(T: AsmToken::RParen, Msg: "expected ')'"))
6379 return nullptr;
6380 Res = MCSpecifierExpr::create(Expr: Res, S: Ops.pop_back_val(), Ctx&: getContext());
6381 }
6382 return Res;
6383}
6384
6385bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
6386 MCAsmParser &Parser = getParser();
6387 LLVM_DEBUG(dbgs() << "parseOperand\n");
6388
6389 // Check if the current operand has a custom associated parser, if so, try to
6390 // custom parse the operand, or fallback to the general approach.
6391 // Setting the third parameter to true tells the parser to keep parsing even
6392 // if the operands are not supported with the current feature set. In this
6393 // case, the instruction matcher will output a "instruction requires a CPU
6394 // feature not currently enabled" error. If this were false, the parser would
6395 // stop here and output a less useful "invalid operand" error.
6396 ParseStatus Res = MatchOperandParserImpl(Operands, Mnemonic, ParseForAllFeatures: true);
6397 if (Res.isSuccess())
6398 return false;
6399 // If there wasn't a custom match, try the generic matcher below. Otherwise,
6400 // there was a match, but an error occurred, in which case, just return that
6401 // the operand parsing failed.
6402 if (Res.isFailure())
6403 return true;
6404
6405 LLVM_DEBUG(dbgs() << ".. Generic Parser\n");
6406
6407 switch (getLexer().getKind()) {
6408 case AsmToken::Dollar: {
6409 // Parse the register.
6410 SMLoc S = Parser.getTok().getLoc();
6411
6412 // Almost all registers have been parsed by custom parsers. There is only
6413 // one exception to this. $zero (and it's alias $0) will reach this point
6414 // for div, divu, and similar instructions because it is not an operand
6415 // to the instruction definition but an explicit register. Special case
6416 // this situation for now.
6417 if (!parseAnyRegister(Operands).isNoMatch())
6418 return false;
6419
6420 // Maybe it is a symbol reference.
6421 StringRef Identifier;
6422 if (Parser.parseIdentifier(Res&: Identifier))
6423 return true;
6424
6425 SMLoc E = SMLoc::getFromPointer(Ptr: Parser.getTok().getLoc().getPointer() - 1);
6426 MCSymbol *Sym = getContext().getOrCreateSymbol(Name: Identifier);
6427 // Otherwise create a symbol reference.
6428 const MCExpr *SymRef = MCSymbolRefExpr::create(Symbol: Sym, Ctx&: getContext());
6429
6430 Operands.push_back(Elt: MipsOperand::CreateImm(Val: SymRef, S, E, Parser&: *this));
6431 return false;
6432 }
6433 default: {
6434 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
6435 const MCExpr *Expr = parseRelocExpr();
6436 if (!Expr)
6437 return true;
6438 SMLoc E = SMLoc::getFromPointer(Ptr: Parser.getTok().getLoc().getPointer() - 1);
6439 Operands.push_back(Elt: MipsOperand::CreateImm(Val: Expr, S, E, Parser&: *this));
6440 return false;
6441 }
6442 } // switch(getLexer().getKind())
6443 return true;
6444}
6445
6446bool MipsAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
6447 SMLoc &EndLoc) {
6448 return !tryParseRegister(Reg, StartLoc, EndLoc).isSuccess();
6449}
6450
6451ParseStatus MipsAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
6452 SMLoc &EndLoc) {
6453 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
6454 ParseStatus Res = parseAnyRegister(Operands);
6455 if (Res.isSuccess()) {
6456 assert(Operands.size() == 1);
6457 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
6458 StartLoc = Operand.getStartLoc();
6459 EndLoc = Operand.getEndLoc();
6460
6461 // AFAIK, we only support numeric registers and named GPR's in CFI
6462 // directives.
6463 // Don't worry about eating tokens before failing. Using an unrecognised
6464 // register is a parse error.
6465 if (Operand.isGPRAsmReg()) {
6466 // Resolve to GPR32 or GPR64 appropriately.
6467 Reg = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
6468 }
6469
6470 return (Reg == (unsigned)-1) ? ParseStatus::NoMatch : ParseStatus::Success;
6471 }
6472
6473 assert(Operands.size() == 0);
6474 return (Reg == (unsigned)-1) ? ParseStatus::NoMatch : ParseStatus::Success;
6475}
6476
6477ParseStatus MipsAsmParser::parseMemOperand(OperandVector &Operands) {
6478 MCAsmParser &Parser = getParser();
6479 LLVM_DEBUG(dbgs() << "parseMemOperand\n");
6480 const MCExpr *IdVal = nullptr;
6481 SMLoc S;
6482 bool isParenExpr = false;
6483 ParseStatus Res = ParseStatus::NoMatch;
6484 // First operand is the offset.
6485 S = Parser.getTok().getLoc();
6486
6487 if (getLexer().getKind() == AsmToken::LParen) {
6488 Parser.Lex();
6489 isParenExpr = true;
6490 }
6491
6492 if (getLexer().getKind() != AsmToken::Dollar) {
6493 IdVal = parseRelocExpr();
6494 if (!IdVal)
6495 return ParseStatus::Failure;
6496 if (isParenExpr && Parser.parseRParen())
6497 return ParseStatus::Failure;
6498
6499 const AsmToken &Tok = Parser.getTok(); // Get the next token.
6500 if (Tok.isNot(K: AsmToken::LParen)) {
6501 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
6502 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
6503 SMLoc E =
6504 SMLoc::getFromPointer(Ptr: Parser.getTok().getLoc().getPointer() - 1);
6505 Operands.push_back(Elt: MipsOperand::CreateImm(Val: IdVal, S, E, Parser&: *this));
6506 return ParseStatus::Success;
6507 }
6508 if (Tok.is(K: AsmToken::EndOfStatement)) {
6509 SMLoc E =
6510 SMLoc::getFromPointer(Ptr: Parser.getTok().getLoc().getPointer() - 1);
6511
6512 // Zero register assumed, add a memory operand with ZERO as its base.
6513 // "Base" will be managed by k_Memory.
6514 auto Base = MipsOperand::createGPRReg(
6515 Index: 0, Str: "0", RegInfo: getContext().getRegisterInfo(), S, E, Parser&: *this);
6516 Operands.push_back(
6517 Elt: MipsOperand::CreateMem(Base: std::move(Base), Off: IdVal, S, E, Parser&: *this));
6518 return ParseStatus::Success;
6519 }
6520 MCBinaryExpr::Opcode Opcode;
6521 // GAS and LLVM treat comparison operators different. GAS will generate -1
6522 // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is
6523 // highly unlikely to be found in a memory offset expression, we don't
6524 // handle them.
6525 switch (Tok.getKind()) {
6526 case AsmToken::Plus:
6527 Opcode = MCBinaryExpr::Add;
6528 Parser.Lex();
6529 break;
6530 case AsmToken::Minus:
6531 Opcode = MCBinaryExpr::Sub;
6532 Parser.Lex();
6533 break;
6534 case AsmToken::Star:
6535 Opcode = MCBinaryExpr::Mul;
6536 Parser.Lex();
6537 break;
6538 case AsmToken::Pipe:
6539 Opcode = MCBinaryExpr::Or;
6540 Parser.Lex();
6541 break;
6542 case AsmToken::Amp:
6543 Opcode = MCBinaryExpr::And;
6544 Parser.Lex();
6545 break;
6546 case AsmToken::LessLess:
6547 Opcode = MCBinaryExpr::Shl;
6548 Parser.Lex();
6549 break;
6550 case AsmToken::GreaterGreater:
6551 Opcode = MCBinaryExpr::LShr;
6552 Parser.Lex();
6553 break;
6554 case AsmToken::Caret:
6555 Opcode = MCBinaryExpr::Xor;
6556 Parser.Lex();
6557 break;
6558 case AsmToken::Slash:
6559 Opcode = MCBinaryExpr::Div;
6560 Parser.Lex();
6561 break;
6562 case AsmToken::Percent:
6563 Opcode = MCBinaryExpr::Mod;
6564 Parser.Lex();
6565 break;
6566 default:
6567 return Error(L: Parser.getTok().getLoc(), Msg: "'(' or expression expected");
6568 }
6569 const MCExpr * NextExpr;
6570 if (getParser().parseExpression(Res&: NextExpr))
6571 return ParseStatus::Failure;
6572 IdVal = MCBinaryExpr::create(Op: Opcode, LHS: IdVal, RHS: NextExpr, Ctx&: getContext());
6573 }
6574
6575 Parser.Lex(); // Eat the '(' token.
6576 }
6577
6578 Res = parseAnyRegister(Operands);
6579 if (!Res.isSuccess())
6580 return Res;
6581
6582 if (Parser.getTok().isNot(K: AsmToken::RParen))
6583 return Error(L: Parser.getTok().getLoc(), Msg: "')' expected");
6584
6585 SMLoc E = SMLoc::getFromPointer(Ptr: Parser.getTok().getLoc().getPointer() - 1);
6586
6587 Parser.Lex(); // Eat the ')' token.
6588
6589 if (!IdVal)
6590 IdVal = MCConstantExpr::create(Value: 0, Ctx&: getContext());
6591
6592 // Replace the register operand with the memory operand.
6593 std::unique_ptr<MipsOperand> op(
6594 static_cast<MipsOperand *>(Operands.back().release()));
6595 // Remove the register from the operands.
6596 // "op" will be managed by k_Memory.
6597 Operands.pop_back();
6598 // Add the memory operand.
6599 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Val: IdVal)) {
6600 int64_t Imm;
6601 if (IdVal->evaluateAsAbsolute(Res&: Imm))
6602 IdVal = MCConstantExpr::create(Value: Imm, Ctx&: getContext());
6603 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
6604 IdVal = MCBinaryExpr::create(Op: BE->getOpcode(), LHS: BE->getRHS(), RHS: BE->getLHS(),
6605 Ctx&: getContext());
6606 }
6607
6608 Operands.push_back(Elt: MipsOperand::CreateMem(Base: std::move(op), Off: IdVal, S, E, Parser&: *this));
6609 return ParseStatus::Success;
6610}
6611
6612bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
6613 MCAsmParser &Parser = getParser();
6614 MCSymbol *Sym = getContext().lookupSymbol(Name: Parser.getTok().getIdentifier());
6615 if (!Sym)
6616 return false;
6617
6618 SMLoc S = Parser.getTok().getLoc();
6619 if (Sym->isVariable()) {
6620 const MCExpr *Expr = Sym->getVariableValue();
6621 if (Expr->getKind() == MCExpr::SymbolRef) {
6622 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
6623 StringRef DefSymbol = Ref->getSymbol().getName();
6624 if (DefSymbol.starts_with(Prefix: "$")) {
6625 ParseStatus Res =
6626 matchAnyRegisterNameWithoutDollar(Operands, Identifier: DefSymbol.substr(Start: 1), S);
6627 if (Res.isSuccess()) {
6628 Parser.Lex();
6629 return true;
6630 }
6631 if (Res.isFailure())
6632 llvm_unreachable("Should never fail");
6633 }
6634 }
6635 } else if (Sym->isUndefined()) {
6636 // If symbol is unset, it might be created in the `parseSetAssignment`
6637 // routine as an alias for a numeric register name.
6638 // Lookup in the aliases list.
6639 auto Entry = RegisterSets.find(Key: Sym->getName());
6640 if (Entry != RegisterSets.end()) {
6641 ParseStatus Res =
6642 matchAnyRegisterWithoutDollar(Operands, Token: Entry->getValue(), S);
6643 if (Res.isSuccess()) {
6644 Parser.Lex();
6645 return true;
6646 }
6647 }
6648 }
6649
6650 return false;
6651}
6652
6653ParseStatus MipsAsmParser::matchAnyRegisterNameWithoutDollar(
6654 OperandVector &Operands, StringRef Identifier, SMLoc S) {
6655 int Index = matchCPURegisterName(Name: Identifier);
6656 if (Index != -1) {
6657 Operands.push_back(Elt: MipsOperand::createGPRReg(
6658 Index, Str: Identifier, RegInfo: getContext().getRegisterInfo(), S,
6659 E: getLexer().getLoc(), Parser&: *this));
6660 return ParseStatus::Success;
6661 }
6662
6663 Index = matchHWRegsRegisterName(Name: Identifier);
6664 if (Index != -1) {
6665 Operands.push_back(Elt: MipsOperand::createHWRegsReg(
6666 Index, Str: Identifier, RegInfo: getContext().getRegisterInfo(), S,
6667 E: getLexer().getLoc(), Parser&: *this));
6668 return ParseStatus::Success;
6669 }
6670
6671 Index = matchFPURegisterName(Name: Identifier);
6672 if (Index != -1) {
6673 Operands.push_back(Elt: MipsOperand::createFGRReg(
6674 Index, Str: Identifier, RegInfo: getContext().getRegisterInfo(), S,
6675 E: getLexer().getLoc(), Parser&: *this));
6676 return ParseStatus::Success;
6677 }
6678
6679 Index = matchFCCRegisterName(Name: Identifier);
6680 if (Index != -1) {
6681 Operands.push_back(Elt: MipsOperand::createFCCReg(
6682 Index, Str: Identifier, RegInfo: getContext().getRegisterInfo(), S,
6683 E: getLexer().getLoc(), Parser&: *this));
6684 return ParseStatus::Success;
6685 }
6686
6687 Index = matchACRegisterName(Name: Identifier);
6688 if (Index != -1) {
6689 Operands.push_back(Elt: MipsOperand::createACCReg(
6690 Index, Str: Identifier, RegInfo: getContext().getRegisterInfo(), S,
6691 E: getLexer().getLoc(), Parser&: *this));
6692 return ParseStatus::Success;
6693 }
6694
6695 Index = matchMSA128RegisterName(Name: Identifier);
6696 if (Index != -1) {
6697 Operands.push_back(Elt: MipsOperand::createMSA128Reg(
6698 Index, Str: Identifier, RegInfo: getContext().getRegisterInfo(), S,
6699 E: getLexer().getLoc(), Parser&: *this));
6700 return ParseStatus::Success;
6701 }
6702
6703 Index = matchMSA128CtrlRegisterName(Name: Identifier);
6704 if (Index != -1) {
6705 Operands.push_back(Elt: MipsOperand::createMSACtrlReg(
6706 Index, Str: Identifier, RegInfo: getContext().getRegisterInfo(), S,
6707 E: getLexer().getLoc(), Parser&: *this));
6708 return ParseStatus::Success;
6709 }
6710
6711 return ParseStatus::NoMatch;
6712}
6713
6714ParseStatus
6715MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands,
6716 const AsmToken &Token, SMLoc S) {
6717 if (Token.is(K: AsmToken::Identifier)) {
6718 LLVM_DEBUG(dbgs() << ".. identifier\n");
6719 StringRef Identifier = Token.getIdentifier();
6720 return matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
6721 }
6722 if (Token.is(K: AsmToken::Integer)) {
6723 LLVM_DEBUG(dbgs() << ".. integer\n");
6724 int64_t RegNum = Token.getIntVal();
6725 if (RegNum < 0 || RegNum > 31) {
6726 // Show the error, but treat invalid register
6727 // number as a normal one to continue parsing
6728 // and catch other possible errors.
6729 Error(L: getLexer().getLoc(), Msg: "invalid register number");
6730 }
6731 Operands.push_back(Elt: MipsOperand::createNumericReg(
6732 Index: RegNum, Str: Token.getString(), RegInfo: getContext().getRegisterInfo(), S,
6733 E: Token.getLoc(), Parser&: *this));
6734 return ParseStatus::Success;
6735 }
6736
6737 LLVM_DEBUG(dbgs() << Token.getKind() << "\n");
6738
6739 return ParseStatus::NoMatch;
6740}
6741
6742ParseStatus
6743MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
6744 auto Token = getLexer().peekTok(ShouldSkipSpace: false);
6745 return matchAnyRegisterWithoutDollar(Operands, Token, S);
6746}
6747
6748ParseStatus MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
6749 MCAsmParser &Parser = getParser();
6750 LLVM_DEBUG(dbgs() << "parseAnyRegister\n");
6751
6752 auto Token = Parser.getTok();
6753
6754 SMLoc S = Token.getLoc();
6755
6756 if (Token.isNot(K: AsmToken::Dollar)) {
6757 LLVM_DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
6758 if (Token.is(K: AsmToken::Identifier)) {
6759 if (searchSymbolAlias(Operands))
6760 return ParseStatus::Success;
6761 }
6762 LLVM_DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
6763 return ParseStatus::NoMatch;
6764 }
6765 LLVM_DEBUG(dbgs() << ".. $\n");
6766
6767 ParseStatus Res = matchAnyRegisterWithoutDollar(Operands, S);
6768 if (Res.isSuccess()) {
6769 Parser.Lex(); // $
6770 Parser.Lex(); // identifier
6771 }
6772 return Res;
6773}
6774
6775ParseStatus MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
6776 MCAsmParser &Parser = getParser();
6777 LLVM_DEBUG(dbgs() << "parseJumpTarget\n");
6778
6779 SMLoc S = getLexer().getLoc();
6780
6781 // Registers are a valid target and have priority over symbols.
6782 ParseStatus Res = parseAnyRegister(Operands);
6783 if (!Res.isNoMatch())
6784 return Res;
6785
6786 // Integers and expressions are acceptable
6787 const MCExpr *Expr = nullptr;
6788 if (Parser.parseExpression(Res&: Expr)) {
6789 // We have no way of knowing if a symbol was consumed so we must ParseFail
6790 return ParseStatus::Failure;
6791 }
6792 Operands.push_back(
6793 Elt: MipsOperand::CreateImm(Val: Expr, S, E: getLexer().getLoc(), Parser&: *this));
6794 return ParseStatus::Success;
6795}
6796
6797ParseStatus MipsAsmParser::parseInvNum(OperandVector &Operands) {
6798 MCAsmParser &Parser = getParser();
6799 const MCExpr *IdVal;
6800 // If the first token is '$' we may have register operand. We have to reject
6801 // cases where it is not a register. Complicating the matter is that
6802 // register names are not reserved across all ABIs.
6803 // Peek past the dollar to see if it's a register name for this ABI.
6804 SMLoc S = Parser.getTok().getLoc();
6805 if (Parser.getTok().is(K: AsmToken::Dollar)) {
6806 return matchCPURegisterName(Name: Parser.getLexer().peekTok().getString()) == -1
6807 ? ParseStatus::Failure
6808 : ParseStatus::NoMatch;
6809 }
6810 if (getParser().parseExpression(Res&: IdVal))
6811 return ParseStatus::Failure;
6812 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Val: IdVal);
6813 if (!MCE)
6814 return ParseStatus::NoMatch;
6815 int64_t Val = MCE->getValue();
6816 SMLoc E = SMLoc::getFromPointer(Ptr: Parser.getTok().getLoc().getPointer() - 1);
6817 Operands.push_back(Elt: MipsOperand::CreateImm(
6818 Val: MCConstantExpr::create(Value: 0 - Val, Ctx&: getContext()), S, E, Parser&: *this));
6819 return ParseStatus::Success;
6820}
6821
6822ParseStatus MipsAsmParser::parseRegisterList(OperandVector &Operands) {
6823 MCAsmParser &Parser = getParser();
6824 SmallVector<MCRegister, 10> Regs;
6825 MCRegister Reg;
6826 MCRegister PrevReg;
6827 bool RegRange = false;
6828 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
6829
6830 if (Parser.getTok().isNot(K: AsmToken::Dollar))
6831 return ParseStatus::Failure;
6832
6833 SMLoc S = Parser.getTok().getLoc();
6834 while (parseAnyRegister(Operands&: TmpOperands).isSuccess()) {
6835 SMLoc E = getLexer().getLoc();
6836 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*TmpOperands.back());
6837 Reg = isGP64bit() ? RegOpnd.getGPR64Reg() : RegOpnd.getGPR32Reg();
6838 if (RegRange) {
6839 // Remove last register operand because registers from register range
6840 // should be inserted first.
6841 if ((isGP64bit() && Reg == Mips::RA_64) ||
6842 (!isGP64bit() && Reg == Mips::RA)) {
6843 Regs.push_back(Elt: Reg);
6844 } else {
6845 MCRegister TmpReg = PrevReg + 1;
6846 while (TmpReg <= Reg) {
6847 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
6848 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
6849 isGP64bit()))
6850 return Error(L: E, Msg: "invalid register operand");
6851
6852 PrevReg = TmpReg;
6853 Regs.push_back(Elt: TmpReg);
6854 TmpReg = TmpReg.id() + 1;
6855 }
6856 }
6857
6858 RegRange = false;
6859 } else {
6860 if (!PrevReg.isValid() &&
6861 ((isGP64bit() && (Reg != Mips::S0_64) && (Reg != Mips::RA_64)) ||
6862 (!isGP64bit() && (Reg != Mips::S0) && (Reg != Mips::RA))))
6863 return Error(L: E, Msg: "$16 or $31 expected");
6864 if (!(((Reg == Mips::FP || Reg == Mips::RA ||
6865 (Reg >= Mips::S0 && Reg <= Mips::S7)) &&
6866 !isGP64bit()) ||
6867 ((Reg == Mips::FP_64 || Reg == Mips::RA_64 ||
6868 (Reg >= Mips::S0_64 && Reg <= Mips::S7_64)) &&
6869 isGP64bit())))
6870 return Error(L: E, Msg: "invalid register operand");
6871 if (PrevReg.isValid() && (Reg != PrevReg + 1) &&
6872 ((Reg != Mips::FP && Reg != Mips::RA && !isGP64bit()) ||
6873 (Reg != Mips::FP_64 && Reg != Mips::RA_64 && isGP64bit())))
6874 return Error(L: E, Msg: "consecutive register numbers expected");
6875
6876 Regs.push_back(Elt: Reg);
6877 }
6878
6879 if (Parser.getTok().is(K: AsmToken::Minus))
6880 RegRange = true;
6881
6882 if (!Parser.getTok().isNot(K: AsmToken::Minus) &&
6883 !Parser.getTok().isNot(K: AsmToken::Comma))
6884 return Error(L: E, Msg: "',' or '-' expected");
6885
6886 Lex(); // Consume comma or minus
6887 if (Parser.getTok().isNot(K: AsmToken::Dollar))
6888 break;
6889
6890 PrevReg = Reg;
6891 }
6892
6893 SMLoc E = Parser.getTok().getLoc();
6894 Operands.push_back(Elt: MipsOperand::CreateRegList(Regs, StartLoc: S, EndLoc: E, Parser&: *this));
6895 parseMemOperand(Operands);
6896 return ParseStatus::Success;
6897}
6898
6899/// Sometimes (i.e. load/stores) the operand may be followed immediately by
6900/// either this.
6901/// ::= '(', register, ')'
6902/// handle it before we iterate so we don't get tripped up by the lack of
6903/// a comma.
6904bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
6905 MCAsmParser &Parser = getParser();
6906 if (getLexer().is(K: AsmToken::LParen)) {
6907 Operands.push_back(
6908 Elt: MipsOperand::CreateToken(Str: "(", S: getLexer().getLoc(), Parser&: *this));
6909 Parser.Lex();
6910 if (parseOperand(Operands, Mnemonic: Name)) {
6911 SMLoc Loc = getLexer().getLoc();
6912 return Error(L: Loc, Msg: "unexpected token in argument list");
6913 }
6914 if (Parser.getTok().isNot(K: AsmToken::RParen)) {
6915 SMLoc Loc = getLexer().getLoc();
6916 return Error(L: Loc, Msg: "unexpected token, expected ')'");
6917 }
6918 Operands.push_back(
6919 Elt: MipsOperand::CreateToken(Str: ")", S: getLexer().getLoc(), Parser&: *this));
6920 Parser.Lex();
6921 }
6922 return false;
6923}
6924
6925/// Sometimes (i.e. in MSA) the operand may be followed immediately by
6926/// either one of these.
6927/// ::= '[', register, ']'
6928/// ::= '[', integer, ']'
6929/// handle it before we iterate so we don't get tripped up by the lack of
6930/// a comma.
6931bool MipsAsmParser::parseBracketSuffix(StringRef Name,
6932 OperandVector &Operands) {
6933 MCAsmParser &Parser = getParser();
6934 if (getLexer().is(K: AsmToken::LBrac)) {
6935 Operands.push_back(
6936 Elt: MipsOperand::CreateToken(Str: "[", S: getLexer().getLoc(), Parser&: *this));
6937 Parser.Lex();
6938 if (parseOperand(Operands, Mnemonic: Name)) {
6939 SMLoc Loc = getLexer().getLoc();
6940 return Error(L: Loc, Msg: "unexpected token in argument list");
6941 }
6942 if (Parser.getTok().isNot(K: AsmToken::RBrac)) {
6943 SMLoc Loc = getLexer().getLoc();
6944 return Error(L: Loc, Msg: "unexpected token, expected ']'");
6945 }
6946 Operands.push_back(
6947 Elt: MipsOperand::CreateToken(Str: "]", S: getLexer().getLoc(), Parser&: *this));
6948 Parser.Lex();
6949 }
6950 return false;
6951}
6952
6953static std::string MipsMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS,
6954 unsigned VariantID = 0);
6955
6956bool MipsAsmParser::areEqualRegs(const MCParsedAsmOperand &Op1,
6957 const MCParsedAsmOperand &Op2) const {
6958 // This target-overriden function exists to maintain current behaviour for
6959 // e.g.
6960 // dahi $3, $3, 0x5678
6961 // as tested in test/MC/Mips/mips64r6/valid.s.
6962 // FIXME: Should this test actually fail with an error? If so, then remove
6963 // this overloaded method.
6964 if (!Op1.isReg() || !Op2.isReg())
6965 return true;
6966 return Op1.getReg() == Op2.getReg();
6967}
6968
6969bool MipsAsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Name,
6970 SMLoc NameLoc, OperandVector &Operands) {
6971 MCAsmParser &Parser = getParser();
6972 LLVM_DEBUG(dbgs() << "parseInstruction\n");
6973
6974 // We have reached first instruction, module directive are now forbidden.
6975 getTargetStreamer().forbidModuleDirective();
6976
6977 // Check if we have valid mnemonic
6978 if (!mnemonicIsValid(Mnemonic: Name, VariantID: 0)) {
6979 FeatureBitset FBS = ComputeAvailableFeatures(FB: getSTI().getFeatureBits());
6980 std::string Suggestion = MipsMnemonicSpellCheck(S: Name, FBS);
6981 return Error(L: NameLoc, Msg: "unknown instruction" + Suggestion);
6982 }
6983 // First operand in MCInst is instruction mnemonic.
6984 Operands.push_back(Elt: MipsOperand::CreateToken(Str: Name, S: NameLoc, Parser&: *this));
6985
6986 // Read the remaining operands.
6987 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
6988 // Read the first operand.
6989 if (parseOperand(Operands, Mnemonic: Name)) {
6990 SMLoc Loc = getLexer().getLoc();
6991 return Error(L: Loc, Msg: "unexpected token in argument list");
6992 }
6993 if (getLexer().is(K: AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
6994 return true;
6995 // AFAIK, parenthesis suffixes are never on the first operand
6996
6997 while (getLexer().is(K: AsmToken::Comma)) {
6998 Parser.Lex(); // Eat the comma.
6999 // Parse and remember the operand.
7000 if (parseOperand(Operands, Mnemonic: Name)) {
7001 SMLoc Loc = getLexer().getLoc();
7002 return Error(L: Loc, Msg: "unexpected token in argument list");
7003 }
7004 // Parse bracket and parenthesis suffixes before we iterate
7005 if (getLexer().is(K: AsmToken::LBrac)) {
7006 if (parseBracketSuffix(Name, Operands))
7007 return true;
7008 } else if (getLexer().is(K: AsmToken::LParen) &&
7009 parseParenSuffix(Name, Operands))
7010 return true;
7011 }
7012 }
7013 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
7014 SMLoc Loc = getLexer().getLoc();
7015 return Error(L: Loc, Msg: "unexpected token in argument list");
7016 }
7017 Parser.Lex(); // Consume the EndOfStatement.
7018 return false;
7019}
7020
7021// FIXME: Given that these have the same name, these should both be
7022// consistent on affecting the Parser.
7023bool MipsAsmParser::reportParseError(const Twine &ErrorMsg) {
7024 SMLoc Loc = getLexer().getLoc();
7025 return Error(L: Loc, Msg: ErrorMsg);
7026}
7027
7028bool MipsAsmParser::reportParseError(SMLoc Loc, const Twine &ErrorMsg) {
7029 return Error(L: Loc, Msg: ErrorMsg);
7030}
7031
7032bool MipsAsmParser::parseSetNoAtDirective() {
7033 MCAsmParser &Parser = getParser();
7034 // Line should look like: ".set noat".
7035
7036 // Set the $at register to $0.
7037 AssemblerOptions.back()->setATRegIndex(0);
7038
7039 Parser.Lex(); // Eat "noat".
7040
7041 // If this is not the end of the statement, report an error.
7042 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
7043 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
7044 return false;
7045 }
7046
7047 getTargetStreamer().emitDirectiveSetNoAt();
7048 Parser.Lex(); // Consume the EndOfStatement.
7049 return false;
7050}
7051
7052bool MipsAsmParser::parseSetAtDirective() {
7053 // Line can be: ".set at", which sets $at to $1
7054 // or ".set at=$reg", which sets $at to $reg.
7055 MCAsmParser &Parser = getParser();
7056 Parser.Lex(); // Eat "at".
7057
7058 if (getLexer().is(K: AsmToken::EndOfStatement)) {
7059 // No register was specified, so we set $at to $1.
7060 AssemblerOptions.back()->setATRegIndex(1);
7061
7062 getTargetStreamer().emitDirectiveSetAt();
7063 Parser.Lex(); // Consume the EndOfStatement.
7064 return false;
7065 }
7066
7067 if (getLexer().isNot(K: AsmToken::Equal)) {
7068 reportParseError(ErrorMsg: "unexpected token, expected equals sign");
7069 return false;
7070 }
7071 Parser.Lex(); // Eat "=".
7072
7073 if (getLexer().isNot(K: AsmToken::Dollar)) {
7074 if (getLexer().is(K: AsmToken::EndOfStatement)) {
7075 reportParseError(ErrorMsg: "no register specified");
7076 return false;
7077 } else {
7078 reportParseError(ErrorMsg: "unexpected token, expected dollar sign '$'");
7079 return false;
7080 }
7081 }
7082 Parser.Lex(); // Eat "$".
7083
7084 // Find out what "reg" is.
7085 unsigned AtRegNo;
7086 const AsmToken &Reg = Parser.getTok();
7087 if (Reg.is(K: AsmToken::Identifier)) {
7088 AtRegNo = matchCPURegisterName(Name: Reg.getIdentifier());
7089 } else if (Reg.is(K: AsmToken::Integer)) {
7090 AtRegNo = Reg.getIntVal();
7091 } else {
7092 reportParseError(ErrorMsg: "unexpected token, expected identifier or integer");
7093 return false;
7094 }
7095
7096 // Check if $reg is a valid register. If it is, set $at to $reg.
7097 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
7098 reportParseError(ErrorMsg: "invalid register");
7099 return false;
7100 }
7101 Parser.Lex(); // Eat "reg".
7102
7103 // If this is not the end of the statement, report an error.
7104 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
7105 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
7106 return false;
7107 }
7108
7109 getTargetStreamer().emitDirectiveSetAtWithArg(RegNo: AtRegNo);
7110
7111 Parser.Lex(); // Consume the EndOfStatement.
7112 return false;
7113}
7114
7115bool MipsAsmParser::parseSetReorderDirective() {
7116 MCAsmParser &Parser = getParser();
7117 Parser.Lex();
7118 // If this is not the end of the statement, report an error.
7119 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
7120 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
7121 return false;
7122 }
7123 AssemblerOptions.back()->setReorder();
7124 getTargetStreamer().emitDirectiveSetReorder();
7125 Parser.Lex(); // Consume the EndOfStatement.
7126 return false;
7127}
7128
7129bool MipsAsmParser::parseSetNoReorderDirective() {
7130 MCAsmParser &Parser = getParser();
7131 Parser.Lex();
7132 // If this is not the end of the statement, report an error.
7133 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
7134 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
7135 return false;
7136 }
7137 AssemblerOptions.back()->setNoReorder();
7138 getTargetStreamer().emitDirectiveSetNoReorder();
7139 Parser.Lex(); // Consume the EndOfStatement.
7140 return false;
7141}
7142
7143bool MipsAsmParser::parseSetMacroDirective() {
7144 MCAsmParser &Parser = getParser();
7145 Parser.Lex();
7146 // If this is not the end of the statement, report an error.
7147 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
7148 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
7149 return false;
7150 }
7151 AssemblerOptions.back()->setMacro();
7152 getTargetStreamer().emitDirectiveSetMacro();
7153 Parser.Lex(); // Consume the EndOfStatement.
7154 return false;
7155}
7156
7157bool MipsAsmParser::parseSetNoMacroDirective() {
7158 MCAsmParser &Parser = getParser();
7159 Parser.Lex();
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 if (AssemblerOptions.back()->isReorder()) {
7166 reportParseError(ErrorMsg: "`noreorder' must be set before `nomacro'");
7167 return false;
7168 }
7169 AssemblerOptions.back()->setNoMacro();
7170 getTargetStreamer().emitDirectiveSetNoMacro();
7171 Parser.Lex(); // Consume the EndOfStatement.
7172 return false;
7173}
7174
7175bool MipsAsmParser::parseSetMsaDirective() {
7176 MCAsmParser &Parser = getParser();
7177 Parser.Lex();
7178
7179 // If this is not the end of the statement, report an error.
7180 if (getLexer().isNot(K: AsmToken::EndOfStatement))
7181 return reportParseError(ErrorMsg: "unexpected token, expected end of statement");
7182
7183 setFeatureBits(Feature: Mips::FeatureMSA, FeatureString: "msa");
7184 getTargetStreamer().emitDirectiveSetMsa();
7185 return false;
7186}
7187
7188bool MipsAsmParser::parseSetNoMsaDirective() {
7189 MCAsmParser &Parser = getParser();
7190 Parser.Lex();
7191
7192 // If this is not the end of the statement, report an error.
7193 if (getLexer().isNot(K: AsmToken::EndOfStatement))
7194 return reportParseError(ErrorMsg: "unexpected token, expected end of statement");
7195
7196 clearFeatureBits(Feature: Mips::FeatureMSA, FeatureString: "msa");
7197 getTargetStreamer().emitDirectiveSetNoMsa();
7198 return false;
7199}
7200
7201bool MipsAsmParser::parseSetNoDspDirective() {
7202 MCAsmParser &Parser = getParser();
7203 Parser.Lex(); // Eat "nodsp".
7204
7205 // If this is not the end of the statement, report an error.
7206 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
7207 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
7208 return false;
7209 }
7210
7211 clearFeatureBits(Feature: Mips::FeatureDSP, FeatureString: "dsp");
7212 getTargetStreamer().emitDirectiveSetNoDsp();
7213 return false;
7214}
7215
7216bool MipsAsmParser::parseSetNoMips3DDirective() {
7217 MCAsmParser &Parser = getParser();
7218 Parser.Lex(); // Eat "nomips3d".
7219
7220 // If this is not the end of the statement, report an error.
7221 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
7222 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
7223 return false;
7224 }
7225
7226 clearFeatureBits(Feature: Mips::FeatureMips3D, FeatureString: "mips3d");
7227 getTargetStreamer().emitDirectiveSetNoMips3D();
7228 return false;
7229}
7230
7231bool MipsAsmParser::parseSetMips16Directive() {
7232 MCAsmParser &Parser = getParser();
7233 Parser.Lex(); // Eat "mips16".
7234
7235 // If this is not the end of the statement, report an error.
7236 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
7237 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
7238 return false;
7239 }
7240
7241 setFeatureBits(Feature: Mips::FeatureMips16, FeatureString: "mips16");
7242 getTargetStreamer().emitDirectiveSetMips16();
7243 Parser.Lex(); // Consume the EndOfStatement.
7244 return false;
7245}
7246
7247bool MipsAsmParser::parseSetNoMips16Directive() {
7248 MCAsmParser &Parser = getParser();
7249 Parser.Lex(); // Eat "nomips16".
7250
7251 // If this is not the end of the statement, report an error.
7252 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
7253 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
7254 return false;
7255 }
7256
7257 clearFeatureBits(Feature: Mips::FeatureMips16, FeatureString: "mips16");
7258 getTargetStreamer().emitDirectiveSetNoMips16();
7259 Parser.Lex(); // Consume the EndOfStatement.
7260 return false;
7261}
7262
7263bool MipsAsmParser::parseSetFpDirective() {
7264 MCAsmParser &Parser = getParser();
7265 MipsABIFlagsSection::FpABIKind FpAbiVal;
7266 // Line can be: .set fp=32
7267 // .set fp=xx
7268 // .set fp=64
7269 Parser.Lex(); // Eat fp token
7270 AsmToken Tok = Parser.getTok();
7271 if (Tok.isNot(K: AsmToken::Equal)) {
7272 reportParseError(ErrorMsg: "unexpected token, expected equals sign '='");
7273 return false;
7274 }
7275 Parser.Lex(); // Eat '=' token.
7276 Tok = Parser.getTok();
7277
7278 if (!parseFpABIValue(FpABI&: FpAbiVal, Directive: ".set"))
7279 return false;
7280
7281 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
7282 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
7283 return false;
7284 }
7285 getTargetStreamer().emitDirectiveSetFp(Value: FpAbiVal);
7286 Parser.Lex(); // Consume the EndOfStatement.
7287 return false;
7288}
7289
7290bool MipsAsmParser::parseSetOddSPRegDirective() {
7291 MCAsmParser &Parser = getParser();
7292
7293 Parser.Lex(); // Eat "oddspreg".
7294 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
7295 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
7296 return false;
7297 }
7298
7299 clearFeatureBits(Feature: Mips::FeatureNoOddSPReg, FeatureString: "nooddspreg");
7300 getTargetStreamer().emitDirectiveSetOddSPReg();
7301 return false;
7302}
7303
7304bool MipsAsmParser::parseSetNoOddSPRegDirective() {
7305 MCAsmParser &Parser = getParser();
7306
7307 Parser.Lex(); // Eat "nooddspreg".
7308 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
7309 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
7310 return false;
7311 }
7312
7313 setFeatureBits(Feature: Mips::FeatureNoOddSPReg, FeatureString: "nooddspreg");
7314 getTargetStreamer().emitDirectiveSetNoOddSPReg();
7315 return false;
7316}
7317
7318bool MipsAsmParser::parseSetMtDirective() {
7319 MCAsmParser &Parser = getParser();
7320 Parser.Lex(); // Eat "mt".
7321
7322 // If this is not the end of the statement, report an error.
7323 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
7324 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
7325 return false;
7326 }
7327
7328 setFeatureBits(Feature: Mips::FeatureMT, FeatureString: "mt");
7329 getTargetStreamer().emitDirectiveSetMt();
7330 Parser.Lex(); // Consume the EndOfStatement.
7331 return false;
7332}
7333
7334bool MipsAsmParser::parseSetNoMtDirective() {
7335 MCAsmParser &Parser = getParser();
7336 Parser.Lex(); // Eat "nomt".
7337
7338 // If this is not the end of the statement, report an error.
7339 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
7340 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
7341 return false;
7342 }
7343
7344 clearFeatureBits(Feature: Mips::FeatureMT, FeatureString: "mt");
7345
7346 getTargetStreamer().emitDirectiveSetNoMt();
7347 Parser.Lex(); // Consume the EndOfStatement.
7348 return false;
7349}
7350
7351bool MipsAsmParser::parseSetNoCRCDirective() {
7352 MCAsmParser &Parser = getParser();
7353 Parser.Lex(); // Eat "nocrc".
7354
7355 // If this is not the end of the statement, report an error.
7356 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
7357 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
7358 return false;
7359 }
7360
7361 clearFeatureBits(Feature: Mips::FeatureCRC, FeatureString: "crc");
7362
7363 getTargetStreamer().emitDirectiveSetNoCRC();
7364 Parser.Lex(); // Consume the EndOfStatement.
7365 return false;
7366}
7367
7368bool MipsAsmParser::parseSetNoVirtDirective() {
7369 MCAsmParser &Parser = getParser();
7370 Parser.Lex(); // Eat "novirt".
7371
7372 // If this is not the end of the statement, report an error.
7373 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
7374 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
7375 return false;
7376 }
7377
7378 clearFeatureBits(Feature: Mips::FeatureVirt, FeatureString: "virt");
7379
7380 getTargetStreamer().emitDirectiveSetNoVirt();
7381 Parser.Lex(); // Consume the EndOfStatement.
7382 return false;
7383}
7384
7385bool MipsAsmParser::parseSetNoGINVDirective() {
7386 MCAsmParser &Parser = getParser();
7387 Parser.Lex(); // Eat "noginv".
7388
7389 // If this is not the end of the statement, report an error.
7390 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
7391 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
7392 return false;
7393 }
7394
7395 clearFeatureBits(Feature: Mips::FeatureGINV, FeatureString: "ginv");
7396
7397 getTargetStreamer().emitDirectiveSetNoGINV();
7398 Parser.Lex(); // Consume the EndOfStatement.
7399 return false;
7400}
7401
7402bool MipsAsmParser::parseSetPopDirective() {
7403 MCAsmParser &Parser = getParser();
7404 SMLoc Loc = getLexer().getLoc();
7405
7406 Parser.Lex();
7407 if (getLexer().isNot(K: AsmToken::EndOfStatement))
7408 return reportParseError(ErrorMsg: "unexpected token, expected end of statement");
7409
7410 // Always keep an element on the options "stack" to prevent the user
7411 // from changing the initial options. This is how we remember them.
7412 if (AssemblerOptions.size() == 2)
7413 return reportParseError(Loc, ErrorMsg: ".set pop with no .set push");
7414
7415 MCSubtargetInfo &STI = copySTI();
7416 AssemblerOptions.pop_back();
7417 setAvailableFeatures(
7418 ComputeAvailableFeatures(FB: AssemblerOptions.back()->getFeatures()));
7419 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
7420
7421 getTargetStreamer().emitDirectiveSetPop();
7422 return false;
7423}
7424
7425bool MipsAsmParser::parseSetPushDirective() {
7426 MCAsmParser &Parser = getParser();
7427 Parser.Lex();
7428 if (getLexer().isNot(K: AsmToken::EndOfStatement))
7429 return reportParseError(ErrorMsg: "unexpected token, expected end of statement");
7430
7431 // Create a copy of the current assembler options environment and push it.
7432 AssemblerOptions.push_back(
7433 Elt: std::make_unique<MipsAssemblerOptions>(args: AssemblerOptions.back().get()));
7434
7435 getTargetStreamer().emitDirectiveSetPush();
7436 return false;
7437}
7438
7439bool MipsAsmParser::parseSetSoftFloatDirective() {
7440 MCAsmParser &Parser = getParser();
7441 Parser.Lex();
7442 if (getLexer().isNot(K: AsmToken::EndOfStatement))
7443 return reportParseError(ErrorMsg: "unexpected token, expected end of statement");
7444
7445 setFeatureBits(Feature: Mips::FeatureSoftFloat, FeatureString: "soft-float");
7446 getTargetStreamer().emitDirectiveSetSoftFloat();
7447 return false;
7448}
7449
7450bool MipsAsmParser::parseSetHardFloatDirective() {
7451 MCAsmParser &Parser = getParser();
7452 Parser.Lex();
7453 if (getLexer().isNot(K: AsmToken::EndOfStatement))
7454 return reportParseError(ErrorMsg: "unexpected token, expected end of statement");
7455
7456 clearFeatureBits(Feature: Mips::FeatureSoftFloat, FeatureString: "soft-float");
7457 getTargetStreamer().emitDirectiveSetHardFloat();
7458 return false;
7459}
7460
7461bool MipsAsmParser::parseSetAssignment() {
7462 StringRef Name;
7463 MCAsmParser &Parser = getParser();
7464
7465 if (Parser.parseIdentifier(Res&: Name))
7466 return reportParseError(ErrorMsg: "expected identifier after .set");
7467
7468 if (getLexer().isNot(K: AsmToken::Comma))
7469 return reportParseError(ErrorMsg: "unexpected token, expected comma");
7470 Lex(); // Eat comma
7471
7472 if (getLexer().is(K: AsmToken::Dollar) &&
7473 getLexer().peekTok().is(K: AsmToken::Integer)) {
7474 // Parse assignment of a numeric register:
7475 // .set r1,$1
7476 Parser.Lex(); // Eat $.
7477 RegisterSets[Name] = Parser.getTok();
7478 Parser.Lex(); // Eat identifier.
7479 getContext().getOrCreateSymbol(Name);
7480 return false;
7481 }
7482
7483 MCSymbol *Sym;
7484 const MCExpr *Value;
7485 if (MCParserUtils::parseAssignmentExpression(Name, /* allow_redef */ true,
7486 Parser, Symbol&: Sym, Value))
7487 return true;
7488 getStreamer().emitAssignment(Symbol: Sym, Value);
7489
7490 return false;
7491}
7492
7493bool MipsAsmParser::parseSetMips0Directive() {
7494 MCAsmParser &Parser = getParser();
7495 Parser.Lex();
7496 if (getLexer().isNot(K: AsmToken::EndOfStatement))
7497 return reportParseError(ErrorMsg: "unexpected token, expected end of statement");
7498
7499 // Reset assembler options to their initial values.
7500 MCSubtargetInfo &STI = copySTI();
7501 setAvailableFeatures(
7502 ComputeAvailableFeatures(FB: AssemblerOptions.front()->getFeatures()));
7503 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
7504 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
7505
7506 getTargetStreamer().emitDirectiveSetMips0();
7507 return false;
7508}
7509
7510bool MipsAsmParser::parseSetArchDirective() {
7511 MCAsmParser &Parser = getParser();
7512 Parser.Lex();
7513 if (getLexer().isNot(K: AsmToken::Equal))
7514 return reportParseError(ErrorMsg: "unexpected token, expected equals sign");
7515
7516 Parser.Lex();
7517 StringRef Arch = getParser().parseStringToEndOfStatement().trim();
7518 if (Arch.empty())
7519 return reportParseError(ErrorMsg: "expected arch identifier");
7520
7521 StringRef ArchFeatureName =
7522 StringSwitch<StringRef>(Arch)
7523 .Case(S: "mips1", Value: "mips1")
7524 .Case(S: "mips2", Value: "mips2")
7525 .Case(S: "mips3", Value: "mips3")
7526 .Case(S: "mips4", Value: "mips4")
7527 .Case(S: "mips5", Value: "mips5")
7528 .Case(S: "mips32", Value: "mips32")
7529 .Case(S: "mips32r2", Value: "mips32r2")
7530 .Case(S: "mips32r3", Value: "mips32r3")
7531 .Case(S: "mips32r5", Value: "mips32r5")
7532 .Case(S: "mips32r6", Value: "mips32r6")
7533 .Case(S: "mips64", Value: "mips64")
7534 .Case(S: "mips64r2", Value: "mips64r2")
7535 .Case(S: "mips64r3", Value: "mips64r3")
7536 .Case(S: "mips64r5", Value: "mips64r5")
7537 .Case(S: "mips64r6", Value: "mips64r6")
7538 .Case(S: "octeon", Value: "cnmips")
7539 .Case(S: "octeon+", Value: "cnmipsp")
7540 .Case(S: "r4000", Value: "mips3") // This is an implementation of Mips3.
7541 .Default(Value: "");
7542
7543 if (ArchFeatureName.empty())
7544 return reportParseError(ErrorMsg: "unsupported architecture");
7545
7546 if (ArchFeatureName == "mips64r6" && inMicroMipsMode())
7547 return reportParseError(ErrorMsg: "mips64r6 does not support microMIPS");
7548
7549 selectArch(ArchFeature: ArchFeatureName);
7550 getTargetStreamer().emitDirectiveSetArch(Arch);
7551 return false;
7552}
7553
7554bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
7555 MCAsmParser &Parser = getParser();
7556 Parser.Lex();
7557 if (getLexer().isNot(K: AsmToken::EndOfStatement))
7558 return reportParseError(ErrorMsg: "unexpected token, expected end of statement");
7559
7560 switch (Feature) {
7561 default:
7562 llvm_unreachable("Unimplemented feature");
7563 case Mips::FeatureMips3D:
7564 setFeatureBits(Feature: Mips::FeatureMips3D, FeatureString: "mips3d");
7565 getTargetStreamer().emitDirectiveSetMips3D();
7566 break;
7567 case Mips::FeatureDSP:
7568 setFeatureBits(Feature: Mips::FeatureDSP, FeatureString: "dsp");
7569 getTargetStreamer().emitDirectiveSetDsp();
7570 break;
7571 case Mips::FeatureDSPR2:
7572 setFeatureBits(Feature: Mips::FeatureDSPR2, FeatureString: "dspr2");
7573 getTargetStreamer().emitDirectiveSetDspr2();
7574 break;
7575 case Mips::FeatureMicroMips:
7576 setFeatureBits(Feature: Mips::FeatureMicroMips, FeatureString: "micromips");
7577 getTargetStreamer().emitDirectiveSetMicroMips();
7578 break;
7579 case Mips::FeatureMips1:
7580 selectArch(ArchFeature: "mips1");
7581 getTargetStreamer().emitDirectiveSetMips1();
7582 break;
7583 case Mips::FeatureMips2:
7584 selectArch(ArchFeature: "mips2");
7585 getTargetStreamer().emitDirectiveSetMips2();
7586 break;
7587 case Mips::FeatureMips3:
7588 selectArch(ArchFeature: "mips3");
7589 getTargetStreamer().emitDirectiveSetMips3();
7590 break;
7591 case Mips::FeatureMips4:
7592 selectArch(ArchFeature: "mips4");
7593 getTargetStreamer().emitDirectiveSetMips4();
7594 break;
7595 case Mips::FeatureMips5:
7596 selectArch(ArchFeature: "mips5");
7597 getTargetStreamer().emitDirectiveSetMips5();
7598 break;
7599 case Mips::FeatureMips32:
7600 selectArch(ArchFeature: "mips32");
7601 getTargetStreamer().emitDirectiveSetMips32();
7602 break;
7603 case Mips::FeatureMips32r2:
7604 selectArch(ArchFeature: "mips32r2");
7605 getTargetStreamer().emitDirectiveSetMips32R2();
7606 break;
7607 case Mips::FeatureMips32r3:
7608 selectArch(ArchFeature: "mips32r3");
7609 getTargetStreamer().emitDirectiveSetMips32R3();
7610 break;
7611 case Mips::FeatureMips32r5:
7612 selectArch(ArchFeature: "mips32r5");
7613 getTargetStreamer().emitDirectiveSetMips32R5();
7614 break;
7615 case Mips::FeatureMips32r6:
7616 selectArch(ArchFeature: "mips32r6");
7617 getTargetStreamer().emitDirectiveSetMips32R6();
7618 break;
7619 case Mips::FeatureMips64:
7620 selectArch(ArchFeature: "mips64");
7621 getTargetStreamer().emitDirectiveSetMips64();
7622 break;
7623 case Mips::FeatureMips64r2:
7624 selectArch(ArchFeature: "mips64r2");
7625 getTargetStreamer().emitDirectiveSetMips64R2();
7626 break;
7627 case Mips::FeatureMips64r3:
7628 selectArch(ArchFeature: "mips64r3");
7629 getTargetStreamer().emitDirectiveSetMips64R3();
7630 break;
7631 case Mips::FeatureMips64r5:
7632 selectArch(ArchFeature: "mips64r5");
7633 getTargetStreamer().emitDirectiveSetMips64R5();
7634 break;
7635 case Mips::FeatureMips64r6:
7636 selectArch(ArchFeature: "mips64r6");
7637 getTargetStreamer().emitDirectiveSetMips64R6();
7638 break;
7639 case Mips::FeatureCRC:
7640 setFeatureBits(Feature: Mips::FeatureCRC, FeatureString: "crc");
7641 getTargetStreamer().emitDirectiveSetCRC();
7642 break;
7643 case Mips::FeatureVirt:
7644 setFeatureBits(Feature: Mips::FeatureVirt, FeatureString: "virt");
7645 getTargetStreamer().emitDirectiveSetVirt();
7646 break;
7647 case Mips::FeatureGINV:
7648 setFeatureBits(Feature: Mips::FeatureGINV, FeatureString: "ginv");
7649 getTargetStreamer().emitDirectiveSetGINV();
7650 break;
7651 }
7652 return false;
7653}
7654
7655bool MipsAsmParser::eatComma(StringRef ErrorStr) {
7656 MCAsmParser &Parser = getParser();
7657 if (getLexer().isNot(K: AsmToken::Comma)) {
7658 SMLoc Loc = getLexer().getLoc();
7659 return Error(L: Loc, Msg: ErrorStr);
7660 }
7661
7662 Parser.Lex(); // Eat the comma.
7663 return true;
7664}
7665
7666// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
7667// In this class, it is only used for .cprestore.
7668// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
7669// MipsTargetELFStreamer and MipsAsmParser.
7670bool MipsAsmParser::isPicAndNotNxxAbi() {
7671 return inPicMode() && !(isABI_N32() || isABI_N64());
7672}
7673
7674bool MipsAsmParser::parseDirectiveCpAdd(SMLoc Loc) {
7675 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
7676 ParseStatus Res = parseAnyRegister(Operands&: Reg);
7677 if (Res.isNoMatch() || Res.isFailure()) {
7678 reportParseError(ErrorMsg: "expected register");
7679 return false;
7680 }
7681
7682 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
7683 if (!RegOpnd.isGPRAsmReg()) {
7684 reportParseError(Loc: RegOpnd.getStartLoc(), ErrorMsg: "invalid register");
7685 return false;
7686 }
7687
7688 // If this is not the end of the statement, report an error.
7689 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
7690 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
7691 return false;
7692 }
7693 getParser().Lex(); // Consume the EndOfStatement.
7694
7695 getTargetStreamer().emitDirectiveCpAdd(Reg: RegOpnd.getGPR32Reg());
7696 return false;
7697}
7698
7699bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
7700 if (AssemblerOptions.back()->isReorder())
7701 Warning(L: Loc, Msg: ".cpload should be inside a noreorder section");
7702
7703 if (inMips16Mode()) {
7704 reportParseError(ErrorMsg: ".cpload is not supported in Mips16 mode");
7705 return false;
7706 }
7707
7708 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
7709 ParseStatus Res = parseAnyRegister(Operands&: Reg);
7710 if (Res.isNoMatch() || Res.isFailure()) {
7711 reportParseError(ErrorMsg: "expected register containing function address");
7712 return false;
7713 }
7714
7715 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
7716 if (!RegOpnd.isGPRAsmReg()) {
7717 reportParseError(Loc: RegOpnd.getStartLoc(), ErrorMsg: "invalid register");
7718 return false;
7719 }
7720
7721 // If this is not the end of the statement, report an error.
7722 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
7723 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
7724 return false;
7725 }
7726
7727 getTargetStreamer().emitDirectiveCpLoad(Reg: RegOpnd.getGPR32Reg());
7728 return false;
7729}
7730
7731bool MipsAsmParser::parseDirectiveCpLocal(SMLoc Loc) {
7732 if (!isABI_N32() && !isABI_N64()) {
7733 reportParseError(ErrorMsg: ".cplocal is allowed only in N32 or N64 mode");
7734 return false;
7735 }
7736
7737 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
7738 ParseStatus Res = parseAnyRegister(Operands&: Reg);
7739 if (Res.isNoMatch() || Res.isFailure()) {
7740 reportParseError(ErrorMsg: "expected register containing global pointer");
7741 return false;
7742 }
7743
7744 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
7745 if (!RegOpnd.isGPRAsmReg()) {
7746 reportParseError(Loc: RegOpnd.getStartLoc(), ErrorMsg: "invalid register");
7747 return false;
7748 }
7749
7750 // If this is not the end of the statement, report an error.
7751 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
7752 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
7753 return false;
7754 }
7755 getParser().Lex(); // Consume the EndOfStatement.
7756
7757 MCRegister NewReg = RegOpnd.getGPR32Reg();
7758 if (IsPicEnabled)
7759 GPReg = NewReg;
7760
7761 getTargetStreamer().emitDirectiveCpLocal(Reg: NewReg);
7762 return false;
7763}
7764
7765bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
7766 MCAsmParser &Parser = getParser();
7767
7768 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
7769 // is used in non-PIC mode.
7770
7771 if (inMips16Mode()) {
7772 reportParseError(ErrorMsg: ".cprestore is not supported in Mips16 mode");
7773 return false;
7774 }
7775
7776 // Get the stack offset value.
7777 const MCExpr *StackOffset;
7778 int64_t StackOffsetVal;
7779 if (Parser.parseExpression(Res&: StackOffset)) {
7780 reportParseError(ErrorMsg: "expected stack offset value");
7781 return false;
7782 }
7783
7784 if (!StackOffset->evaluateAsAbsolute(Res&: StackOffsetVal)) {
7785 reportParseError(ErrorMsg: "stack offset is not an absolute expression");
7786 return false;
7787 }
7788
7789 if (StackOffsetVal < 0) {
7790 Warning(L: Loc, Msg: ".cprestore with negative stack offset has no effect");
7791 IsCpRestoreSet = false;
7792 } else {
7793 IsCpRestoreSet = true;
7794 CpRestoreOffset = StackOffsetVal;
7795 }
7796
7797 // If this is not the end of the statement, report an error.
7798 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
7799 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
7800 return false;
7801 }
7802
7803 if (!getTargetStreamer().emitDirectiveCpRestore(
7804 Offset: CpRestoreOffset, GetATReg: [&]() { return getATReg(Loc); }, IDLoc: Loc, STI))
7805 return true;
7806 Parser.Lex(); // Consume the EndOfStatement.
7807 return false;
7808}
7809
7810bool MipsAsmParser::parseDirectiveCPSetup() {
7811 MCAsmParser &Parser = getParser();
7812 unsigned Save;
7813 bool SaveIsReg = true;
7814
7815 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
7816 ParseStatus Res = parseAnyRegister(Operands&: TmpReg);
7817 if (Res.isNoMatch()) {
7818 reportParseError(ErrorMsg: "expected register containing function address");
7819 return false;
7820 }
7821
7822 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7823 if (!FuncRegOpnd.isGPRAsmReg()) {
7824 reportParseError(Loc: FuncRegOpnd.getStartLoc(), ErrorMsg: "invalid register");
7825 return false;
7826 }
7827
7828 MCRegister FuncReg = FuncRegOpnd.getGPR32Reg();
7829 TmpReg.clear();
7830
7831 if (!eatComma(ErrorStr: "unexpected token, expected comma"))
7832 return true;
7833
7834 Res = parseAnyRegister(Operands&: TmpReg);
7835 if (Res.isNoMatch()) {
7836 const MCExpr *OffsetExpr;
7837 int64_t OffsetVal;
7838 SMLoc ExprLoc = getLexer().getLoc();
7839
7840 if (Parser.parseExpression(Res&: OffsetExpr) ||
7841 !OffsetExpr->evaluateAsAbsolute(Res&: OffsetVal)) {
7842 reportParseError(Loc: ExprLoc, ErrorMsg: "expected save register or stack offset");
7843 return false;
7844 }
7845
7846 Save = OffsetVal;
7847 SaveIsReg = false;
7848 } else {
7849 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7850 if (!SaveOpnd.isGPRAsmReg()) {
7851 reportParseError(Loc: SaveOpnd.getStartLoc(), ErrorMsg: "invalid register");
7852 return false;
7853 }
7854 Save = SaveOpnd.getGPR32Reg().id();
7855 }
7856
7857 if (!eatComma(ErrorStr: "unexpected token, expected comma"))
7858 return true;
7859
7860 const MCExpr *Expr;
7861 if (Parser.parseExpression(Res&: Expr)) {
7862 reportParseError(ErrorMsg: "expected expression");
7863 return false;
7864 }
7865
7866 if (Expr->getKind() != MCExpr::SymbolRef) {
7867 reportParseError(ErrorMsg: "expected symbol");
7868 return false;
7869 }
7870 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
7871
7872 CpSaveLocation = Save;
7873 CpSaveLocationIsRegister = SaveIsReg;
7874
7875 getTargetStreamer().emitDirectiveCpsetup(Reg: FuncReg, RegOrOffset: Save, Sym: Ref->getSymbol(),
7876 IsReg: SaveIsReg);
7877 return false;
7878}
7879
7880bool MipsAsmParser::parseDirectiveCPReturn() {
7881 getTargetStreamer().emitDirectiveCpreturn(SaveLocation: CpSaveLocation,
7882 SaveLocationIsRegister: CpSaveLocationIsRegister);
7883 return false;
7884}
7885
7886bool MipsAsmParser::parseDirectiveNaN() {
7887 MCAsmParser &Parser = getParser();
7888 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
7889 const AsmToken &Tok = Parser.getTok();
7890
7891 if (Tok.getString() == "2008") {
7892 Parser.Lex();
7893 getTargetStreamer().emitDirectiveNaN2008();
7894 return false;
7895 } else if (Tok.getString() == "legacy") {
7896 Parser.Lex();
7897 getTargetStreamer().emitDirectiveNaNLegacy();
7898 return false;
7899 }
7900 }
7901 // If we don't recognize the option passed to the .nan
7902 // directive (e.g. no option or unknown option), emit an error.
7903 reportParseError(ErrorMsg: "invalid option in .nan directive");
7904 return false;
7905}
7906
7907bool MipsAsmParser::parseDirectiveSet() {
7908 const AsmToken &Tok = getParser().getTok();
7909 StringRef IdVal = Tok.getString();
7910 SMLoc Loc = Tok.getLoc();
7911
7912 if (IdVal == "noat")
7913 return parseSetNoAtDirective();
7914 if (IdVal == "at")
7915 return parseSetAtDirective();
7916 if (IdVal == "arch")
7917 return parseSetArchDirective();
7918 if (IdVal == "bopt") {
7919 Warning(L: Loc, Msg: "'bopt' feature is unsupported");
7920 getParser().Lex();
7921 return false;
7922 }
7923 if (IdVal == "nobopt") {
7924 // We're already running in nobopt mode, so nothing to do.
7925 getParser().Lex();
7926 return false;
7927 }
7928 if (IdVal == "fp")
7929 return parseSetFpDirective();
7930 if (IdVal == "oddspreg")
7931 return parseSetOddSPRegDirective();
7932 if (IdVal == "nooddspreg")
7933 return parseSetNoOddSPRegDirective();
7934 if (IdVal == "pop")
7935 return parseSetPopDirective();
7936 if (IdVal == "push")
7937 return parseSetPushDirective();
7938 if (IdVal == "reorder")
7939 return parseSetReorderDirective();
7940 if (IdVal == "noreorder")
7941 return parseSetNoReorderDirective();
7942 if (IdVal == "macro")
7943 return parseSetMacroDirective();
7944 if (IdVal == "nomacro")
7945 return parseSetNoMacroDirective();
7946 if (IdVal == "mips16")
7947 return parseSetMips16Directive();
7948 if (IdVal == "nomips16")
7949 return parseSetNoMips16Directive();
7950 if (IdVal == "nomicromips") {
7951 clearFeatureBits(Feature: Mips::FeatureMicroMips, FeatureString: "micromips");
7952 getTargetStreamer().emitDirectiveSetNoMicroMips();
7953 getParser().eatToEndOfStatement();
7954 return false;
7955 }
7956 if (IdVal == "micromips") {
7957 if (hasMips64r6()) {
7958 Error(L: Loc, Msg: ".set micromips directive is not supported with MIPS64R6");
7959 return false;
7960 }
7961 return parseSetFeature(Feature: Mips::FeatureMicroMips);
7962 }
7963 if (IdVal == "mips0")
7964 return parseSetMips0Directive();
7965 if (IdVal == "mips1")
7966 return parseSetFeature(Feature: Mips::FeatureMips1);
7967 if (IdVal == "mips2")
7968 return parseSetFeature(Feature: Mips::FeatureMips2);
7969 if (IdVal == "mips3")
7970 return parseSetFeature(Feature: Mips::FeatureMips3);
7971 if (IdVal == "mips4")
7972 return parseSetFeature(Feature: Mips::FeatureMips4);
7973 if (IdVal == "mips5")
7974 return parseSetFeature(Feature: Mips::FeatureMips5);
7975 if (IdVal == "mips32")
7976 return parseSetFeature(Feature: Mips::FeatureMips32);
7977 if (IdVal == "mips32r2")
7978 return parseSetFeature(Feature: Mips::FeatureMips32r2);
7979 if (IdVal == "mips32r3")
7980 return parseSetFeature(Feature: Mips::FeatureMips32r3);
7981 if (IdVal == "mips32r5")
7982 return parseSetFeature(Feature: Mips::FeatureMips32r5);
7983 if (IdVal == "mips32r6")
7984 return parseSetFeature(Feature: Mips::FeatureMips32r6);
7985 if (IdVal == "mips64")
7986 return parseSetFeature(Feature: Mips::FeatureMips64);
7987 if (IdVal == "mips64r2")
7988 return parseSetFeature(Feature: Mips::FeatureMips64r2);
7989 if (IdVal == "mips64r3")
7990 return parseSetFeature(Feature: Mips::FeatureMips64r3);
7991 if (IdVal == "mips64r5")
7992 return parseSetFeature(Feature: Mips::FeatureMips64r5);
7993 if (IdVal == "mips64r6") {
7994 if (inMicroMipsMode()) {
7995 Error(L: Loc, Msg: "MIPS64R6 is not supported with microMIPS");
7996 return false;
7997 }
7998 return parseSetFeature(Feature: Mips::FeatureMips64r6);
7999 }
8000 if (IdVal == "dsp")
8001 return parseSetFeature(Feature: Mips::FeatureDSP);
8002 if (IdVal == "dspr2")
8003 return parseSetFeature(Feature: Mips::FeatureDSPR2);
8004 if (IdVal == "nodsp")
8005 return parseSetNoDspDirective();
8006 if (IdVal == "mips3d")
8007 return parseSetFeature(Feature: Mips::FeatureMips3D);
8008 if (IdVal == "nomips3d")
8009 return parseSetNoMips3DDirective();
8010 if (IdVal == "msa")
8011 return parseSetMsaDirective();
8012 if (IdVal == "nomsa")
8013 return parseSetNoMsaDirective();
8014 if (IdVal == "mt")
8015 return parseSetMtDirective();
8016 if (IdVal == "nomt")
8017 return parseSetNoMtDirective();
8018 if (IdVal == "softfloat")
8019 return parseSetSoftFloatDirective();
8020 if (IdVal == "hardfloat")
8021 return parseSetHardFloatDirective();
8022 if (IdVal == "crc")
8023 return parseSetFeature(Feature: Mips::FeatureCRC);
8024 if (IdVal == "nocrc")
8025 return parseSetNoCRCDirective();
8026 if (IdVal == "virt")
8027 return parseSetFeature(Feature: Mips::FeatureVirt);
8028 if (IdVal == "novirt")
8029 return parseSetNoVirtDirective();
8030 if (IdVal == "ginv")
8031 return parseSetFeature(Feature: Mips::FeatureGINV);
8032 if (IdVal == "noginv")
8033 return parseSetNoGINVDirective();
8034
8035 // It is just an identifier, look for an assignment.
8036 return parseSetAssignment();
8037}
8038
8039/// parseDirectiveGpWord
8040/// ::= .gpword local_sym
8041bool MipsAsmParser::parseDirectiveGpWord() {
8042 const MCExpr *Value;
8043 if (getParser().parseExpression(Res&: Value))
8044 return true;
8045 getTargetStreamer().emitGPRel32Value(Value);
8046 return parseEOL();
8047}
8048
8049/// parseDirectiveGpDWord
8050/// ::= .gpdword local_sym
8051bool MipsAsmParser::parseDirectiveGpDWord() {
8052 const MCExpr *Value;
8053 if (getParser().parseExpression(Res&: Value))
8054 return true;
8055 getTargetStreamer().emitGPRel64Value(Value);
8056 return parseEOL();
8057}
8058
8059/// parseDirectiveDtpRelWord
8060/// ::= .dtprelword tls_sym
8061bool MipsAsmParser::parseDirectiveDtpRelWord() {
8062 const MCExpr *Value;
8063 if (getParser().parseExpression(Res&: Value))
8064 return true;
8065 getTargetStreamer().emitDTPRel32Value(Value);
8066 return parseEOL();
8067}
8068
8069/// parseDirectiveDtpRelDWord
8070/// ::= .dtpreldword tls_sym
8071bool MipsAsmParser::parseDirectiveDtpRelDWord() {
8072 const MCExpr *Value;
8073 if (getParser().parseExpression(Res&: Value))
8074 return true;
8075 getTargetStreamer().emitDTPRel64Value(Value);
8076 return parseEOL();
8077}
8078
8079/// parseDirectiveTpRelWord
8080/// ::= .tprelword tls_sym
8081bool MipsAsmParser::parseDirectiveTpRelWord() {
8082 const MCExpr *Value;
8083 if (getParser().parseExpression(Res&: Value))
8084 return true;
8085 getTargetStreamer().emitTPRel32Value(Value);
8086 return parseEOL();
8087}
8088
8089/// parseDirectiveTpRelDWord
8090/// ::= .tpreldword tls_sym
8091bool MipsAsmParser::parseDirectiveTpRelDWord() {
8092 const MCExpr *Value;
8093 if (getParser().parseExpression(Res&: Value))
8094 return true;
8095 getTargetStreamer().emitTPRel64Value(Value);
8096 return parseEOL();
8097}
8098
8099bool MipsAsmParser::parseDirectiveOption() {
8100 MCAsmParser &Parser = getParser();
8101 // Get the option token.
8102 AsmToken Tok = Parser.getTok();
8103 // At the moment only identifiers are supported.
8104 if (Tok.isNot(K: AsmToken::Identifier)) {
8105 return Error(L: Parser.getTok().getLoc(),
8106 Msg: "unexpected token, expected identifier");
8107 }
8108
8109 StringRef Option = Tok.getIdentifier();
8110
8111 if (Option == "pic0") {
8112 // MipsAsmParser needs to know if the current PIC mode changes.
8113 IsPicEnabled = false;
8114
8115 getTargetStreamer().emitDirectiveOptionPic0();
8116 Parser.Lex();
8117 if (Parser.getTok().isNot(K: AsmToken::EndOfStatement)) {
8118 return Error(L: Parser.getTok().getLoc(),
8119 Msg: "unexpected token, expected end of statement");
8120 }
8121 return false;
8122 }
8123
8124 if (Option == "pic2") {
8125 // MipsAsmParser needs to know if the current PIC mode changes.
8126 IsPicEnabled = true;
8127
8128 getTargetStreamer().emitDirectiveOptionPic2();
8129 Parser.Lex();
8130 if (Parser.getTok().isNot(K: AsmToken::EndOfStatement)) {
8131 return Error(L: Parser.getTok().getLoc(),
8132 Msg: "unexpected token, expected end of statement");
8133 }
8134 return false;
8135 }
8136
8137 // Unknown option.
8138 Warning(L: Parser.getTok().getLoc(),
8139 Msg: "unknown option, expected 'pic0' or 'pic2'");
8140 Parser.eatToEndOfStatement();
8141 return false;
8142}
8143
8144/// parseInsnDirective
8145/// ::= .insn
8146bool MipsAsmParser::parseInsnDirective() {
8147 // If this is not the end of the statement, report an error.
8148 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
8149 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
8150 return false;
8151 }
8152
8153 // The actual label marking happens in
8154 // MipsELFStreamer::createPendingLabelRelocs().
8155 getTargetStreamer().emitDirectiveInsn();
8156
8157 getParser().Lex(); // Eat EndOfStatement token.
8158 return false;
8159}
8160
8161/// parseRSectionDirective
8162/// ::= .rdata
8163bool MipsAsmParser::parseRSectionDirective(StringRef Section) {
8164 // If this is not the end of the statement, report an error.
8165 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
8166 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
8167 return false;
8168 }
8169
8170 MCSection *ELFSection = getContext().getELFSection(
8171 Section, Type: ELF::SHT_PROGBITS, Flags: ELF::SHF_ALLOC);
8172 getParser().getStreamer().switchSection(Section: ELFSection);
8173
8174 getParser().Lex(); // Eat EndOfStatement token.
8175 return false;
8176}
8177
8178/// parseSSectionDirective
8179/// ::= .sbss
8180/// ::= .sdata
8181bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
8182 // If this is not the end of the statement, report an error.
8183 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
8184 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
8185 return false;
8186 }
8187
8188 MCSection *ELFSection = getContext().getELFSection(
8189 Section, Type, Flags: ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
8190 getParser().getStreamer().switchSection(Section: ELFSection);
8191
8192 getParser().Lex(); // Eat EndOfStatement token.
8193 return false;
8194}
8195
8196/// parseDirectiveModule
8197/// ::= .module oddspreg
8198/// ::= .module nooddspreg
8199/// ::= .module fp=value
8200/// ::= .module softfloat
8201/// ::= .module hardfloat
8202/// ::= .module mt
8203/// ::= .module crc
8204/// ::= .module nocrc
8205/// ::= .module virt
8206/// ::= .module novirt
8207/// ::= .module ginv
8208/// ::= .module noginv
8209bool MipsAsmParser::parseDirectiveModule() {
8210 MCAsmParser &Parser = getParser();
8211 AsmLexer &Lexer = getLexer();
8212 SMLoc L = Lexer.getLoc();
8213
8214 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
8215 // TODO : get a better message.
8216 reportParseError(ErrorMsg: ".module directive must appear before any code");
8217 return false;
8218 }
8219
8220 StringRef Option;
8221 if (Parser.parseIdentifier(Res&: Option)) {
8222 reportParseError(ErrorMsg: "expected .module option identifier");
8223 return false;
8224 }
8225
8226 if (Option == "oddspreg") {
8227 clearModuleFeatureBits(Feature: Mips::FeatureNoOddSPReg, FeatureString: "nooddspreg");
8228
8229 // Synchronize the abiflags information with the FeatureBits information we
8230 // changed above.
8231 getTargetStreamer().updateABIInfo(P: *this);
8232
8233 // If printing assembly, use the recently updated abiflags information.
8234 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
8235 // emitted at the end).
8236 getTargetStreamer().emitDirectiveModuleOddSPReg();
8237
8238 // If this is not the end of the statement, report an error.
8239 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
8240 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
8241 return false;
8242 }
8243
8244 return false; // parseDirectiveModule has finished successfully.
8245 } else if (Option == "nooddspreg") {
8246 if (!isABI_O32()) {
8247 return Error(L, Msg: "'.module nooddspreg' requires the O32 ABI");
8248 }
8249
8250 setModuleFeatureBits(Feature: Mips::FeatureNoOddSPReg, FeatureString: "nooddspreg");
8251
8252 // Synchronize the abiflags information with the FeatureBits information we
8253 // changed above.
8254 getTargetStreamer().updateABIInfo(P: *this);
8255
8256 // If printing assembly, use the recently updated abiflags information.
8257 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
8258 // emitted at the end).
8259 getTargetStreamer().emitDirectiveModuleOddSPReg();
8260
8261 // If this is not the end of the statement, report an error.
8262 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
8263 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
8264 return false;
8265 }
8266
8267 return false; // parseDirectiveModule has finished successfully.
8268 } else if (Option == "fp") {
8269 return parseDirectiveModuleFP();
8270 } else if (Option == "softfloat") {
8271 setModuleFeatureBits(Feature: Mips::FeatureSoftFloat, FeatureString: "soft-float");
8272
8273 // Synchronize the ABI Flags information with the FeatureBits information we
8274 // updated above.
8275 getTargetStreamer().updateABIInfo(P: *this);
8276
8277 // If printing assembly, use the recently updated ABI Flags information.
8278 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
8279 // emitted later).
8280 getTargetStreamer().emitDirectiveModuleSoftFloat();
8281
8282 // If this is not the end of the statement, report an error.
8283 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
8284 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
8285 return false;
8286 }
8287
8288 return false; // parseDirectiveModule has finished successfully.
8289 } else if (Option == "hardfloat") {
8290 clearModuleFeatureBits(Feature: Mips::FeatureSoftFloat, FeatureString: "soft-float");
8291
8292 // Synchronize the ABI Flags information with the FeatureBits information we
8293 // updated above.
8294 getTargetStreamer().updateABIInfo(P: *this);
8295
8296 // If printing assembly, use the recently updated ABI Flags information.
8297 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
8298 // emitted later).
8299 getTargetStreamer().emitDirectiveModuleHardFloat();
8300
8301 // If this is not the end of the statement, report an error.
8302 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
8303 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
8304 return false;
8305 }
8306
8307 return false; // parseDirectiveModule has finished successfully.
8308 } else if (Option == "mt") {
8309 setModuleFeatureBits(Feature: Mips::FeatureMT, FeatureString: "mt");
8310
8311 // Synchronize the ABI Flags information with the FeatureBits information we
8312 // updated above.
8313 getTargetStreamer().updateABIInfo(P: *this);
8314
8315 // If printing assembly, use the recently updated ABI Flags information.
8316 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
8317 // emitted later).
8318 getTargetStreamer().emitDirectiveModuleMT();
8319
8320 // If this is not the end of the statement, report an error.
8321 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
8322 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
8323 return false;
8324 }
8325
8326 return false; // parseDirectiveModule has finished successfully.
8327 } else if (Option == "crc") {
8328 setModuleFeatureBits(Feature: Mips::FeatureCRC, FeatureString: "crc");
8329
8330 // Synchronize the ABI Flags information with the FeatureBits information we
8331 // updated above.
8332 getTargetStreamer().updateABIInfo(P: *this);
8333
8334 // If printing assembly, use the recently updated ABI Flags information.
8335 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
8336 // emitted later).
8337 getTargetStreamer().emitDirectiveModuleCRC();
8338
8339 // If this is not the end of the statement, report an error.
8340 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
8341 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
8342 return false;
8343 }
8344
8345 return false; // parseDirectiveModule has finished successfully.
8346 } else if (Option == "nocrc") {
8347 clearModuleFeatureBits(Feature: Mips::FeatureCRC, FeatureString: "crc");
8348
8349 // Synchronize the ABI Flags information with the FeatureBits information we
8350 // updated above.
8351 getTargetStreamer().updateABIInfo(P: *this);
8352
8353 // If printing assembly, use the recently updated ABI Flags information.
8354 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
8355 // emitted later).
8356 getTargetStreamer().emitDirectiveModuleNoCRC();
8357
8358 // If this is not the end of the statement, report an error.
8359 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
8360 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
8361 return false;
8362 }
8363
8364 return false; // parseDirectiveModule has finished successfully.
8365 } else if (Option == "virt") {
8366 setModuleFeatureBits(Feature: Mips::FeatureVirt, FeatureString: "virt");
8367
8368 // Synchronize the ABI Flags information with the FeatureBits information we
8369 // updated above.
8370 getTargetStreamer().updateABIInfo(P: *this);
8371
8372 // If printing assembly, use the recently updated ABI Flags information.
8373 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
8374 // emitted later).
8375 getTargetStreamer().emitDirectiveModuleVirt();
8376
8377 // If this is not the end of the statement, report an error.
8378 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
8379 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
8380 return false;
8381 }
8382
8383 return false; // parseDirectiveModule has finished successfully.
8384 } else if (Option == "novirt") {
8385 clearModuleFeatureBits(Feature: Mips::FeatureVirt, FeatureString: "virt");
8386
8387 // Synchronize the ABI Flags information with the FeatureBits information we
8388 // updated above.
8389 getTargetStreamer().updateABIInfo(P: *this);
8390
8391 // If printing assembly, use the recently updated ABI Flags information.
8392 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
8393 // emitted later).
8394 getTargetStreamer().emitDirectiveModuleNoVirt();
8395
8396 // If this is not the end of the statement, report an error.
8397 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
8398 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
8399 return false;
8400 }
8401
8402 return false; // parseDirectiveModule has finished successfully.
8403 } else if (Option == "ginv") {
8404 setModuleFeatureBits(Feature: Mips::FeatureGINV, FeatureString: "ginv");
8405
8406 // Synchronize the ABI Flags information with the FeatureBits information we
8407 // updated above.
8408 getTargetStreamer().updateABIInfo(P: *this);
8409
8410 // If printing assembly, use the recently updated ABI Flags information.
8411 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
8412 // emitted later).
8413 getTargetStreamer().emitDirectiveModuleGINV();
8414
8415 // If this is not the end of the statement, report an error.
8416 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
8417 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
8418 return false;
8419 }
8420
8421 return false; // parseDirectiveModule has finished successfully.
8422 } else if (Option == "noginv") {
8423 clearModuleFeatureBits(Feature: Mips::FeatureGINV, FeatureString: "ginv");
8424
8425 // Synchronize the ABI Flags information with the FeatureBits information we
8426 // updated above.
8427 getTargetStreamer().updateABIInfo(P: *this);
8428
8429 // If printing assembly, use the recently updated ABI Flags information.
8430 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
8431 // emitted later).
8432 getTargetStreamer().emitDirectiveModuleNoGINV();
8433
8434 // If this is not the end of the statement, report an error.
8435 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
8436 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
8437 return false;
8438 }
8439
8440 return false; // parseDirectiveModule has finished successfully.
8441 } else {
8442 return Error(L, Msg: "'" + Twine(Option) + "' is not a valid .module option.");
8443 }
8444}
8445
8446/// parseDirectiveModuleFP
8447/// ::= =32
8448/// ::= =xx
8449/// ::= =64
8450bool MipsAsmParser::parseDirectiveModuleFP() {
8451 MCAsmParser &Parser = getParser();
8452 AsmLexer &Lexer = getLexer();
8453
8454 if (Lexer.isNot(K: AsmToken::Equal)) {
8455 reportParseError(ErrorMsg: "unexpected token, expected equals sign '='");
8456 return false;
8457 }
8458 Parser.Lex(); // Eat '=' token.
8459
8460 MipsABIFlagsSection::FpABIKind FpABI;
8461 if (!parseFpABIValue(FpABI, Directive: ".module"))
8462 return false;
8463
8464 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
8465 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
8466 return false;
8467 }
8468
8469 // Synchronize the abiflags information with the FeatureBits information we
8470 // changed above.
8471 getTargetStreamer().updateABIInfo(P: *this);
8472
8473 // If printing assembly, use the recently updated abiflags information.
8474 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
8475 // emitted at the end).
8476 getTargetStreamer().emitDirectiveModuleFP();
8477
8478 Parser.Lex(); // Consume the EndOfStatement.
8479 return false;
8480}
8481
8482bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
8483 StringRef Directive) {
8484 MCAsmParser &Parser = getParser();
8485 AsmLexer &Lexer = getLexer();
8486 bool ModuleLevelOptions = Directive == ".module";
8487
8488 if (Lexer.is(K: AsmToken::Identifier)) {
8489 StringRef Value = Parser.getTok().getString();
8490 Parser.Lex();
8491
8492 if (Value != "xx") {
8493 reportParseError(ErrorMsg: "unsupported value, expected 'xx', '32' or '64'");
8494 return false;
8495 }
8496
8497 if (!isABI_O32()) {
8498 reportParseError(ErrorMsg: "'" + Directive + " fp=xx' requires the O32 ABI");
8499 return false;
8500 }
8501
8502 FpABI = MipsABIFlagsSection::FpABIKind::XX;
8503 if (ModuleLevelOptions) {
8504 setModuleFeatureBits(Feature: Mips::FeatureFPXX, FeatureString: "fpxx");
8505 clearModuleFeatureBits(Feature: Mips::FeatureFP64Bit, FeatureString: "fp64");
8506 } else {
8507 setFeatureBits(Feature: Mips::FeatureFPXX, FeatureString: "fpxx");
8508 clearFeatureBits(Feature: Mips::FeatureFP64Bit, FeatureString: "fp64");
8509 }
8510 return true;
8511 }
8512
8513 if (Lexer.is(K: AsmToken::Integer)) {
8514 unsigned Value = Parser.getTok().getIntVal();
8515 Parser.Lex();
8516
8517 if (Value != 32 && Value != 64) {
8518 reportParseError(ErrorMsg: "unsupported value, expected 'xx', '32' or '64'");
8519 return false;
8520 }
8521
8522 if (Value == 32) {
8523 if (!isABI_O32()) {
8524 reportParseError(ErrorMsg: "'" + Directive + " fp=32' requires the O32 ABI");
8525 return false;
8526 }
8527
8528 FpABI = MipsABIFlagsSection::FpABIKind::S32;
8529 if (ModuleLevelOptions) {
8530 clearModuleFeatureBits(Feature: Mips::FeatureFPXX, FeatureString: "fpxx");
8531 clearModuleFeatureBits(Feature: Mips::FeatureFP64Bit, FeatureString: "fp64");
8532 } else {
8533 clearFeatureBits(Feature: Mips::FeatureFPXX, FeatureString: "fpxx");
8534 clearFeatureBits(Feature: Mips::FeatureFP64Bit, FeatureString: "fp64");
8535 }
8536 } else {
8537 FpABI = MipsABIFlagsSection::FpABIKind::S64;
8538 if (ModuleLevelOptions) {
8539 clearModuleFeatureBits(Feature: Mips::FeatureFPXX, FeatureString: "fpxx");
8540 setModuleFeatureBits(Feature: Mips::FeatureFP64Bit, FeatureString: "fp64");
8541 } else {
8542 clearFeatureBits(Feature: Mips::FeatureFPXX, FeatureString: "fpxx");
8543 setFeatureBits(Feature: Mips::FeatureFP64Bit, FeatureString: "fp64");
8544 }
8545 }
8546
8547 return true;
8548 }
8549
8550 return false;
8551}
8552
8553bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
8554 // This returns false if this function recognizes the directive
8555 // regardless of whether it is successfully handles or reports an
8556 // error. Otherwise it returns true to give the generic parser a
8557 // chance at recognizing it.
8558
8559 MCAsmParser &Parser = getParser();
8560 StringRef IDVal = DirectiveID.getString();
8561
8562 if (IDVal == ".cpadd") {
8563 parseDirectiveCpAdd(Loc: DirectiveID.getLoc());
8564 return false;
8565 }
8566 if (IDVal == ".cpload") {
8567 parseDirectiveCpLoad(Loc: DirectiveID.getLoc());
8568 return false;
8569 }
8570 if (IDVal == ".cprestore") {
8571 parseDirectiveCpRestore(Loc: DirectiveID.getLoc());
8572 return false;
8573 }
8574 if (IDVal == ".cplocal") {
8575 parseDirectiveCpLocal(Loc: DirectiveID.getLoc());
8576 return false;
8577 }
8578 if (IDVal == ".ent") {
8579 StringRef SymbolName;
8580
8581 if (Parser.parseIdentifier(Res&: SymbolName)) {
8582 reportParseError(ErrorMsg: "expected identifier after .ent");
8583 return false;
8584 }
8585
8586 // There's an undocumented extension that allows an integer to
8587 // follow the name of the procedure which AFAICS is ignored by GAS.
8588 // Example: .ent foo,2
8589 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
8590 if (getLexer().isNot(K: AsmToken::Comma)) {
8591 // Even though we accept this undocumented extension for compatibility
8592 // reasons, the additional integer argument does not actually change
8593 // the behaviour of the '.ent' directive, so we would like to discourage
8594 // its use. We do this by not referring to the extended version in
8595 // error messages which are not directly related to its use.
8596 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
8597 return false;
8598 }
8599 Parser.Lex(); // Eat the comma.
8600 const MCExpr *DummyNumber;
8601 int64_t DummyNumberVal;
8602 // If the user was explicitly trying to use the extended version,
8603 // we still give helpful extension-related error messages.
8604 if (Parser.parseExpression(Res&: DummyNumber)) {
8605 reportParseError(ErrorMsg: "expected number after comma");
8606 return false;
8607 }
8608 if (!DummyNumber->evaluateAsAbsolute(Res&: DummyNumberVal)) {
8609 reportParseError(ErrorMsg: "expected an absolute expression after comma");
8610 return false;
8611 }
8612 }
8613
8614 // If this is not the end of the statement, report an error.
8615 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
8616 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
8617 return false;
8618 }
8619
8620 MCSymbol *Sym = getContext().getOrCreateSymbol(Name: SymbolName);
8621
8622 getTargetStreamer().emitDirectiveEnt(Symbol: *Sym);
8623 CurrentFn = Sym;
8624 IsCpRestoreSet = false;
8625 return false;
8626 }
8627
8628 if (IDVal == ".end") {
8629 StringRef SymbolName;
8630
8631 if (Parser.parseIdentifier(Res&: SymbolName)) {
8632 reportParseError(ErrorMsg: "expected identifier after .end");
8633 return false;
8634 }
8635
8636 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
8637 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
8638 return false;
8639 }
8640
8641 if (CurrentFn == nullptr) {
8642 reportParseError(ErrorMsg: ".end used without .ent");
8643 return false;
8644 }
8645
8646 if ((SymbolName != CurrentFn->getName())) {
8647 reportParseError(ErrorMsg: ".end symbol does not match .ent symbol");
8648 return false;
8649 }
8650
8651 getTargetStreamer().emitDirectiveEnd(Name: SymbolName);
8652 CurrentFn = nullptr;
8653 IsCpRestoreSet = false;
8654 return false;
8655 }
8656
8657 if (IDVal == ".frame") {
8658 // .frame $stack_reg, frame_size_in_bytes, $return_reg
8659 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
8660 ParseStatus Res = parseAnyRegister(Operands&: TmpReg);
8661 if (Res.isNoMatch() || Res.isFailure()) {
8662 reportParseError(ErrorMsg: "expected stack register");
8663 return false;
8664 }
8665
8666 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
8667 if (!StackRegOpnd.isGPRAsmReg()) {
8668 reportParseError(Loc: StackRegOpnd.getStartLoc(),
8669 ErrorMsg: "expected general purpose register");
8670 return false;
8671 }
8672 MCRegister StackReg = StackRegOpnd.getGPR32Reg();
8673
8674 if (Parser.getTok().is(K: AsmToken::Comma))
8675 Parser.Lex();
8676 else {
8677 reportParseError(ErrorMsg: "unexpected token, expected comma");
8678 return false;
8679 }
8680
8681 // Parse the frame size.
8682 const MCExpr *FrameSize;
8683 int64_t FrameSizeVal;
8684
8685 if (Parser.parseExpression(Res&: FrameSize)) {
8686 reportParseError(ErrorMsg: "expected frame size value");
8687 return false;
8688 }
8689
8690 if (!FrameSize->evaluateAsAbsolute(Res&: FrameSizeVal)) {
8691 reportParseError(ErrorMsg: "frame size not an absolute expression");
8692 return false;
8693 }
8694
8695 if (Parser.getTok().is(K: AsmToken::Comma))
8696 Parser.Lex();
8697 else {
8698 reportParseError(ErrorMsg: "unexpected token, expected comma");
8699 return false;
8700 }
8701
8702 // Parse the return register.
8703 TmpReg.clear();
8704 Res = parseAnyRegister(Operands&: TmpReg);
8705 if (Res.isNoMatch() || Res.isFailure()) {
8706 reportParseError(ErrorMsg: "expected return register");
8707 return false;
8708 }
8709
8710 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
8711 if (!ReturnRegOpnd.isGPRAsmReg()) {
8712 reportParseError(Loc: ReturnRegOpnd.getStartLoc(),
8713 ErrorMsg: "expected general purpose register");
8714 return false;
8715 }
8716
8717 // If this is not the end of the statement, report an error.
8718 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
8719 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
8720 return false;
8721 }
8722
8723 getTargetStreamer().emitFrame(StackReg, StackSize: FrameSizeVal,
8724 ReturnReg: ReturnRegOpnd.getGPR32Reg());
8725 IsCpRestoreSet = false;
8726 return false;
8727 }
8728
8729 if (IDVal == ".set") {
8730 parseDirectiveSet();
8731 return false;
8732 }
8733
8734 if (IDVal == ".mask" || IDVal == ".fmask") {
8735 // .mask bitmask, frame_offset
8736 // bitmask: One bit for each register used.
8737 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
8738 // first register is expected to be saved.
8739 // Examples:
8740 // .mask 0x80000000, -4
8741 // .fmask 0x80000000, -4
8742 //
8743
8744 // Parse the bitmask
8745 const MCExpr *BitMask;
8746 int64_t BitMaskVal;
8747
8748 if (Parser.parseExpression(Res&: BitMask)) {
8749 reportParseError(ErrorMsg: "expected bitmask value");
8750 return false;
8751 }
8752
8753 if (!BitMask->evaluateAsAbsolute(Res&: BitMaskVal)) {
8754 reportParseError(ErrorMsg: "bitmask not an absolute expression");
8755 return false;
8756 }
8757
8758 if (Parser.getTok().is(K: AsmToken::Comma))
8759 Parser.Lex();
8760 else {
8761 reportParseError(ErrorMsg: "unexpected token, expected comma");
8762 return false;
8763 }
8764
8765 // Parse the frame_offset
8766 const MCExpr *FrameOffset;
8767 int64_t FrameOffsetVal;
8768
8769 if (Parser.parseExpression(Res&: FrameOffset)) {
8770 reportParseError(ErrorMsg: "expected frame offset value");
8771 return false;
8772 }
8773
8774 if (!FrameOffset->evaluateAsAbsolute(Res&: FrameOffsetVal)) {
8775 reportParseError(ErrorMsg: "frame offset not an absolute expression");
8776 return false;
8777 }
8778
8779 // If this is not the end of the statement, report an error.
8780 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
8781 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
8782 return false;
8783 }
8784
8785 if (IDVal == ".mask")
8786 getTargetStreamer().emitMask(CPUBitmask: BitMaskVal, CPUTopSavedRegOff: FrameOffsetVal);
8787 else
8788 getTargetStreamer().emitFMask(FPUBitmask: BitMaskVal, FPUTopSavedRegOff: FrameOffsetVal);
8789 return false;
8790 }
8791
8792 if (IDVal == ".nan")
8793 return parseDirectiveNaN();
8794
8795 if (IDVal == ".gpword") {
8796 parseDirectiveGpWord();
8797 return false;
8798 }
8799
8800 if (IDVal == ".gpdword") {
8801 parseDirectiveGpDWord();
8802 return false;
8803 }
8804
8805 if (IDVal == ".dtprelword") {
8806 parseDirectiveDtpRelWord();
8807 return false;
8808 }
8809
8810 if (IDVal == ".dtpreldword") {
8811 parseDirectiveDtpRelDWord();
8812 return false;
8813 }
8814
8815 if (IDVal == ".tprelword") {
8816 parseDirectiveTpRelWord();
8817 return false;
8818 }
8819
8820 if (IDVal == ".tpreldword") {
8821 parseDirectiveTpRelDWord();
8822 return false;
8823 }
8824
8825 if (IDVal == ".option") {
8826 parseDirectiveOption();
8827 return false;
8828 }
8829
8830 if (IDVal == ".abicalls") {
8831 getTargetStreamer().emitDirectiveAbiCalls();
8832 if (Parser.getTok().isNot(K: AsmToken::EndOfStatement)) {
8833 Error(L: Parser.getTok().getLoc(),
8834 Msg: "unexpected token, expected end of statement");
8835 }
8836 return false;
8837 }
8838
8839 if (IDVal == ".cpsetup") {
8840 parseDirectiveCPSetup();
8841 return false;
8842 }
8843 if (IDVal == ".cpreturn") {
8844 parseDirectiveCPReturn();
8845 return false;
8846 }
8847 if (IDVal == ".module") {
8848 parseDirectiveModule();
8849 return false;
8850 }
8851 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
8852 parseInternalDirectiveReallowModule();
8853 return false;
8854 }
8855 if (IDVal == ".insn") {
8856 parseInsnDirective();
8857 return false;
8858 }
8859 if (IDVal == ".rdata") {
8860 parseRSectionDirective(Section: ".rodata");
8861 return false;
8862 }
8863 if (IDVal == ".sbss") {
8864 parseSSectionDirective(Section: IDVal, Type: ELF::SHT_NOBITS);
8865 return false;
8866 }
8867 if (IDVal == ".sdata") {
8868 parseSSectionDirective(Section: IDVal, Type: ELF::SHT_PROGBITS);
8869 return false;
8870 }
8871
8872 return true;
8873}
8874
8875bool MipsAsmParser::parseInternalDirectiveReallowModule() {
8876 // If this is not the end of the statement, report an error.
8877 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
8878 reportParseError(ErrorMsg: "unexpected token, expected end of statement");
8879 return false;
8880 }
8881
8882 getTargetStreamer().reallowModuleDirective();
8883
8884 getParser().Lex(); // Eat EndOfStatement token.
8885 return false;
8886}
8887
8888extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
8889LLVMInitializeMipsAsmParser() {
8890 RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget());
8891 RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget());
8892 RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target());
8893 RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget());
8894}
8895
8896#define GET_REGISTER_MATCHER
8897#define GET_MATCHER_IMPLEMENTATION
8898#define GET_MNEMONIC_SPELL_CHECKER
8899#include "MipsGenAsmMatcher.inc"
8900
8901bool MipsAsmParser::mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {
8902 // Find the appropriate table for this asm variant.
8903 const MatchEntry *Start, *End;
8904 switch (VariantID) {
8905 default: llvm_unreachable("invalid variant!");
8906 case 0: Start = std::begin(arr: MatchTable0); End = std::end(arr: MatchTable0); break;
8907 }
8908 // Search the table.
8909 auto MnemonicRange = std::equal_range(first: Start, last: End, val: Mnemonic, comp: LessOpcode());
8910 return MnemonicRange.first != MnemonicRange.second;
8911}
8912