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

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