Thanks to visit codestin.com
Credit goes to llvm.org

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