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