1 //===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "MCTargetDesc/MipsABIInfo.h"
11 #include "MCTargetDesc/MipsMCExpr.h"
12 #include "MCTargetDesc/MipsMCTargetDesc.h"
13 #include "MipsRegisterInfo.h"
14 #include "MipsTargetObjectFile.h"
15 #include "MipsTargetStreamer.h"
16 #include "llvm/ADT/SmallVector.h"
17 #include "llvm/ADT/StringSwitch.h"
18 #include "llvm/MC/MCContext.h"
19 #include "llvm/MC/MCExpr.h"
20 #include "llvm/MC/MCInst.h"
21 #include "llvm/MC/MCInstBuilder.h"
22 #include "llvm/MC/MCParser/MCAsmLexer.h"
23 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
24 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
25 #include "llvm/MC/MCSectionELF.h"
26 #include "llvm/MC/MCStreamer.h"
27 #include "llvm/MC/MCSubtargetInfo.h"
28 #include "llvm/MC/MCSymbol.h"
29 #include "llvm/Support/Debug.h"
30 #include "llvm/Support/ELF.h"
31 #include "llvm/Support/MathExtras.h"
32 #include "llvm/Support/SourceMgr.h"
33 #include "llvm/Support/TargetRegistry.h"
34 #include "llvm/Support/raw_ostream.h"
35 #include <memory>
36
37 using namespace llvm;
38
39 #define DEBUG_TYPE "mips-asm-parser"
40
41 namespace llvm {
42 class MCInstrInfo;
43 }
44
45 namespace {
46 class MipsAssemblerOptions {
47 public:
MipsAssemblerOptions(const FeatureBitset & Features_)48 MipsAssemblerOptions(const FeatureBitset &Features_) :
49 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
50
MipsAssemblerOptions(const MipsAssemblerOptions * Opts)51 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
52 ATReg = Opts->getATRegIndex();
53 Reorder = Opts->isReorder();
54 Macro = Opts->isMacro();
55 Features = Opts->getFeatures();
56 }
57
getATRegIndex() const58 unsigned getATRegIndex() const { return ATReg; }
setATRegIndex(unsigned Reg)59 bool setATRegIndex(unsigned Reg) {
60 if (Reg > 31)
61 return false;
62
63 ATReg = Reg;
64 return true;
65 }
66
isReorder() const67 bool isReorder() const { return Reorder; }
setReorder()68 void setReorder() { Reorder = true; }
setNoReorder()69 void setNoReorder() { Reorder = false; }
70
isMacro() const71 bool isMacro() const { return Macro; }
setMacro()72 void setMacro() { Macro = true; }
setNoMacro()73 void setNoMacro() { Macro = false; }
74
getFeatures() const75 const FeatureBitset &getFeatures() const { return Features; }
setFeatures(const FeatureBitset & Features_)76 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
77
78 // Set of features that are either architecture features or referenced
79 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
80 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
81 // The reason we need this mask is explained in the selectArch function.
82 // FIXME: Ideally we would like TableGen to generate this information.
83 static const FeatureBitset AllArchRelatedMask;
84
85 private:
86 unsigned ATReg;
87 bool Reorder;
88 bool Macro;
89 FeatureBitset Features;
90 };
91 }
92
93 const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
94 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
95 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
96 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
97 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
98 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
99 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
100 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
101 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
102 };
103
104 namespace {
105 class MipsAsmParser : public MCTargetAsmParser {
getTargetStreamer()106 MipsTargetStreamer &getTargetStreamer() {
107 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
108 return static_cast<MipsTargetStreamer &>(TS);
109 }
110
111 MipsABIInfo ABI;
112 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
113 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
114 // nullptr, which indicates that no function is currently
115 // selected. This usually happens after an '.end func'
116 // directive.
117 bool IsLittleEndian;
118 bool IsPicEnabled;
119 bool IsCpRestoreSet;
120 int CpRestoreOffset;
121 unsigned CpSaveLocation;
122 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
123 bool CpSaveLocationIsRegister;
124
125 // Print a warning along with its fix-it message at the given range.
126 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
127 SMRange Range, bool ShowColors = true);
128
129 #define GET_ASSEMBLER_HEADER
130 #include "MipsGenAsmMatcher.inc"
131
132 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
133
134 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
135 OperandVector &Operands, MCStreamer &Out,
136 uint64_t &ErrorInfo,
137 bool MatchingInlineAsm) override;
138
139 /// Parse a register as used in CFI directives
140 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
141
142 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
143
144 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
145
146 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
147 SMLoc NameLoc, OperandVector &Operands) override;
148
149 bool ParseDirective(AsmToken DirectiveID) override;
150
151 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
152 OperandMatchResultTy
153 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
154 StringRef Identifier, SMLoc S);
155 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
156 SMLoc S);
157 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
158 OperandMatchResultTy parseImm(OperandVector &Operands);
159 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
160 OperandMatchResultTy parseInvNum(OperandVector &Operands);
161 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
162 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
163 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
164
165 bool searchSymbolAlias(OperandVector &Operands);
166
167 bool parseOperand(OperandVector &, StringRef Mnemonic);
168
169 enum MacroExpanderResultTy {
170 MER_NotAMacro,
171 MER_Success,
172 MER_Fail,
173 };
174
175 // Expands assembly pseudo instructions.
176 MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
177 MCStreamer &Out,
178 const MCSubtargetInfo *STI);
179
180 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
181 const MCSubtargetInfo *STI);
182
183 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
184 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
185 MCStreamer &Out, const MCSubtargetInfo *STI);
186
187 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
188 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
189 MCStreamer &Out, const MCSubtargetInfo *STI);
190
191 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
192 MCStreamer &Out, const MCSubtargetInfo *STI);
193
194 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
195 const MCOperand &Offset, bool Is32BitAddress,
196 SMLoc IDLoc, MCStreamer &Out,
197 const MCSubtargetInfo *STI);
198
199 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
200 const MCSubtargetInfo *STI);
201
202 void expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
203 const MCSubtargetInfo *STI, bool IsLoad, bool IsImmOpnd);
204
205 void expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
206 const MCSubtargetInfo *STI, bool IsImmOpnd);
207
208 void expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
209 const MCSubtargetInfo *STI, bool IsImmOpnd);
210
211 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
212 const MCSubtargetInfo *STI);
213
214 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
215 const MCSubtargetInfo *STI);
216
217 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
218 const MCSubtargetInfo *STI);
219
220 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
221 const MCSubtargetInfo *STI);
222
223 bool expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
224 const MCSubtargetInfo *STI, const bool IsMips64,
225 const bool Signed);
226
227 bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
228 MCStreamer &Out, const MCSubtargetInfo *STI);
229
230 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out,
231 const MCSubtargetInfo *STI);
232
233 bool expandUlw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
234 const MCSubtargetInfo *STI);
235
236 bool expandRotation(MCInst &Inst, SMLoc IDLoc,
237 MCStreamer &Out, const MCSubtargetInfo *STI);
238 bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
239 const MCSubtargetInfo *STI);
240 bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
241 const MCSubtargetInfo *STI);
242 bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
243 const MCSubtargetInfo *STI);
244
245 bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
246 const MCSubtargetInfo *STI);
247
248 bool reportParseError(Twine ErrorMsg);
249 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
250
251 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
252 bool parseRelocOperand(const MCExpr *&Res);
253
254 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
255
256 bool isEvaluated(const MCExpr *Expr);
257 bool parseSetMips0Directive();
258 bool parseSetArchDirective();
259 bool parseSetFeature(uint64_t Feature);
260 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
261 bool parseDirectiveCpLoad(SMLoc Loc);
262 bool parseDirectiveCpRestore(SMLoc Loc);
263 bool parseDirectiveCPSetup();
264 bool parseDirectiveCPReturn();
265 bool parseDirectiveNaN();
266 bool parseDirectiveSet();
267 bool parseDirectiveOption();
268 bool parseInsnDirective();
269 bool parseSSectionDirective(StringRef Section, unsigned Type);
270
271 bool parseSetAtDirective();
272 bool parseSetNoAtDirective();
273 bool parseSetMacroDirective();
274 bool parseSetNoMacroDirective();
275 bool parseSetMsaDirective();
276 bool parseSetNoMsaDirective();
277 bool parseSetNoDspDirective();
278 bool parseSetReorderDirective();
279 bool parseSetNoReorderDirective();
280 bool parseSetMips16Directive();
281 bool parseSetNoMips16Directive();
282 bool parseSetFpDirective();
283 bool parseSetOddSPRegDirective();
284 bool parseSetNoOddSPRegDirective();
285 bool parseSetPopDirective();
286 bool parseSetPushDirective();
287 bool parseSetSoftFloatDirective();
288 bool parseSetHardFloatDirective();
289
290 bool parseSetAssignment();
291
292 bool parseDataDirective(unsigned Size, SMLoc L);
293 bool parseDirectiveGpWord();
294 bool parseDirectiveGpDWord();
295 bool parseDirectiveModule();
296 bool parseDirectiveModuleFP();
297 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
298 StringRef Directive);
299
300 bool parseInternalDirectiveReallowModule();
301
302 bool eatComma(StringRef ErrorStr);
303
304 int matchCPURegisterName(StringRef Symbol);
305
306 int matchHWRegsRegisterName(StringRef Symbol);
307
308 int matchFPURegisterName(StringRef Name);
309
310 int matchFCCRegisterName(StringRef Name);
311
312 int matchACRegisterName(StringRef Name);
313
314 int matchMSA128RegisterName(StringRef Name);
315
316 int matchMSA128CtrlRegisterName(StringRef Name);
317
318 unsigned getReg(int RC, int RegNo);
319
320 /// Returns the internal register number for the current AT. Also checks if
321 /// the current AT is unavailable (set to $0) and gives an error if it is.
322 /// This should be used in pseudo-instruction expansions which need AT.
323 unsigned getATReg(SMLoc Loc);
324
325 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
326 const MCSubtargetInfo *STI);
327
328 // Helper function that checks if the value of a vector index is within the
329 // boundaries of accepted values for each RegisterKind
330 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
331 bool validateMSAIndex(int Val, int RegKind);
332
333 // Selects a new architecture by updating the FeatureBits with the necessary
334 // info including implied dependencies.
335 // Internally, it clears all the feature bits related to *any* architecture
336 // and selects the new one using the ToggleFeature functionality of the
337 // MCSubtargetInfo object that handles implied dependencies. The reason we
338 // clear all the arch related bits manually is because ToggleFeature only
339 // clears the features that imply the feature being cleared and not the
340 // features implied by the feature being cleared. This is easier to see
341 // with an example:
342 // --------------------------------------------------
343 // | Feature | Implies |
344 // | -------------------------------------------------|
345 // | FeatureMips1 | None |
346 // | FeatureMips2 | FeatureMips1 |
347 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
348 // | FeatureMips4 | FeatureMips3 |
349 // | ... | |
350 // --------------------------------------------------
351 //
352 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
353 // FeatureMipsGP64 | FeatureMips1)
354 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
selectArch(StringRef ArchFeature)355 void selectArch(StringRef ArchFeature) {
356 MCSubtargetInfo &STI = copySTI();
357 FeatureBitset FeatureBits = STI.getFeatureBits();
358 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
359 STI.setFeatureBits(FeatureBits);
360 setAvailableFeatures(
361 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
362 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
363 }
364
setFeatureBits(uint64_t Feature,StringRef FeatureString)365 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
366 if (!(getSTI().getFeatureBits()[Feature])) {
367 MCSubtargetInfo &STI = copySTI();
368 setAvailableFeatures(
369 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
370 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
371 }
372 }
373
clearFeatureBits(uint64_t Feature,StringRef FeatureString)374 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
375 if (getSTI().getFeatureBits()[Feature]) {
376 MCSubtargetInfo &STI = copySTI();
377 setAvailableFeatures(
378 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
379 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
380 }
381 }
382
setModuleFeatureBits(uint64_t Feature,StringRef FeatureString)383 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
384 setFeatureBits(Feature, FeatureString);
385 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
386 }
387
clearModuleFeatureBits(uint64_t Feature,StringRef FeatureString)388 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
389 clearFeatureBits(Feature, FeatureString);
390 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
391 }
392
393 public:
394 enum MipsMatchResultTy {
395 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
396 Match_RequiresDifferentOperands,
397 Match_RequiresNoZeroRegister,
398 #define GET_OPERAND_DIAGNOSTIC_TYPES
399 #include "MipsGenAsmMatcher.inc"
400 #undef GET_OPERAND_DIAGNOSTIC_TYPES
401 };
402
MipsAsmParser(const MCSubtargetInfo & sti,MCAsmParser & parser,const MCInstrInfo & MII,const MCTargetOptions & Options)403 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
404 const MCInstrInfo &MII, const MCTargetOptions &Options)
405 : MCTargetAsmParser(Options, sti),
406 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
407 sti.getCPU(), Options)) {
408 MCAsmParserExtension::Initialize(parser);
409
410 parser.addAliasForDirective(".asciiz", ".asciz");
411
412 // Initialize the set of available features.
413 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
414
415 // Remember the initial assembler options. The user can not modify these.
416 AssemblerOptions.push_back(
417 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
418
419 // Create an assembler options environment for the user to modify.
420 AssemblerOptions.push_back(
421 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
422
423 getTargetStreamer().updateABIInfo(*this);
424
425 if (!isABI_O32() && !useOddSPReg() != 0)
426 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
427
428 CurrentFn = nullptr;
429
430 IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
431
432 IsCpRestoreSet = false;
433 CpRestoreOffset = -1;
434
435 const Triple &TheTriple = sti.getTargetTriple();
436 if ((TheTriple.getArch() == Triple::mips) ||
437 (TheTriple.getArch() == Triple::mips64))
438 IsLittleEndian = false;
439 else
440 IsLittleEndian = true;
441 }
442
443 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
hasEightFccRegisters() const444 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
445
isGP64bit() const446 bool isGP64bit() const {
447 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
448 }
isFP64bit() const449 bool isFP64bit() const {
450 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
451 }
getABI() const452 const MipsABIInfo &getABI() const { return ABI; }
isABI_N32() const453 bool isABI_N32() const { return ABI.IsN32(); }
isABI_N64() const454 bool isABI_N64() const { return ABI.IsN64(); }
isABI_O32() const455 bool isABI_O32() const { return ABI.IsO32(); }
isABI_FPXX() const456 bool isABI_FPXX() const {
457 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
458 }
459
useOddSPReg() const460 bool useOddSPReg() const {
461 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
462 }
463
inMicroMipsMode() const464 bool inMicroMipsMode() const {
465 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
466 }
hasMips1() const467 bool hasMips1() const {
468 return getSTI().getFeatureBits()[Mips::FeatureMips1];
469 }
hasMips2() const470 bool hasMips2() const {
471 return getSTI().getFeatureBits()[Mips::FeatureMips2];
472 }
hasMips3() const473 bool hasMips3() const {
474 return getSTI().getFeatureBits()[Mips::FeatureMips3];
475 }
hasMips4() const476 bool hasMips4() const {
477 return getSTI().getFeatureBits()[Mips::FeatureMips4];
478 }
hasMips5() const479 bool hasMips5() const {
480 return getSTI().getFeatureBits()[Mips::FeatureMips5];
481 }
hasMips32() const482 bool hasMips32() const {
483 return getSTI().getFeatureBits()[Mips::FeatureMips32];
484 }
hasMips64() const485 bool hasMips64() const {
486 return getSTI().getFeatureBits()[Mips::FeatureMips64];
487 }
hasMips32r2() const488 bool hasMips32r2() const {
489 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
490 }
hasMips64r2() const491 bool hasMips64r2() const {
492 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
493 }
hasMips32r3() const494 bool hasMips32r3() const {
495 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
496 }
hasMips64r3() const497 bool hasMips64r3() const {
498 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
499 }
hasMips32r5() const500 bool hasMips32r5() const {
501 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
502 }
hasMips64r5() const503 bool hasMips64r5() const {
504 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
505 }
hasMips32r6() const506 bool hasMips32r6() const {
507 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
508 }
hasMips64r6() const509 bool hasMips64r6() const {
510 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
511 }
512
hasDSP() const513 bool hasDSP() const {
514 return getSTI().getFeatureBits()[Mips::FeatureDSP];
515 }
hasDSPR2() const516 bool hasDSPR2() const {
517 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
518 }
hasDSPR3() const519 bool hasDSPR3() const {
520 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
521 }
hasMSA() const522 bool hasMSA() const {
523 return getSTI().getFeatureBits()[Mips::FeatureMSA];
524 }
hasCnMips() const525 bool hasCnMips() const {
526 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
527 }
528
inPicMode()529 bool inPicMode() {
530 return IsPicEnabled;
531 }
532
inMips16Mode() const533 bool inMips16Mode() const {
534 return getSTI().getFeatureBits()[Mips::FeatureMips16];
535 }
536
useTraps() const537 bool useTraps() const {
538 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
539 }
540
useSoftFloat() const541 bool useSoftFloat() const {
542 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
543 }
544
545 /// Warn if RegIndex is the same as the current AT.
546 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
547
548 void warnIfNoMacro(SMLoc Loc);
549
isLittle() const550 bool isLittle() const { return IsLittleEndian; }
551 };
552 }
553
554 namespace {
555
556 /// MipsOperand - Instances of this class represent a parsed Mips machine
557 /// instruction.
558 class MipsOperand : public MCParsedAsmOperand {
559 public:
560 /// Broad categories of register classes
561 /// The exact class is finalized by the render method.
562 enum RegKind {
563 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
564 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
565 /// isFP64bit())
566 RegKind_FCC = 4, /// FCC
567 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
568 RegKind_MSACtrl = 16, /// MSA control registers
569 RegKind_COP2 = 32, /// COP2
570 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
571 /// context).
572 RegKind_CCR = 128, /// CCR
573 RegKind_HWRegs = 256, /// HWRegs
574 RegKind_COP3 = 512, /// COP3
575 RegKind_COP0 = 1024, /// COP0
576 /// Potentially any (e.g. $1)
577 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
578 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
579 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
580 };
581
582 private:
583 enum KindTy {
584 k_Immediate, /// An immediate (possibly involving symbol references)
585 k_Memory, /// Base + Offset Memory Address
586 k_RegisterIndex, /// A register index in one or more RegKind.
587 k_Token, /// A simple token
588 k_RegList, /// A physical register list
589 k_RegPair /// A pair of physical register
590 } Kind;
591
592 public:
MipsOperand(KindTy K,MipsAsmParser & Parser)593 MipsOperand(KindTy K, MipsAsmParser &Parser)
594 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
595
596 private:
597 /// For diagnostics, and checking the assembler temporary
598 MipsAsmParser &AsmParser;
599
600 struct Token {
601 const char *Data;
602 unsigned Length;
603 };
604
605 struct RegIdxOp {
606 unsigned Index; /// Index into the register class
607 RegKind Kind; /// Bitfield of the kinds it could possibly be
608 const MCRegisterInfo *RegInfo;
609 };
610
611 struct ImmOp {
612 const MCExpr *Val;
613 };
614
615 struct MemOp {
616 MipsOperand *Base;
617 const MCExpr *Off;
618 };
619
620 struct RegListOp {
621 SmallVector<unsigned, 10> *List;
622 };
623
624 union {
625 struct Token Tok;
626 struct RegIdxOp RegIdx;
627 struct ImmOp Imm;
628 struct MemOp Mem;
629 struct RegListOp RegList;
630 };
631
632 SMLoc StartLoc, EndLoc;
633
634 /// Internal constructor for register kinds
CreateReg(unsigned Index,RegKind RegKind,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)635 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
636 const MCRegisterInfo *RegInfo,
637 SMLoc S, SMLoc E,
638 MipsAsmParser &Parser) {
639 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
640 Op->RegIdx.Index = Index;
641 Op->RegIdx.RegInfo = RegInfo;
642 Op->RegIdx.Kind = RegKind;
643 Op->StartLoc = S;
644 Op->EndLoc = E;
645 return Op;
646 }
647
648 public:
649 /// Coerce the register to GPR32 and return the real register for the current
650 /// target.
getGPR32Reg() const651 unsigned getGPR32Reg() const {
652 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
653 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
654 unsigned ClassID = Mips::GPR32RegClassID;
655 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
656 }
657
658 /// Coerce the register to GPR32 and return the real register for the current
659 /// target.
getGPRMM16Reg() const660 unsigned getGPRMM16Reg() const {
661 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
662 unsigned ClassID = Mips::GPR32RegClassID;
663 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
664 }
665
666 /// Coerce the register to GPR64 and return the real register for the current
667 /// target.
getGPR64Reg() const668 unsigned getGPR64Reg() const {
669 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
670 unsigned ClassID = Mips::GPR64RegClassID;
671 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
672 }
673
674 private:
675 /// Coerce the register to AFGR64 and return the real register for the current
676 /// target.
getAFGR64Reg() const677 unsigned getAFGR64Reg() const {
678 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
679 if (RegIdx.Index % 2 != 0)
680 AsmParser.Warning(StartLoc, "Float register should be even.");
681 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
682 .getRegister(RegIdx.Index / 2);
683 }
684
685 /// Coerce the register to FGR64 and return the real register for the current
686 /// target.
getFGR64Reg() const687 unsigned getFGR64Reg() const {
688 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
689 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
690 .getRegister(RegIdx.Index);
691 }
692
693 /// Coerce the register to FGR32 and return the real register for the current
694 /// target.
getFGR32Reg() const695 unsigned getFGR32Reg() const {
696 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
697 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
698 .getRegister(RegIdx.Index);
699 }
700
701 /// Coerce the register to FGRH32 and return the real register for the current
702 /// target.
getFGRH32Reg() const703 unsigned getFGRH32Reg() const {
704 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
705 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
706 .getRegister(RegIdx.Index);
707 }
708
709 /// Coerce the register to FCC and return the real register for the current
710 /// target.
getFCCReg() const711 unsigned getFCCReg() const {
712 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
713 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
714 .getRegister(RegIdx.Index);
715 }
716
717 /// Coerce the register to MSA128 and return the real register for the current
718 /// target.
getMSA128Reg() const719 unsigned getMSA128Reg() const {
720 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
721 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
722 // identical
723 unsigned ClassID = Mips::MSA128BRegClassID;
724 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
725 }
726
727 /// Coerce the register to MSACtrl and return the real register for the
728 /// current target.
getMSACtrlReg() const729 unsigned getMSACtrlReg() const {
730 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
731 unsigned ClassID = Mips::MSACtrlRegClassID;
732 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
733 }
734
735 /// Coerce the register to COP0 and return the real register for the
736 /// current target.
getCOP0Reg() const737 unsigned getCOP0Reg() const {
738 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
739 unsigned ClassID = Mips::COP0RegClassID;
740 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
741 }
742
743 /// Coerce the register to COP2 and return the real register for the
744 /// current target.
getCOP2Reg() const745 unsigned getCOP2Reg() const {
746 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
747 unsigned ClassID = Mips::COP2RegClassID;
748 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
749 }
750
751 /// Coerce the register to COP3 and return the real register for the
752 /// current target.
getCOP3Reg() const753 unsigned getCOP3Reg() const {
754 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
755 unsigned ClassID = Mips::COP3RegClassID;
756 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
757 }
758
759 /// Coerce the register to ACC64DSP and return the real register for the
760 /// current target.
getACC64DSPReg() const761 unsigned getACC64DSPReg() const {
762 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
763 unsigned ClassID = Mips::ACC64DSPRegClassID;
764 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
765 }
766
767 /// Coerce the register to HI32DSP and return the real register for the
768 /// current target.
getHI32DSPReg() const769 unsigned getHI32DSPReg() const {
770 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
771 unsigned ClassID = Mips::HI32DSPRegClassID;
772 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
773 }
774
775 /// Coerce the register to LO32DSP and return the real register for the
776 /// current target.
getLO32DSPReg() const777 unsigned getLO32DSPReg() const {
778 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
779 unsigned ClassID = Mips::LO32DSPRegClassID;
780 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
781 }
782
783 /// Coerce the register to CCR and return the real register for the
784 /// current target.
getCCRReg() const785 unsigned getCCRReg() const {
786 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
787 unsigned ClassID = Mips::CCRRegClassID;
788 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
789 }
790
791 /// Coerce the register to HWRegs and return the real register for the
792 /// current target.
getHWRegsReg() const793 unsigned getHWRegsReg() const {
794 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
795 unsigned ClassID = Mips::HWRegsRegClassID;
796 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
797 }
798
799 public:
addExpr(MCInst & Inst,const MCExpr * Expr) const800 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
801 // Add as immediate when possible. Null MCExpr = 0.
802 if (!Expr)
803 Inst.addOperand(MCOperand::createImm(0));
804 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
805 Inst.addOperand(MCOperand::createImm(CE->getValue()));
806 else
807 Inst.addOperand(MCOperand::createExpr(Expr));
808 }
809
addRegOperands(MCInst & Inst,unsigned N) const810 void addRegOperands(MCInst &Inst, unsigned N) const {
811 llvm_unreachable("Use a custom parser instead");
812 }
813
814 /// Render the operand to an MCInst as a GPR32
815 /// Asserts if the wrong number of operands are requested, or the operand
816 /// is not a k_RegisterIndex compatible with RegKind_GPR
addGPR32AsmRegOperands(MCInst & Inst,unsigned N) const817 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
818 assert(N == 1 && "Invalid number of operands!");
819 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
820 }
821
addGPRMM16AsmRegOperands(MCInst & Inst,unsigned N) const822 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
823 assert(N == 1 && "Invalid number of operands!");
824 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
825 }
826
addGPRMM16AsmRegZeroOperands(MCInst & Inst,unsigned N) const827 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
828 assert(N == 1 && "Invalid number of operands!");
829 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
830 }
831
addGPRMM16AsmRegMovePOperands(MCInst & Inst,unsigned N) const832 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
833 assert(N == 1 && "Invalid number of operands!");
834 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
835 }
836
837 /// Render the operand to an MCInst as a GPR64
838 /// Asserts if the wrong number of operands are requested, or the operand
839 /// is not a k_RegisterIndex compatible with RegKind_GPR
addGPR64AsmRegOperands(MCInst & Inst,unsigned N) const840 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
841 assert(N == 1 && "Invalid number of operands!");
842 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
843 }
844
addAFGR64AsmRegOperands(MCInst & Inst,unsigned N) const845 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
846 assert(N == 1 && "Invalid number of operands!");
847 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
848 }
849
addFGR64AsmRegOperands(MCInst & Inst,unsigned N) const850 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
851 assert(N == 1 && "Invalid number of operands!");
852 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
853 }
854
addFGR32AsmRegOperands(MCInst & Inst,unsigned N) const855 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
856 assert(N == 1 && "Invalid number of operands!");
857 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
858 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
859 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
860 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
861 "registers");
862 }
863
addFGRH32AsmRegOperands(MCInst & Inst,unsigned N) const864 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
865 assert(N == 1 && "Invalid number of operands!");
866 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
867 }
868
addFCCAsmRegOperands(MCInst & Inst,unsigned N) const869 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
870 assert(N == 1 && "Invalid number of operands!");
871 Inst.addOperand(MCOperand::createReg(getFCCReg()));
872 }
873
addMSA128AsmRegOperands(MCInst & Inst,unsigned N) const874 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
875 assert(N == 1 && "Invalid number of operands!");
876 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
877 }
878
addMSACtrlAsmRegOperands(MCInst & Inst,unsigned N) const879 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
880 assert(N == 1 && "Invalid number of operands!");
881 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
882 }
883
addCOP0AsmRegOperands(MCInst & Inst,unsigned N) const884 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
885 assert(N == 1 && "Invalid number of operands!");
886 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
887 }
888
addCOP2AsmRegOperands(MCInst & Inst,unsigned N) const889 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
890 assert(N == 1 && "Invalid number of operands!");
891 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
892 }
893
addCOP3AsmRegOperands(MCInst & Inst,unsigned N) const894 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
895 assert(N == 1 && "Invalid number of operands!");
896 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
897 }
898
addACC64DSPAsmRegOperands(MCInst & Inst,unsigned N) const899 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
900 assert(N == 1 && "Invalid number of operands!");
901 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
902 }
903
addHI32DSPAsmRegOperands(MCInst & Inst,unsigned N) const904 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
905 assert(N == 1 && "Invalid number of operands!");
906 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
907 }
908
addLO32DSPAsmRegOperands(MCInst & Inst,unsigned N) const909 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
910 assert(N == 1 && "Invalid number of operands!");
911 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
912 }
913
addCCRAsmRegOperands(MCInst & Inst,unsigned N) const914 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
915 assert(N == 1 && "Invalid number of operands!");
916 Inst.addOperand(MCOperand::createReg(getCCRReg()));
917 }
918
addHWRegsAsmRegOperands(MCInst & Inst,unsigned N) const919 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
920 assert(N == 1 && "Invalid number of operands!");
921 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
922 }
923
924 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
addConstantUImmOperands(MCInst & Inst,unsigned N) const925 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
926 assert(N == 1 && "Invalid number of operands!");
927 uint64_t Imm = getConstantImm() - Offset;
928 Imm &= (1 << Bits) - 1;
929 Imm += Offset;
930 Imm += AdjustOffset;
931 Inst.addOperand(MCOperand::createImm(Imm));
932 }
933
934 template <unsigned Bits>
addSImmOperands(MCInst & Inst,unsigned N) const935 void addSImmOperands(MCInst &Inst, unsigned N) const {
936 if (isImm() && !isConstantImm()) {
937 addExpr(Inst, getImm());
938 return;
939 }
940 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
941 }
942
943 template <unsigned Bits>
addUImmOperands(MCInst & Inst,unsigned N) const944 void addUImmOperands(MCInst &Inst, unsigned N) const {
945 if (isImm() && !isConstantImm()) {
946 addExpr(Inst, getImm());
947 return;
948 }
949 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
950 }
951
952 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
addConstantSImmOperands(MCInst & Inst,unsigned N) const953 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
954 assert(N == 1 && "Invalid number of operands!");
955 int64_t Imm = getConstantImm() - Offset;
956 Imm = SignExtend64<Bits>(Imm);
957 Imm += Offset;
958 Imm += AdjustOffset;
959 Inst.addOperand(MCOperand::createImm(Imm));
960 }
961
addImmOperands(MCInst & Inst,unsigned N) const962 void addImmOperands(MCInst &Inst, unsigned N) const {
963 assert(N == 1 && "Invalid number of operands!");
964 const MCExpr *Expr = getImm();
965 addExpr(Inst, Expr);
966 }
967
addMemOperands(MCInst & Inst,unsigned N) const968 void addMemOperands(MCInst &Inst, unsigned N) const {
969 assert(N == 2 && "Invalid number of operands!");
970
971 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
972 ? getMemBase()->getGPR64Reg()
973 : getMemBase()->getGPR32Reg()));
974
975 const MCExpr *Expr = getMemOff();
976 addExpr(Inst, Expr);
977 }
978
addMicroMipsMemOperands(MCInst & Inst,unsigned N) const979 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
980 assert(N == 2 && "Invalid number of operands!");
981
982 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
983
984 const MCExpr *Expr = getMemOff();
985 addExpr(Inst, Expr);
986 }
987
addRegListOperands(MCInst & Inst,unsigned N) const988 void addRegListOperands(MCInst &Inst, unsigned N) const {
989 assert(N == 1 && "Invalid number of operands!");
990
991 for (auto RegNo : getRegList())
992 Inst.addOperand(MCOperand::createReg(RegNo));
993 }
994
addRegPairOperands(MCInst & Inst,unsigned N) const995 void addRegPairOperands(MCInst &Inst, unsigned N) const {
996 assert(N == 2 && "Invalid number of operands!");
997 assert((RegIdx.Kind & RegKind_GPR) && "Invalid access!");
998 unsigned RegNo = getRegPair();
999 AsmParser.warnIfRegIndexIsAT(RegNo, StartLoc);
1000 Inst.addOperand(MCOperand::createReg(
1001 RegIdx.RegInfo->getRegClass(
1002 AsmParser.getABI().AreGprs64bit()
1003 ? Mips::GPR64RegClassID
1004 : Mips::GPR32RegClassID).getRegister(RegNo++)));
1005 Inst.addOperand(MCOperand::createReg(
1006 RegIdx.RegInfo->getRegClass(
1007 AsmParser.getABI().AreGprs64bit()
1008 ? Mips::GPR64RegClassID
1009 : Mips::GPR32RegClassID).getRegister(RegNo)));
1010 }
1011
addMovePRegPairOperands(MCInst & Inst,unsigned N) const1012 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1013 assert(N == 2 && "Invalid number of operands!");
1014 for (auto RegNo : getRegList())
1015 Inst.addOperand(MCOperand::createReg(RegNo));
1016 }
1017
isReg() const1018 bool isReg() const override {
1019 // As a special case until we sort out the definition of div/divu, accept
1020 // $0/$zero here so that MCK_ZERO works correctly.
1021 return isGPRAsmReg() && RegIdx.Index == 0;
1022 }
isRegIdx() const1023 bool isRegIdx() const { return Kind == k_RegisterIndex; }
isImm() const1024 bool isImm() const override { return Kind == k_Immediate; }
isConstantImm() const1025 bool isConstantImm() const {
1026 return isImm() && isa<MCConstantExpr>(getImm());
1027 }
isConstantImmz() const1028 bool isConstantImmz() const {
1029 return isConstantImm() && getConstantImm() == 0;
1030 }
isConstantUImm() const1031 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1032 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1033 }
isSImm() const1034 template <unsigned Bits> bool isSImm() const {
1035 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1036 }
isUImm() const1037 template <unsigned Bits> bool isUImm() const {
1038 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1039 }
isAnyImm() const1040 template <unsigned Bits> bool isAnyImm() const {
1041 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1042 isUInt<Bits>(getConstantImm()))
1043 : isImm();
1044 }
isConstantSImm() const1045 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1046 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
1047 }
isConstantUImmRange() const1048 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1049 return isConstantImm() && getConstantImm() >= Bottom &&
1050 getConstantImm() <= Top;
1051 }
isToken() const1052 bool isToken() const override {
1053 // Note: It's not possible to pretend that other operand kinds are tokens.
1054 // The matcher emitter checks tokens first.
1055 return Kind == k_Token;
1056 }
isMem() const1057 bool isMem() const override { return Kind == k_Memory; }
isConstantMemOff() const1058 bool isConstantMemOff() const {
1059 return isMem() && isa<MCConstantExpr>(getMemOff());
1060 }
1061 // Allow relocation operators.
1062 // FIXME: This predicate and others need to look through binary expressions
1063 // and determine whether a Value is a constant or not.
1064 template <unsigned Bits, unsigned ShiftAmount = 0>
isMemWithSimmOffset() const1065 bool isMemWithSimmOffset() const {
1066 if (!isMem())
1067 return false;
1068 if (!getMemBase()->isGPRAsmReg())
1069 return false;
1070 if (isa<MCTargetExpr>(getMemOff()) ||
1071 (isConstantMemOff() &&
1072 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
1073 return true;
1074 MCValue Res;
1075 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1076 return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
1077 }
isMemWithGRPMM16Base() const1078 bool isMemWithGRPMM16Base() const {
1079 return isMem() && getMemBase()->isMM16AsmReg();
1080 }
isMemWithUimmOffsetSP() const1081 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1082 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1083 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1084 }
isMemWithUimmWordAlignedOffsetSP() const1085 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1086 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1087 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1088 && (getMemBase()->getGPR32Reg() == Mips::SP);
1089 }
isMemWithSimmWordAlignedOffsetGP() const1090 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
1091 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1092 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1093 && (getMemBase()->getGPR32Reg() == Mips::GP);
1094 }
1095 template <unsigned Bits, unsigned ShiftLeftAmount>
isScaledUImm() const1096 bool isScaledUImm() const {
1097 return isConstantImm() &&
1098 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
1099 }
1100 template <unsigned Bits, unsigned ShiftLeftAmount>
isScaledSImm() const1101 bool isScaledSImm() const {
1102 return isConstantImm() &&
1103 isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm());
1104 }
isRegList16() const1105 bool isRegList16() const {
1106 if (!isRegList())
1107 return false;
1108
1109 int Size = RegList.List->size();
1110 if (Size < 2 || Size > 5)
1111 return false;
1112
1113 unsigned R0 = RegList.List->front();
1114 unsigned R1 = RegList.List->back();
1115 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1116 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
1117 return false;
1118
1119 int PrevReg = *RegList.List->begin();
1120 for (int i = 1; i < Size - 1; i++) {
1121 int Reg = (*(RegList.List))[i];
1122 if ( Reg != PrevReg + 1)
1123 return false;
1124 PrevReg = Reg;
1125 }
1126
1127 return true;
1128 }
isInvNum() const1129 bool isInvNum() const { return Kind == k_Immediate; }
isLSAImm() const1130 bool isLSAImm() const {
1131 if (!isConstantImm())
1132 return false;
1133 int64_t Val = getConstantImm();
1134 return 1 <= Val && Val <= 4;
1135 }
isRegList() const1136 bool isRegList() const { return Kind == k_RegList; }
isMovePRegPair() const1137 bool isMovePRegPair() const {
1138 if (Kind != k_RegList || RegList.List->size() != 2)
1139 return false;
1140
1141 unsigned R0 = RegList.List->front();
1142 unsigned R1 = RegList.List->back();
1143
1144 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1145 (R0 == Mips::A1 && R1 == Mips::A3) ||
1146 (R0 == Mips::A2 && R1 == Mips::A3) ||
1147 (R0 == Mips::A0 && R1 == Mips::S5) ||
1148 (R0 == Mips::A0 && R1 == Mips::S6) ||
1149 (R0 == Mips::A0 && R1 == Mips::A1) ||
1150 (R0 == Mips::A0 && R1 == Mips::A2) ||
1151 (R0 == Mips::A0 && R1 == Mips::A3) ||
1152 (R0 == Mips::A1_64 && R1 == Mips::A2_64) ||
1153 (R0 == Mips::A1_64 && R1 == Mips::A3_64) ||
1154 (R0 == Mips::A2_64 && R1 == Mips::A3_64) ||
1155 (R0 == Mips::A0_64 && R1 == Mips::S5_64) ||
1156 (R0 == Mips::A0_64 && R1 == Mips::S6_64) ||
1157 (R0 == Mips::A0_64 && R1 == Mips::A1_64) ||
1158 (R0 == Mips::A0_64 && R1 == Mips::A2_64) ||
1159 (R0 == Mips::A0_64 && R1 == Mips::A3_64))
1160 return true;
1161
1162 return false;
1163 }
1164
getToken() const1165 StringRef getToken() const {
1166 assert(Kind == k_Token && "Invalid access!");
1167 return StringRef(Tok.Data, Tok.Length);
1168 }
isRegPair() const1169 bool isRegPair() const {
1170 return Kind == k_RegPair && RegIdx.Index <= 30;
1171 }
1172
getReg() const1173 unsigned getReg() const override {
1174 // As a special case until we sort out the definition of div/divu, accept
1175 // $0/$zero here so that MCK_ZERO works correctly.
1176 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1177 RegIdx.Kind & RegKind_GPR)
1178 return getGPR32Reg(); // FIXME: GPR64 too
1179
1180 llvm_unreachable("Invalid access!");
1181 return 0;
1182 }
1183
getImm() const1184 const MCExpr *getImm() const {
1185 assert((Kind == k_Immediate) && "Invalid access!");
1186 return Imm.Val;
1187 }
1188
getConstantImm() const1189 int64_t getConstantImm() const {
1190 const MCExpr *Val = getImm();
1191 return static_cast<const MCConstantExpr *>(Val)->getValue();
1192 }
1193
getMemBase() const1194 MipsOperand *getMemBase() const {
1195 assert((Kind == k_Memory) && "Invalid access!");
1196 return Mem.Base;
1197 }
1198
getMemOff() const1199 const MCExpr *getMemOff() const {
1200 assert((Kind == k_Memory) && "Invalid access!");
1201 return Mem.Off;
1202 }
1203
getConstantMemOff() const1204 int64_t getConstantMemOff() const {
1205 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1206 }
1207
getRegList() const1208 const SmallVectorImpl<unsigned> &getRegList() const {
1209 assert((Kind == k_RegList) && "Invalid access!");
1210 return *(RegList.List);
1211 }
1212
getRegPair() const1213 unsigned getRegPair() const {
1214 assert((Kind == k_RegPair) && "Invalid access!");
1215 return RegIdx.Index;
1216 }
1217
CreateToken(StringRef Str,SMLoc S,MipsAsmParser & Parser)1218 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1219 MipsAsmParser &Parser) {
1220 auto Op = make_unique<MipsOperand>(k_Token, Parser);
1221 Op->Tok.Data = Str.data();
1222 Op->Tok.Length = Str.size();
1223 Op->StartLoc = S;
1224 Op->EndLoc = S;
1225 return Op;
1226 }
1227
1228 /// Create a numeric register (e.g. $1). The exact register remains
1229 /// unresolved until an instruction successfully matches
1230 static std::unique_ptr<MipsOperand>
createNumericReg(unsigned Index,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)1231 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
1232 SMLoc E, MipsAsmParser &Parser) {
1233 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
1234 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
1235 }
1236
1237 /// Create a register that is definitely a GPR.
1238 /// This is typically only used for named registers such as $gp.
1239 static std::unique_ptr<MipsOperand>
createGPRReg(unsigned Index,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)1240 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
1241 MipsAsmParser &Parser) {
1242 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
1243 }
1244
1245 /// Create a register that is definitely a FGR.
1246 /// This is typically only used for named registers such as $f0.
1247 static std::unique_ptr<MipsOperand>
createFGRReg(unsigned Index,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)1248 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
1249 MipsAsmParser &Parser) {
1250 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1251 }
1252
1253 /// Create a register that is definitely a HWReg.
1254 /// This is typically only used for named registers such as $hwr_cpunum.
1255 static std::unique_ptr<MipsOperand>
createHWRegsReg(unsigned Index,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)1256 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1257 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1258 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1259 }
1260
1261 /// Create a register that is definitely an FCC.
1262 /// This is typically only used for named registers such as $fcc0.
1263 static std::unique_ptr<MipsOperand>
createFCCReg(unsigned Index,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)1264 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
1265 MipsAsmParser &Parser) {
1266 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1267 }
1268
1269 /// Create a register that is definitely an ACC.
1270 /// This is typically only used for named registers such as $ac0.
1271 static std::unique_ptr<MipsOperand>
createACCReg(unsigned Index,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)1272 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
1273 MipsAsmParser &Parser) {
1274 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1275 }
1276
1277 /// Create a register that is definitely an MSA128.
1278 /// This is typically only used for named registers such as $w0.
1279 static std::unique_ptr<MipsOperand>
createMSA128Reg(unsigned Index,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)1280 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
1281 SMLoc E, MipsAsmParser &Parser) {
1282 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1283 }
1284
1285 /// Create a register that is definitely an MSACtrl.
1286 /// This is typically only used for named registers such as $msaaccess.
1287 static std::unique_ptr<MipsOperand>
createMSACtrlReg(unsigned Index,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)1288 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
1289 SMLoc E, MipsAsmParser &Parser) {
1290 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1291 }
1292
1293 static std::unique_ptr<MipsOperand>
CreateImm(const MCExpr * Val,SMLoc S,SMLoc E,MipsAsmParser & Parser)1294 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1295 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
1296 Op->Imm.Val = Val;
1297 Op->StartLoc = S;
1298 Op->EndLoc = E;
1299 return Op;
1300 }
1301
1302 static std::unique_ptr<MipsOperand>
CreateMem(std::unique_ptr<MipsOperand> Base,const MCExpr * Off,SMLoc S,SMLoc E,MipsAsmParser & Parser)1303 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1304 SMLoc E, MipsAsmParser &Parser) {
1305 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1306 Op->Mem.Base = Base.release();
1307 Op->Mem.Off = Off;
1308 Op->StartLoc = S;
1309 Op->EndLoc = E;
1310 return Op;
1311 }
1312
1313 static std::unique_ptr<MipsOperand>
CreateRegList(SmallVectorImpl<unsigned> & Regs,SMLoc StartLoc,SMLoc EndLoc,MipsAsmParser & Parser)1314 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1315 MipsAsmParser &Parser) {
1316 assert (Regs.size() > 0 && "Empty list not allowed");
1317
1318 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
1319 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
1320 Op->StartLoc = StartLoc;
1321 Op->EndLoc = EndLoc;
1322 return Op;
1323 }
1324
CreateRegPair(const MipsOperand & MOP,SMLoc S,SMLoc E,MipsAsmParser & Parser)1325 static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
1326 SMLoc S, SMLoc E,
1327 MipsAsmParser &Parser) {
1328 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1329 Op->RegIdx.Index = MOP.RegIdx.Index;
1330 Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo;
1331 Op->RegIdx.Kind = MOP.RegIdx.Kind;
1332 Op->StartLoc = S;
1333 Op->EndLoc = E;
1334 return Op;
1335 }
1336
isGPRAsmReg() const1337 bool isGPRAsmReg() const {
1338 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
1339 }
isMM16AsmReg() const1340 bool isMM16AsmReg() const {
1341 if (!(isRegIdx() && RegIdx.Kind))
1342 return false;
1343 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1344 || RegIdx.Index == 16 || RegIdx.Index == 17);
1345 }
isMM16AsmRegZero() const1346 bool isMM16AsmRegZero() const {
1347 if (!(isRegIdx() && RegIdx.Kind))
1348 return false;
1349 return (RegIdx.Index == 0 ||
1350 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1351 RegIdx.Index == 17);
1352 }
isMM16AsmRegMoveP() const1353 bool isMM16AsmRegMoveP() const {
1354 if (!(isRegIdx() && RegIdx.Kind))
1355 return false;
1356 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1357 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1358 }
isFGRAsmReg() const1359 bool isFGRAsmReg() const {
1360 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1361 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
1362 }
isHWRegsAsmReg() const1363 bool isHWRegsAsmReg() const {
1364 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
1365 }
isCCRAsmReg() const1366 bool isCCRAsmReg() const {
1367 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
1368 }
isFCCAsmReg() const1369 bool isFCCAsmReg() const {
1370 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1371 return false;
1372 if (!AsmParser.hasEightFccRegisters())
1373 return RegIdx.Index == 0;
1374 return RegIdx.Index <= 7;
1375 }
isACCAsmReg() const1376 bool isACCAsmReg() const {
1377 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
1378 }
isCOP0AsmReg() const1379 bool isCOP0AsmReg() const {
1380 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1381 }
isCOP2AsmReg() const1382 bool isCOP2AsmReg() const {
1383 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
1384 }
isCOP3AsmReg() const1385 bool isCOP3AsmReg() const {
1386 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1387 }
isMSA128AsmReg() const1388 bool isMSA128AsmReg() const {
1389 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
1390 }
isMSACtrlAsmReg() const1391 bool isMSACtrlAsmReg() const {
1392 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
1393 }
1394
1395 /// getStartLoc - Get the location of the first token of this operand.
getStartLoc() const1396 SMLoc getStartLoc() const override { return StartLoc; }
1397 /// getEndLoc - Get the location of the last token of this operand.
getEndLoc() const1398 SMLoc getEndLoc() const override { return EndLoc; }
1399
~MipsOperand()1400 virtual ~MipsOperand() {
1401 switch (Kind) {
1402 case k_Immediate:
1403 break;
1404 case k_Memory:
1405 delete Mem.Base;
1406 break;
1407 case k_RegList:
1408 delete RegList.List;
1409 case k_RegisterIndex:
1410 case k_Token:
1411 case k_RegPair:
1412 break;
1413 }
1414 }
1415
print(raw_ostream & OS) const1416 void print(raw_ostream &OS) const override {
1417 switch (Kind) {
1418 case k_Immediate:
1419 OS << "Imm<";
1420 OS << *Imm.Val;
1421 OS << ">";
1422 break;
1423 case k_Memory:
1424 OS << "Mem<";
1425 Mem.Base->print(OS);
1426 OS << ", ";
1427 OS << *Mem.Off;
1428 OS << ">";
1429 break;
1430 case k_RegisterIndex:
1431 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1432 break;
1433 case k_Token:
1434 OS << Tok.Data;
1435 break;
1436 case k_RegList:
1437 OS << "RegList< ";
1438 for (auto Reg : (*RegList.List))
1439 OS << Reg << " ";
1440 OS << ">";
1441 break;
1442 case k_RegPair:
1443 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1444 break;
1445 }
1446 }
1447 }; // class MipsOperand
1448 } // namespace
1449
1450 namespace llvm {
1451 extern const MCInstrDesc MipsInsts[];
1452 }
getInstDesc(unsigned Opcode)1453 static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1454 return MipsInsts[Opcode];
1455 }
1456
hasShortDelaySlot(unsigned Opcode)1457 static bool hasShortDelaySlot(unsigned Opcode) {
1458 switch (Opcode) {
1459 case Mips::JALS_MM:
1460 case Mips::JALRS_MM:
1461 case Mips::JALRS16_MM:
1462 case Mips::BGEZALS_MM:
1463 case Mips::BLTZALS_MM:
1464 return true;
1465 default:
1466 return false;
1467 }
1468 }
1469
getSingleMCSymbol(const MCExpr * Expr)1470 static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1471 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1472 return &SRExpr->getSymbol();
1473 }
1474
1475 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1476 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1477 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1478
1479 if (LHSSym)
1480 return LHSSym;
1481
1482 if (RHSSym)
1483 return RHSSym;
1484
1485 return nullptr;
1486 }
1487
1488 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1489 return getSingleMCSymbol(UExpr->getSubExpr());
1490
1491 return nullptr;
1492 }
1493
countMCSymbolRefExpr(const MCExpr * Expr)1494 static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1495 if (isa<MCSymbolRefExpr>(Expr))
1496 return 1;
1497
1498 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1499 return countMCSymbolRefExpr(BExpr->getLHS()) +
1500 countMCSymbolRefExpr(BExpr->getRHS());
1501
1502 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1503 return countMCSymbolRefExpr(UExpr->getSubExpr());
1504
1505 return 0;
1506 }
1507
processInstruction(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)1508 bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
1509 MCStreamer &Out,
1510 const MCSubtargetInfo *STI) {
1511 MipsTargetStreamer &TOut = getTargetStreamer();
1512 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
1513 bool ExpandedJalSym = false;
1514
1515 Inst.setLoc(IDLoc);
1516
1517 if (MCID.isBranch() || MCID.isCall()) {
1518 const unsigned Opcode = Inst.getOpcode();
1519 MCOperand Offset;
1520
1521 switch (Opcode) {
1522 default:
1523 break;
1524 case Mips::BBIT0:
1525 case Mips::BBIT032:
1526 case Mips::BBIT1:
1527 case Mips::BBIT132:
1528 assert(hasCnMips() && "instruction only valid for octeon cpus");
1529 // Fall through
1530
1531 case Mips::BEQ:
1532 case Mips::BNE:
1533 case Mips::BEQ_MM:
1534 case Mips::BNE_MM:
1535 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1536 Offset = Inst.getOperand(2);
1537 if (!Offset.isImm())
1538 break; // We'll deal with this situation later on when applying fixups.
1539 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
1540 return Error(IDLoc, "branch target out of range");
1541 if (OffsetToAlignment(Offset.getImm(),
1542 1LL << (inMicroMipsMode() ? 1 : 2)))
1543 return Error(IDLoc, "branch to misaligned address");
1544 break;
1545 case Mips::BGEZ:
1546 case Mips::BGTZ:
1547 case Mips::BLEZ:
1548 case Mips::BLTZ:
1549 case Mips::BGEZAL:
1550 case Mips::BLTZAL:
1551 case Mips::BC1F:
1552 case Mips::BC1T:
1553 case Mips::BGEZ_MM:
1554 case Mips::BGTZ_MM:
1555 case Mips::BLEZ_MM:
1556 case Mips::BLTZ_MM:
1557 case Mips::BGEZAL_MM:
1558 case Mips::BLTZAL_MM:
1559 case Mips::BC1F_MM:
1560 case Mips::BC1T_MM:
1561 case Mips::BC1EQZC_MMR6:
1562 case Mips::BC1NEZC_MMR6:
1563 case Mips::BC2EQZC_MMR6:
1564 case Mips::BC2NEZC_MMR6:
1565 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1566 Offset = Inst.getOperand(1);
1567 if (!Offset.isImm())
1568 break; // We'll deal with this situation later on when applying fixups.
1569 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
1570 return Error(IDLoc, "branch target out of range");
1571 if (OffsetToAlignment(Offset.getImm(),
1572 1LL << (inMicroMipsMode() ? 1 : 2)))
1573 return Error(IDLoc, "branch to misaligned address");
1574 break;
1575 case Mips::BEQZ16_MM:
1576 case Mips::BEQZC16_MMR6:
1577 case Mips::BNEZ16_MM:
1578 case Mips::BNEZC16_MMR6:
1579 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1580 Offset = Inst.getOperand(1);
1581 if (!Offset.isImm())
1582 break; // We'll deal with this situation later on when applying fixups.
1583 if (!isInt<8>(Offset.getImm()))
1584 return Error(IDLoc, "branch target out of range");
1585 if (OffsetToAlignment(Offset.getImm(), 2LL))
1586 return Error(IDLoc, "branch to misaligned address");
1587 break;
1588 }
1589 }
1590
1591 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1592 // We still accept it but it is a normal nop.
1593 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1594 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1595 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1596 "nop instruction");
1597 }
1598
1599 if (hasCnMips()) {
1600 const unsigned Opcode = Inst.getOpcode();
1601 MCOperand Opnd;
1602 int Imm;
1603
1604 switch (Opcode) {
1605 default:
1606 break;
1607
1608 case Mips::BBIT0:
1609 case Mips::BBIT032:
1610 case Mips::BBIT1:
1611 case Mips::BBIT132:
1612 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1613 // The offset is handled above
1614 Opnd = Inst.getOperand(1);
1615 if (!Opnd.isImm())
1616 return Error(IDLoc, "expected immediate operand kind");
1617 Imm = Opnd.getImm();
1618 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1619 Opcode == Mips::BBIT1 ? 63 : 31))
1620 return Error(IDLoc, "immediate operand value out of range");
1621 if (Imm > 31) {
1622 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1623 : Mips::BBIT132);
1624 Inst.getOperand(1).setImm(Imm - 32);
1625 }
1626 break;
1627
1628 case Mips::SEQi:
1629 case Mips::SNEi:
1630 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1631 Opnd = Inst.getOperand(2);
1632 if (!Opnd.isImm())
1633 return Error(IDLoc, "expected immediate operand kind");
1634 Imm = Opnd.getImm();
1635 if (!isInt<10>(Imm))
1636 return Error(IDLoc, "immediate operand value out of range");
1637 break;
1638 }
1639 }
1640
1641 // This expansion is not in a function called by tryExpandInstruction()
1642 // because the pseudo-instruction doesn't have a distinct opcode.
1643 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1644 inPicMode()) {
1645 warnIfNoMacro(IDLoc);
1646
1647 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1648
1649 // We can do this expansion if there's only 1 symbol in the argument
1650 // expression.
1651 if (countMCSymbolRefExpr(JalExpr) > 1)
1652 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1653
1654 // FIXME: This is checking the expression can be handled by the later stages
1655 // of the assembler. We ought to leave it to those later stages.
1656 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1657
1658 // FIXME: Add support for label+offset operands (currently causes an error).
1659 // FIXME: Add support for forward-declared local symbols.
1660 // FIXME: Add expansion for when the LargeGOT option is enabled.
1661 if (JalSym->isInSection() || JalSym->isTemporary()) {
1662 if (isABI_O32()) {
1663 // If it's a local symbol and the O32 ABI is being used, we expand to:
1664 // lw $25, 0($gp)
1665 // R_(MICRO)MIPS_GOT16 label
1666 // addiu $25, $25, 0
1667 // R_(MICRO)MIPS_LO16 label
1668 // jalr $25
1669 const MCExpr *Got16RelocExpr =
1670 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
1671 const MCExpr *Lo16RelocExpr =
1672 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
1673
1674 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
1675 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
1676 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1677 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
1678 } else if (isABI_N32() || isABI_N64()) {
1679 // If it's a local symbol and the N32/N64 ABIs are being used,
1680 // we expand to:
1681 // lw/ld $25, 0($gp)
1682 // R_(MICRO)MIPS_GOT_DISP label
1683 // jalr $25
1684 const MCExpr *GotDispRelocExpr =
1685 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
1686
1687 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
1688 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
1689 STI);
1690 }
1691 } else {
1692 // If it's an external/weak symbol, we expand to:
1693 // lw/ld $25, 0($gp)
1694 // R_(MICRO)MIPS_CALL16 label
1695 // jalr $25
1696 const MCExpr *Call16RelocExpr =
1697 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
1698
1699 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1700 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
1701 }
1702
1703 MCInst JalrInst;
1704 if (IsCpRestoreSet && inMicroMipsMode())
1705 JalrInst.setOpcode(Mips::JALRS_MM);
1706 else
1707 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
1708 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1709 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1710
1711 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1712 // This relocation is supposed to be an optimization hint for the linker
1713 // and is not necessary for correctness.
1714
1715 Inst = JalrInst;
1716 ExpandedJalSym = true;
1717 }
1718
1719 if (MCID.mayLoad() || MCID.mayStore()) {
1720 // Check the offset of memory operand, if it is a symbol
1721 // reference or immediate we may have to expand instructions.
1722 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1723 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1724 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1725 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1726 MCOperand &Op = Inst.getOperand(i);
1727 if (Op.isImm()) {
1728 int MemOffset = Op.getImm();
1729 if (MemOffset < -32768 || MemOffset > 32767) {
1730 // Offset can't exceed 16bit value.
1731 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
1732 return false;
1733 }
1734 } else if (Op.isExpr()) {
1735 const MCExpr *Expr = Op.getExpr();
1736 if (Expr->getKind() == MCExpr::SymbolRef) {
1737 const MCSymbolRefExpr *SR =
1738 static_cast<const MCSymbolRefExpr *>(Expr);
1739 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
1740 // Expand symbol.
1741 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
1742 return false;
1743 }
1744 } else if (!isEvaluated(Expr)) {
1745 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
1746 return false;
1747 }
1748 }
1749 }
1750 } // for
1751 } // if load/store
1752
1753 if (inMicroMipsMode()) {
1754 if (MCID.mayLoad()) {
1755 // Try to create 16-bit GP relative load instruction.
1756 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1757 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1758 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1759 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1760 MCOperand &Op = Inst.getOperand(i);
1761 if (Op.isImm()) {
1762 int MemOffset = Op.getImm();
1763 MCOperand &DstReg = Inst.getOperand(0);
1764 MCOperand &BaseReg = Inst.getOperand(1);
1765 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
1766 getContext().getRegisterInfo()->getRegClass(
1767 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
1768 (BaseReg.getReg() == Mips::GP ||
1769 BaseReg.getReg() == Mips::GP_64)) {
1770
1771 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
1772 IDLoc, STI);
1773 return false;
1774 }
1775 }
1776 }
1777 } // for
1778 } // if load
1779
1780 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1781
1782 MCOperand Opnd;
1783 int Imm;
1784
1785 switch (Inst.getOpcode()) {
1786 default:
1787 break;
1788 case Mips::ADDIUSP_MM:
1789 Opnd = Inst.getOperand(0);
1790 if (!Opnd.isImm())
1791 return Error(IDLoc, "expected immediate operand kind");
1792 Imm = Opnd.getImm();
1793 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1794 Imm % 4 != 0)
1795 return Error(IDLoc, "immediate operand value out of range");
1796 break;
1797 case Mips::SLL16_MM:
1798 case Mips::SRL16_MM:
1799 Opnd = Inst.getOperand(2);
1800 if (!Opnd.isImm())
1801 return Error(IDLoc, "expected immediate operand kind");
1802 Imm = Opnd.getImm();
1803 if (Imm < 1 || Imm > 8)
1804 return Error(IDLoc, "immediate operand value out of range");
1805 break;
1806 case Mips::LI16_MM:
1807 Opnd = Inst.getOperand(1);
1808 if (!Opnd.isImm())
1809 return Error(IDLoc, "expected immediate operand kind");
1810 Imm = Opnd.getImm();
1811 if (Imm < -1 || Imm > 126)
1812 return Error(IDLoc, "immediate operand value out of range");
1813 break;
1814 case Mips::ADDIUR2_MM:
1815 Opnd = Inst.getOperand(2);
1816 if (!Opnd.isImm())
1817 return Error(IDLoc, "expected immediate operand kind");
1818 Imm = Opnd.getImm();
1819 if (!(Imm == 1 || Imm == -1 ||
1820 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1821 return Error(IDLoc, "immediate operand value out of range");
1822 break;
1823 case Mips::ANDI16_MM:
1824 Opnd = Inst.getOperand(2);
1825 if (!Opnd.isImm())
1826 return Error(IDLoc, "expected immediate operand kind");
1827 Imm = Opnd.getImm();
1828 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1829 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1830 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1831 return Error(IDLoc, "immediate operand value out of range");
1832 break;
1833 case Mips::LBU16_MM:
1834 Opnd = Inst.getOperand(2);
1835 if (!Opnd.isImm())
1836 return Error(IDLoc, "expected immediate operand kind");
1837 Imm = Opnd.getImm();
1838 if (Imm < -1 || Imm > 14)
1839 return Error(IDLoc, "immediate operand value out of range");
1840 break;
1841 case Mips::SB16_MM:
1842 case Mips::SB16_MMR6:
1843 Opnd = Inst.getOperand(2);
1844 if (!Opnd.isImm())
1845 return Error(IDLoc, "expected immediate operand kind");
1846 Imm = Opnd.getImm();
1847 if (Imm < 0 || Imm > 15)
1848 return Error(IDLoc, "immediate operand value out of range");
1849 break;
1850 case Mips::LHU16_MM:
1851 case Mips::SH16_MM:
1852 case Mips::SH16_MMR6:
1853 Opnd = Inst.getOperand(2);
1854 if (!Opnd.isImm())
1855 return Error(IDLoc, "expected immediate operand kind");
1856 Imm = Opnd.getImm();
1857 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1858 return Error(IDLoc, "immediate operand value out of range");
1859 break;
1860 case Mips::LW16_MM:
1861 case Mips::SW16_MM:
1862 case Mips::SW16_MMR6:
1863 Opnd = Inst.getOperand(2);
1864 if (!Opnd.isImm())
1865 return Error(IDLoc, "expected immediate operand kind");
1866 Imm = Opnd.getImm();
1867 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1868 return Error(IDLoc, "immediate operand value out of range");
1869 break;
1870 case Mips::ADDIUPC_MM:
1871 MCOperand Opnd = Inst.getOperand(1);
1872 if (!Opnd.isImm())
1873 return Error(IDLoc, "expected immediate operand kind");
1874 int Imm = Opnd.getImm();
1875 if ((Imm % 4 != 0) || !isInt<25>(Imm))
1876 return Error(IDLoc, "immediate operand value out of range");
1877 break;
1878 }
1879 }
1880
1881 bool FillDelaySlot =
1882 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
1883 if (FillDelaySlot)
1884 TOut.emitDirectiveSetNoReorder();
1885
1886 MacroExpanderResultTy ExpandResult =
1887 tryExpandInstruction(Inst, IDLoc, Out, STI);
1888 switch (ExpandResult) {
1889 case MER_NotAMacro:
1890 Out.EmitInstruction(Inst, *STI);
1891 break;
1892 case MER_Success:
1893 break;
1894 case MER_Fail:
1895 return true;
1896 }
1897
1898 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
1899 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
1900 if (inMicroMipsMode())
1901 TOut.setUsesMicroMips();
1902
1903 // If this instruction has a delay slot and .set reorder is active,
1904 // emit a NOP after it.
1905 if (FillDelaySlot) {
1906 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
1907 TOut.emitDirectiveSetReorder();
1908 }
1909
1910 if ((Inst.getOpcode() == Mips::JalOneReg ||
1911 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
1912 isPicAndNotNxxAbi()) {
1913 if (IsCpRestoreSet) {
1914 // We need a NOP between the JALR and the LW:
1915 // If .set reorder has been used, we've already emitted a NOP.
1916 // If .set noreorder has been used, we need to emit a NOP at this point.
1917 if (!AssemblerOptions.back()->isReorder())
1918 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
1919 STI);
1920
1921 // Load the $gp from the stack.
1922 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
1923 } else
1924 Warning(IDLoc, "no .cprestore used in PIC mode");
1925 }
1926
1927 return false;
1928 }
1929
1930 MipsAsmParser::MacroExpanderResultTy
tryExpandInstruction(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)1931 MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
1932 const MCSubtargetInfo *STI) {
1933 switch (Inst.getOpcode()) {
1934 default:
1935 return MER_NotAMacro;
1936 case Mips::LoadImm32:
1937 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
1938 case Mips::LoadImm64:
1939 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
1940 case Mips::LoadAddrImm32:
1941 case Mips::LoadAddrImm64:
1942 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1943 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1944 "expected immediate operand kind");
1945
1946 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
1947 Inst.getOperand(1),
1948 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
1949 Out, STI)
1950 ? MER_Fail
1951 : MER_Success;
1952 case Mips::LoadAddrReg32:
1953 case Mips::LoadAddrReg64:
1954 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1955 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1956 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
1957 "expected immediate operand kind");
1958
1959 return expandLoadAddress(Inst.getOperand(0).getReg(),
1960 Inst.getOperand(1).getReg(), Inst.getOperand(2),
1961 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
1962 Out, STI)
1963 ? MER_Fail
1964 : MER_Success;
1965 case Mips::B_MM_Pseudo:
1966 case Mips::B_MMR6_Pseudo:
1967 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
1968 : MER_Success;
1969 case Mips::SWM_MM:
1970 case Mips::LWM_MM:
1971 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
1972 : MER_Success;
1973 case Mips::JalOneReg:
1974 case Mips::JalTwoReg:
1975 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
1976 case Mips::BneImm:
1977 case Mips::BeqImm:
1978 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
1979 case Mips::BLT:
1980 case Mips::BLE:
1981 case Mips::BGE:
1982 case Mips::BGT:
1983 case Mips::BLTU:
1984 case Mips::BLEU:
1985 case Mips::BGEU:
1986 case Mips::BGTU:
1987 case Mips::BLTL:
1988 case Mips::BLEL:
1989 case Mips::BGEL:
1990 case Mips::BGTL:
1991 case Mips::BLTUL:
1992 case Mips::BLEUL:
1993 case Mips::BGEUL:
1994 case Mips::BGTUL:
1995 case Mips::BLTImmMacro:
1996 case Mips::BLEImmMacro:
1997 case Mips::BGEImmMacro:
1998 case Mips::BGTImmMacro:
1999 case Mips::BLTUImmMacro:
2000 case Mips::BLEUImmMacro:
2001 case Mips::BGEUImmMacro:
2002 case Mips::BGTUImmMacro:
2003 case Mips::BLTLImmMacro:
2004 case Mips::BLELImmMacro:
2005 case Mips::BGELImmMacro:
2006 case Mips::BGTLImmMacro:
2007 case Mips::BLTULImmMacro:
2008 case Mips::BLEULImmMacro:
2009 case Mips::BGEULImmMacro:
2010 case Mips::BGTULImmMacro:
2011 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2012 case Mips::SDivMacro:
2013 return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2014 : MER_Success;
2015 case Mips::DSDivMacro:
2016 return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2017 : MER_Success;
2018 case Mips::UDivMacro:
2019 return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2020 : MER_Success;
2021 case Mips::DUDivMacro:
2022 return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2023 : MER_Success;
2024 case Mips::PseudoTRUNC_W_S:
2025 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2026 : MER_Success;
2027 case Mips::PseudoTRUNC_W_D32:
2028 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
2029 : MER_Success;
2030 case Mips::PseudoTRUNC_W_D:
2031 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2032 : MER_Success;
2033 case Mips::Ulh:
2034 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2035 case Mips::Ulhu:
2036 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2037 case Mips::Ulw:
2038 return expandUlw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2039 case Mips::NORImm:
2040 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2041 case Mips::ADDi:
2042 case Mips::ADDiu:
2043 case Mips::SLTi:
2044 case Mips::SLTiu:
2045 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2046 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2047 int64_t ImmValue = Inst.getOperand(2).getImm();
2048 if (isInt<16>(ImmValue))
2049 return MER_NotAMacro;
2050 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2051 : MER_Success;
2052 }
2053 return MER_NotAMacro;
2054 case Mips::ANDi:
2055 case Mips::ORi:
2056 case Mips::XORi:
2057 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2058 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2059 int64_t ImmValue = Inst.getOperand(2).getImm();
2060 if (isUInt<16>(ImmValue))
2061 return MER_NotAMacro;
2062 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2063 : MER_Success;
2064 }
2065 return MER_NotAMacro;
2066 case Mips::ROL:
2067 case Mips::ROR:
2068 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2069 case Mips::ROLImm:
2070 case Mips::RORImm:
2071 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2072 case Mips::DROL:
2073 case Mips::DROR:
2074 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2075 case Mips::DROLImm:
2076 case Mips::DRORImm:
2077 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2078 case Mips::ABSMacro:
2079 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2080 }
2081 }
2082
expandJalWithRegs(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)2083 bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
2084 MCStreamer &Out,
2085 const MCSubtargetInfo *STI) {
2086 MipsTargetStreamer &TOut = getTargetStreamer();
2087
2088 // Create a JALR instruction which is going to replace the pseudo-JAL.
2089 MCInst JalrInst;
2090 JalrInst.setLoc(IDLoc);
2091 const MCOperand FirstRegOp = Inst.getOperand(0);
2092 const unsigned Opcode = Inst.getOpcode();
2093
2094 if (Opcode == Mips::JalOneReg) {
2095 // jal $rs => jalr $rs
2096 if (IsCpRestoreSet && inMicroMipsMode()) {
2097 JalrInst.setOpcode(Mips::JALRS16_MM);
2098 JalrInst.addOperand(FirstRegOp);
2099 } else if (inMicroMipsMode()) {
2100 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
2101 JalrInst.addOperand(FirstRegOp);
2102 } else {
2103 JalrInst.setOpcode(Mips::JALR);
2104 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
2105 JalrInst.addOperand(FirstRegOp);
2106 }
2107 } else if (Opcode == Mips::JalTwoReg) {
2108 // jal $rd, $rs => jalr $rd, $rs
2109 if (IsCpRestoreSet && inMicroMipsMode())
2110 JalrInst.setOpcode(Mips::JALRS_MM);
2111 else
2112 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
2113 JalrInst.addOperand(FirstRegOp);
2114 const MCOperand SecondRegOp = Inst.getOperand(1);
2115 JalrInst.addOperand(SecondRegOp);
2116 }
2117 Out.EmitInstruction(JalrInst, *STI);
2118
2119 // If .set reorder is active and branch instruction has a delay slot,
2120 // emit a NOP after it.
2121 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
2122 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2123 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2124 STI);
2125
2126 return false;
2127 }
2128
2129 /// Can the value be represented by a unsigned N-bit value and a shift left?
isShiftedUIntAtAnyPosition(uint64_t x)2130 template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
2131 unsigned BitNum = findFirstSet(x);
2132
2133 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2134 }
2135
2136 /// Load (or add) an immediate into a register.
2137 ///
2138 /// @param ImmValue The immediate to load.
2139 /// @param DstReg The register that will hold the immediate.
2140 /// @param SrcReg A register to add to the immediate or Mips::NoRegister
2141 /// for a simple initialization.
2142 /// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2143 /// @param IsAddress True if the immediate represents an address. False if it
2144 /// is an integer.
2145 /// @param IDLoc Location of the immediate in the source file.
loadImmediate(int64_t ImmValue,unsigned DstReg,unsigned SrcReg,bool Is32BitImm,bool IsAddress,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)2146 bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
2147 unsigned SrcReg, bool Is32BitImm,
2148 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2149 const MCSubtargetInfo *STI) {
2150 MipsTargetStreamer &TOut = getTargetStreamer();
2151
2152 if (!Is32BitImm && !isGP64bit()) {
2153 Error(IDLoc, "instruction requires a 64-bit architecture");
2154 return true;
2155 }
2156
2157 if (Is32BitImm) {
2158 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2159 // Sign extend up to 64-bit so that the predicates match the hardware
2160 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2161 // true.
2162 ImmValue = SignExtend64<32>(ImmValue);
2163 } else {
2164 Error(IDLoc, "instruction requires a 32-bit immediate");
2165 return true;
2166 }
2167 }
2168
2169 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2170 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2171
2172 bool UseSrcReg = false;
2173 if (SrcReg != Mips::NoRegister)
2174 UseSrcReg = true;
2175
2176 unsigned TmpReg = DstReg;
2177 if (UseSrcReg &&
2178 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
2179 // At this point we need AT to perform the expansions and we exit if it is
2180 // not available.
2181 unsigned ATReg = getATReg(IDLoc);
2182 if (!ATReg)
2183 return true;
2184 TmpReg = ATReg;
2185 }
2186
2187 if (isInt<16>(ImmValue)) {
2188 if (!UseSrcReg)
2189 SrcReg = ZeroReg;
2190
2191 // This doesn't quite follow the usual ABI expectations for N32 but matches
2192 // traditional assembler behaviour. N32 would normally use addiu for both
2193 // integers and addresses.
2194 if (IsAddress && !Is32BitImm) {
2195 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
2196 return false;
2197 }
2198
2199 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
2200 return false;
2201 }
2202
2203 if (isUInt<16>(ImmValue)) {
2204 unsigned TmpReg = DstReg;
2205 if (SrcReg == DstReg) {
2206 TmpReg = getATReg(IDLoc);
2207 if (!TmpReg)
2208 return true;
2209 }
2210
2211 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
2212 if (UseSrcReg)
2213 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
2214 return false;
2215 }
2216
2217 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2218 warnIfNoMacro(IDLoc);
2219
2220 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2221 uint16_t Bits15To0 = ImmValue & 0xffff;
2222
2223 if (!Is32BitImm && !isInt<32>(ImmValue)) {
2224 // Traditional behaviour seems to special case this particular value. It's
2225 // not clear why other masks are handled differently.
2226 if (ImmValue == 0xffffffff) {
2227 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2228 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
2229 if (UseSrcReg)
2230 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
2231 return false;
2232 }
2233
2234 // Expand to an ORi instead of a LUi to avoid sign-extending into the
2235 // upper 32 bits.
2236 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2237 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
2238 if (Bits15To0)
2239 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
2240 if (UseSrcReg)
2241 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
2242 return false;
2243 }
2244
2245 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
2246 if (Bits15To0)
2247 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
2248 if (UseSrcReg)
2249 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
2250 return false;
2251 }
2252
2253 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2254 if (Is32BitImm) {
2255 Error(IDLoc, "instruction requires a 32-bit immediate");
2256 return true;
2257 }
2258
2259 // Traditionally, these immediates are shifted as little as possible and as
2260 // such we align the most significant bit to bit 15 of our temporary.
2261 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2262 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2263 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2264 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
2265 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2266 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
2267
2268 if (UseSrcReg)
2269 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
2270
2271 return false;
2272 }
2273
2274 warnIfNoMacro(IDLoc);
2275
2276 // The remaining case is packed with a sequence of dsll and ori with zeros
2277 // being omitted and any neighbouring dsll's being coalesced.
2278 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2279
2280 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2281 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
2282 IDLoc, Out, STI))
2283 return false;
2284
2285 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2286 // skip it and defer the shift to the next chunk.
2287 unsigned ShiftCarriedForwards = 16;
2288 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2289 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2290
2291 if (ImmChunk != 0) {
2292 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2293 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
2294 ShiftCarriedForwards = 0;
2295 }
2296
2297 ShiftCarriedForwards += 16;
2298 }
2299 ShiftCarriedForwards -= 16;
2300
2301 // Finish any remaining shifts left by trailing zeros.
2302 if (ShiftCarriedForwards)
2303 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2304
2305 if (UseSrcReg)
2306 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
2307
2308 return false;
2309 }
2310
expandLoadImm(MCInst & Inst,bool Is32BitImm,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)2311 bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
2312 MCStreamer &Out, const MCSubtargetInfo *STI) {
2313 const MCOperand &ImmOp = Inst.getOperand(1);
2314 assert(ImmOp.isImm() && "expected immediate operand kind");
2315 const MCOperand &DstRegOp = Inst.getOperand(0);
2316 assert(DstRegOp.isReg() && "expected register operand kind");
2317
2318 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
2319 Is32BitImm, false, IDLoc, Out, STI))
2320 return true;
2321
2322 return false;
2323 }
2324
expandLoadAddress(unsigned DstReg,unsigned BaseReg,const MCOperand & Offset,bool Is32BitAddress,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)2325 bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2326 const MCOperand &Offset,
2327 bool Is32BitAddress, SMLoc IDLoc,
2328 MCStreamer &Out,
2329 const MCSubtargetInfo *STI) {
2330 // la can't produce a usable address when addresses are 64-bit.
2331 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2332 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2333 // We currently can't do this because we depend on the equality
2334 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2335 Error(IDLoc, "la used to load 64-bit address");
2336 // Continue as if we had 'dla' instead.
2337 Is32BitAddress = false;
2338 }
2339
2340 // dla requires 64-bit addresses.
2341 if (!Is32BitAddress && !hasMips3()) {
2342 Error(IDLoc, "instruction requires a 64-bit architecture");
2343 return true;
2344 }
2345
2346 if (!Offset.isImm())
2347 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
2348 Is32BitAddress, IDLoc, Out, STI);
2349
2350 if (!ABI.ArePtrs64bit()) {
2351 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2352 Is32BitAddress = true;
2353 }
2354
2355 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
2356 IDLoc, Out, STI);
2357 }
2358
loadAndAddSymbolAddress(const MCExpr * SymExpr,unsigned DstReg,unsigned SrcReg,bool Is32BitSym,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)2359 bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2360 unsigned DstReg, unsigned SrcReg,
2361 bool Is32BitSym, SMLoc IDLoc,
2362 MCStreamer &Out,
2363 const MCSubtargetInfo *STI) {
2364 MipsTargetStreamer &TOut = getTargetStreamer();
2365 bool UseSrcReg = SrcReg != Mips::NoRegister;
2366 warnIfNoMacro(IDLoc);
2367
2368 if (inPicMode() && ABI.IsO32()) {
2369 MCValue Res;
2370 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2371 Error(IDLoc, "expected relocatable expression");
2372 return true;
2373 }
2374 if (Res.getSymB() != nullptr) {
2375 Error(IDLoc, "expected relocatable expression with only one symbol");
2376 return true;
2377 }
2378
2379 // The case where the result register is $25 is somewhat special. If the
2380 // symbol in the final relocation is external and not modified with a
2381 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
2382 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
2383 Res.getConstant() == 0 && !Res.getSymA()->getSymbol().isInSection() &&
2384 !Res.getSymA()->getSymbol().isTemporary()) {
2385 const MCExpr *CallExpr =
2386 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2387 TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
2388 MCOperand::createExpr(CallExpr), IDLoc, STI);
2389 return false;
2390 }
2391
2392 // The remaining cases are:
2393 // External GOT: lw $tmp, %got(symbol+offset)($gp)
2394 // >addiu $tmp, $tmp, %lo(offset)
2395 // >addiu $rd, $tmp, $rs
2396 // Local GOT: lw $tmp, %got(symbol+offset)($gp)
2397 // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
2398 // >addiu $rd, $tmp, $rs
2399 // The addiu's marked with a '>' may be omitted if they are redundant. If
2400 // this happens then the last instruction must use $rd as the result
2401 // register.
2402 const MipsMCExpr *GotExpr =
2403 MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
2404 const MCExpr *LoExpr = nullptr;
2405 if (Res.getSymA()->getSymbol().isInSection() ||
2406 Res.getSymA()->getSymbol().isTemporary())
2407 LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
2408 else if (Res.getConstant() != 0) {
2409 // External symbols fully resolve the symbol with just the %got(symbol)
2410 // but we must still account for any offset to the symbol for expressions
2411 // like symbol+8.
2412 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2413 }
2414
2415 unsigned TmpReg = DstReg;
2416 if (UseSrcReg &&
2417 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2418 SrcReg)) {
2419 // If $rs is the same as $rd, we need to use AT.
2420 // If it is not available we exit.
2421 unsigned ATReg = getATReg(IDLoc);
2422 if (!ATReg)
2423 return true;
2424 TmpReg = ATReg;
2425 }
2426
2427 TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
2428 MCOperand::createExpr(GotExpr), IDLoc, STI);
2429
2430 if (LoExpr)
2431 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2432 IDLoc, STI);
2433
2434 if (UseSrcReg)
2435 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2436
2437 return false;
2438 }
2439
2440 const MipsMCExpr *HiExpr =
2441 MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
2442 const MipsMCExpr *LoExpr =
2443 MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
2444
2445 // This is the 64-bit symbol address expansion.
2446 if (ABI.ArePtrs64bit() && isGP64bit()) {
2447 // We always need AT for the 64-bit expansion.
2448 // If it is not available we exit.
2449 unsigned ATReg = getATReg(IDLoc);
2450 if (!ATReg)
2451 return true;
2452
2453 const MipsMCExpr *HighestExpr =
2454 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
2455 const MipsMCExpr *HigherExpr =
2456 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
2457
2458 if (UseSrcReg &&
2459 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2460 SrcReg)) {
2461 // If $rs is the same as $rd:
2462 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2463 // daddiu $at, $at, %higher(sym)
2464 // dsll $at, $at, 16
2465 // daddiu $at, $at, %hi(sym)
2466 // dsll $at, $at, 16
2467 // daddiu $at, $at, %lo(sym)
2468 // daddu $rd, $at, $rd
2469 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2470 STI);
2471 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
2472 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2473 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2474 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
2475 IDLoc, STI);
2476 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2477 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2478 IDLoc, STI);
2479 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
2480
2481 return false;
2482 }
2483
2484 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2485 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2486 // lui $at, %hi(sym)
2487 // daddiu $rd, $rd, %higher(sym)
2488 // daddiu $at, $at, %lo(sym)
2489 // dsll32 $rd, $rd, 0
2490 // daddu $rd, $rd, $at
2491 // (daddu $rd, $rd, $rs)
2492 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2493 STI);
2494 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2495 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
2496 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2497 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2498 IDLoc, STI);
2499 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
2500 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
2501 if (UseSrcReg)
2502 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
2503
2504 return false;
2505 }
2506
2507 // And now, the 32-bit symbol address expansion:
2508 // If $rs is the same as $rd:
2509 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2510 // ori $at, $at, %lo(sym)
2511 // addu $rd, $at, $rd
2512 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2513 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2514 // ori $rd, $rd, %lo(sym)
2515 // (addu $rd, $rd, $rs)
2516 unsigned TmpReg = DstReg;
2517 if (UseSrcReg &&
2518 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
2519 // If $rs is the same as $rd, we need to use AT.
2520 // If it is not available we exit.
2521 unsigned ATReg = getATReg(IDLoc);
2522 if (!ATReg)
2523 return true;
2524 TmpReg = ATReg;
2525 }
2526
2527 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2528 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2529 IDLoc, STI);
2530
2531 if (UseSrcReg)
2532 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2533 else
2534 assert(
2535 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
2536
2537 return false;
2538 }
2539
expandUncondBranchMMPseudo(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)2540 bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
2541 MCStreamer &Out,
2542 const MCSubtargetInfo *STI) {
2543 MipsTargetStreamer &TOut = getTargetStreamer();
2544
2545 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2546 "unexpected number of operands");
2547
2548 MCOperand Offset = Inst.getOperand(0);
2549 if (Offset.isExpr()) {
2550 Inst.clear();
2551 Inst.setOpcode(Mips::BEQ_MM);
2552 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2553 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2554 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
2555 } else {
2556 assert(Offset.isImm() && "expected immediate operand kind");
2557 if (isInt<11>(Offset.getImm())) {
2558 // If offset fits into 11 bits then this instruction becomes microMIPS
2559 // 16-bit unconditional branch instruction.
2560 if (inMicroMipsMode())
2561 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
2562 } else {
2563 if (!isInt<17>(Offset.getImm()))
2564 Error(IDLoc, "branch target out of range");
2565 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2566 Error(IDLoc, "branch to misaligned address");
2567 Inst.clear();
2568 Inst.setOpcode(Mips::BEQ_MM);
2569 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2570 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2571 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
2572 }
2573 }
2574 Out.EmitInstruction(Inst, *STI);
2575
2576 // If .set reorder is active and branch instruction has a delay slot,
2577 // emit a NOP after it.
2578 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2579 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2580 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
2581
2582 return false;
2583 }
2584
expandBranchImm(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)2585 bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2586 const MCSubtargetInfo *STI) {
2587 MipsTargetStreamer &TOut = getTargetStreamer();
2588 const MCOperand &DstRegOp = Inst.getOperand(0);
2589 assert(DstRegOp.isReg() && "expected register operand kind");
2590
2591 const MCOperand &ImmOp = Inst.getOperand(1);
2592 assert(ImmOp.isImm() && "expected immediate operand kind");
2593
2594 const MCOperand &MemOffsetOp = Inst.getOperand(2);
2595 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
2596 "expected immediate or expression operand");
2597
2598 unsigned OpCode = 0;
2599 switch(Inst.getOpcode()) {
2600 case Mips::BneImm:
2601 OpCode = Mips::BNE;
2602 break;
2603 case Mips::BeqImm:
2604 OpCode = Mips::BEQ;
2605 break;
2606 default:
2607 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2608 break;
2609 }
2610
2611 int64_t ImmValue = ImmOp.getImm();
2612 if (ImmValue == 0)
2613 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2614 STI);
2615 else {
2616 warnIfNoMacro(IDLoc);
2617
2618 unsigned ATReg = getATReg(IDLoc);
2619 if (!ATReg)
2620 return true;
2621
2622 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
2623 IDLoc, Out, STI))
2624 return true;
2625
2626 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
2627 }
2628 return false;
2629 }
2630
expandMemInst(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI,bool IsLoad,bool IsImmOpnd)2631 void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2632 const MCSubtargetInfo *STI, bool IsLoad,
2633 bool IsImmOpnd) {
2634 if (IsLoad) {
2635 expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2636 return;
2637 }
2638 expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2639 }
2640
expandLoadInst(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI,bool IsImmOpnd)2641 void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2642 const MCSubtargetInfo *STI, bool IsImmOpnd) {
2643 MipsTargetStreamer &TOut = getTargetStreamer();
2644
2645 unsigned DstReg = Inst.getOperand(0).getReg();
2646 unsigned BaseReg = Inst.getOperand(1).getReg();
2647
2648 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2649 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
2650 unsigned DstRegClassID =
2651 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
2652 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
2653 (DstRegClassID == Mips::GPR64RegClassID);
2654
2655 if (IsImmOpnd) {
2656 // Try to use DstReg as the temporary.
2657 if (IsGPR && (BaseReg != DstReg)) {
2658 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2659 Inst.getOperand(2).getImm(), DstReg, IDLoc,
2660 STI);
2661 return;
2662 }
2663
2664 // At this point we need AT to perform the expansions and we exit if it is
2665 // not available.
2666 unsigned ATReg = getATReg(IDLoc);
2667 if (!ATReg)
2668 return;
2669
2670 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2671 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
2672 return;
2673 }
2674
2675 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
2676 MCOperand LoOperand = MCOperand::createExpr(
2677 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
2678 MCOperand HiOperand = MCOperand::createExpr(
2679 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
2680
2681 // Try to use DstReg as the temporary.
2682 if (IsGPR && (BaseReg != DstReg)) {
2683 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2684 LoOperand, DstReg, IDLoc, STI);
2685 return;
2686 }
2687
2688 // At this point we need AT to perform the expansions and we exit if it is
2689 // not available.
2690 unsigned ATReg = getATReg(IDLoc);
2691 if (!ATReg)
2692 return;
2693
2694 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2695 LoOperand, ATReg, IDLoc, STI);
2696 }
2697
expandStoreInst(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI,bool IsImmOpnd)2698 void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2699 const MCSubtargetInfo *STI,
2700 bool IsImmOpnd) {
2701 MipsTargetStreamer &TOut = getTargetStreamer();
2702
2703 unsigned SrcReg = Inst.getOperand(0).getReg();
2704 unsigned BaseReg = Inst.getOperand(1).getReg();
2705
2706 if (IsImmOpnd) {
2707 TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
2708 Inst.getOperand(2).getImm(),
2709 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
2710 return;
2711 }
2712
2713 unsigned ATReg = getATReg(IDLoc);
2714 if (!ATReg)
2715 return;
2716
2717 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
2718 MCOperand LoOperand = MCOperand::createExpr(
2719 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
2720 MCOperand HiOperand = MCOperand::createExpr(
2721 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
2722 TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
2723 LoOperand, ATReg, IDLoc, STI);
2724 }
2725
expandLoadStoreMultiple(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)2726 bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2727 MCStreamer &Out,
2728 const MCSubtargetInfo *STI) {
2729 unsigned OpNum = Inst.getNumOperands();
2730 unsigned Opcode = Inst.getOpcode();
2731 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2732
2733 assert (Inst.getOperand(OpNum - 1).isImm() &&
2734 Inst.getOperand(OpNum - 2).isReg() &&
2735 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2736
2737 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2738 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2739 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
2740 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
2741 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
2742 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
2743 // It can be implemented as SWM16 or LWM16 instruction.
2744 if (inMicroMipsMode() && hasMips32r6())
2745 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
2746 else
2747 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2748 }
2749
2750 Inst.setOpcode(NewOpcode);
2751 Out.EmitInstruction(Inst, *STI);
2752 return false;
2753 }
2754
expandCondBranches(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)2755 bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2756 MCStreamer &Out,
2757 const MCSubtargetInfo *STI) {
2758 MipsTargetStreamer &TOut = getTargetStreamer();
2759 bool EmittedNoMacroWarning = false;
2760 unsigned PseudoOpcode = Inst.getOpcode();
2761 unsigned SrcReg = Inst.getOperand(0).getReg();
2762 const MCOperand &TrgOp = Inst.getOperand(1);
2763 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2764
2765 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
2766 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
2767
2768 unsigned TrgReg;
2769 if (TrgOp.isReg())
2770 TrgReg = TrgOp.getReg();
2771 else if (TrgOp.isImm()) {
2772 warnIfNoMacro(IDLoc);
2773 EmittedNoMacroWarning = true;
2774
2775 TrgReg = getATReg(IDLoc);
2776 if (!TrgReg)
2777 return true;
2778
2779 switch(PseudoOpcode) {
2780 default:
2781 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2782 case Mips::BLTImmMacro:
2783 PseudoOpcode = Mips::BLT;
2784 break;
2785 case Mips::BLEImmMacro:
2786 PseudoOpcode = Mips::BLE;
2787 break;
2788 case Mips::BGEImmMacro:
2789 PseudoOpcode = Mips::BGE;
2790 break;
2791 case Mips::BGTImmMacro:
2792 PseudoOpcode = Mips::BGT;
2793 break;
2794 case Mips::BLTUImmMacro:
2795 PseudoOpcode = Mips::BLTU;
2796 break;
2797 case Mips::BLEUImmMacro:
2798 PseudoOpcode = Mips::BLEU;
2799 break;
2800 case Mips::BGEUImmMacro:
2801 PseudoOpcode = Mips::BGEU;
2802 break;
2803 case Mips::BGTUImmMacro:
2804 PseudoOpcode = Mips::BGTU;
2805 break;
2806 case Mips::BLTLImmMacro:
2807 PseudoOpcode = Mips::BLTL;
2808 break;
2809 case Mips::BLELImmMacro:
2810 PseudoOpcode = Mips::BLEL;
2811 break;
2812 case Mips::BGELImmMacro:
2813 PseudoOpcode = Mips::BGEL;
2814 break;
2815 case Mips::BGTLImmMacro:
2816 PseudoOpcode = Mips::BGTL;
2817 break;
2818 case Mips::BLTULImmMacro:
2819 PseudoOpcode = Mips::BLTUL;
2820 break;
2821 case Mips::BLEULImmMacro:
2822 PseudoOpcode = Mips::BLEUL;
2823 break;
2824 case Mips::BGEULImmMacro:
2825 PseudoOpcode = Mips::BGEUL;
2826 break;
2827 case Mips::BGTULImmMacro:
2828 PseudoOpcode = Mips::BGTUL;
2829 break;
2830 }
2831
2832 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
2833 false, IDLoc, Out, STI))
2834 return true;
2835 }
2836
2837 switch (PseudoOpcode) {
2838 case Mips::BLT:
2839 case Mips::BLTU:
2840 case Mips::BLTL:
2841 case Mips::BLTUL:
2842 AcceptsEquality = false;
2843 ReverseOrderSLT = false;
2844 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2845 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
2846 ZeroSrcOpcode = Mips::BGTZ;
2847 ZeroTrgOpcode = Mips::BLTZ;
2848 break;
2849 case Mips::BLE:
2850 case Mips::BLEU:
2851 case Mips::BLEL:
2852 case Mips::BLEUL:
2853 AcceptsEquality = true;
2854 ReverseOrderSLT = true;
2855 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2856 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
2857 ZeroSrcOpcode = Mips::BGEZ;
2858 ZeroTrgOpcode = Mips::BLEZ;
2859 break;
2860 case Mips::BGE:
2861 case Mips::BGEU:
2862 case Mips::BGEL:
2863 case Mips::BGEUL:
2864 AcceptsEquality = true;
2865 ReverseOrderSLT = false;
2866 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2867 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
2868 ZeroSrcOpcode = Mips::BLEZ;
2869 ZeroTrgOpcode = Mips::BGEZ;
2870 break;
2871 case Mips::BGT:
2872 case Mips::BGTU:
2873 case Mips::BGTL:
2874 case Mips::BGTUL:
2875 AcceptsEquality = false;
2876 ReverseOrderSLT = true;
2877 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2878 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
2879 ZeroSrcOpcode = Mips::BLTZ;
2880 ZeroTrgOpcode = Mips::BGTZ;
2881 break;
2882 default:
2883 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2884 }
2885
2886 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2887 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2888 if (IsSrcRegZero && IsTrgRegZero) {
2889 // FIXME: All of these Opcode-specific if's are needed for compatibility
2890 // with GAS' behaviour. However, they may not generate the most efficient
2891 // code in some circumstances.
2892 if (PseudoOpcode == Mips::BLT) {
2893 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2894 IDLoc, STI);
2895 return false;
2896 }
2897 if (PseudoOpcode == Mips::BLE) {
2898 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2899 IDLoc, STI);
2900 Warning(IDLoc, "branch is always taken");
2901 return false;
2902 }
2903 if (PseudoOpcode == Mips::BGE) {
2904 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2905 IDLoc, STI);
2906 Warning(IDLoc, "branch is always taken");
2907 return false;
2908 }
2909 if (PseudoOpcode == Mips::BGT) {
2910 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2911 IDLoc, STI);
2912 return false;
2913 }
2914 if (PseudoOpcode == Mips::BGTU) {
2915 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
2916 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
2917 return false;
2918 }
2919 if (AcceptsEquality) {
2920 // If both registers are $0 and the pseudo-branch accepts equality, it
2921 // will always be taken, so we emit an unconditional branch.
2922 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2923 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
2924 Warning(IDLoc, "branch is always taken");
2925 return false;
2926 }
2927 // If both registers are $0 and the pseudo-branch does not accept
2928 // equality, it will never be taken, so we don't have to emit anything.
2929 return false;
2930 }
2931 if (IsSrcRegZero || IsTrgRegZero) {
2932 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2933 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2934 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2935 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2936 // the pseudo-branch will never be taken, so we don't emit anything.
2937 // This only applies to unsigned pseudo-branches.
2938 return false;
2939 }
2940 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2941 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2942 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2943 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2944 // the pseudo-branch will always be taken, so we emit an unconditional
2945 // branch.
2946 // This only applies to unsigned pseudo-branches.
2947 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2948 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
2949 Warning(IDLoc, "branch is always taken");
2950 return false;
2951 }
2952 if (IsUnsigned) {
2953 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2954 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2955 // the pseudo-branch will be taken only when the non-zero register is
2956 // different from 0, so we emit a BNEZ.
2957 //
2958 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2959 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2960 // the pseudo-branch will be taken only when the non-zero register is
2961 // equal to 0, so we emit a BEQZ.
2962 //
2963 // Because only BLEU and BGEU branch on equality, we can use the
2964 // AcceptsEquality variable to decide when to emit the BEQZ.
2965 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
2966 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
2967 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
2968 return false;
2969 }
2970 // If we have a signed pseudo-branch and one of the registers is $0,
2971 // we can use an appropriate compare-to-zero branch. We select which one
2972 // to use in the switch statement above.
2973 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
2974 IsSrcRegZero ? TrgReg : SrcReg,
2975 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
2976 return false;
2977 }
2978
2979 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2980 // expansions. If it is not available, we return.
2981 unsigned ATRegNum = getATReg(IDLoc);
2982 if (!ATRegNum)
2983 return true;
2984
2985 if (!EmittedNoMacroWarning)
2986 warnIfNoMacro(IDLoc);
2987
2988 // SLT fits well with 2 of our 4 pseudo-branches:
2989 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2990 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2991 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2992 // This is accomplished by using a BNEZ with the result of the SLT.
2993 //
2994 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2995 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2996 // Because only BGE and BLE branch on equality, we can use the
2997 // AcceptsEquality variable to decide when to emit the BEQZ.
2998 // Note that the order of the SLT arguments doesn't change between
2999 // opposites.
3000 //
3001 // The same applies to the unsigned variants, except that SLTu is used
3002 // instead of SLT.
3003 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
3004 ReverseOrderSLT ? TrgReg : SrcReg,
3005 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
3006
3007 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
3008 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
3009 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
3010 STI);
3011 return false;
3012 }
3013
expandDiv(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI,const bool IsMips64,const bool Signed)3014 bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3015 const MCSubtargetInfo *STI, const bool IsMips64,
3016 const bool Signed) {
3017 MipsTargetStreamer &TOut = getTargetStreamer();
3018
3019 warnIfNoMacro(IDLoc);
3020
3021 const MCOperand &RdRegOp = Inst.getOperand(0);
3022 assert(RdRegOp.isReg() && "expected register operand kind");
3023 unsigned RdReg = RdRegOp.getReg();
3024
3025 const MCOperand &RsRegOp = Inst.getOperand(1);
3026 assert(RsRegOp.isReg() && "expected register operand kind");
3027 unsigned RsReg = RsRegOp.getReg();
3028
3029 const MCOperand &RtRegOp = Inst.getOperand(2);
3030 assert(RtRegOp.isReg() && "expected register operand kind");
3031 unsigned RtReg = RtRegOp.getReg();
3032 unsigned DivOp;
3033 unsigned ZeroReg;
3034
3035 if (IsMips64) {
3036 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
3037 ZeroReg = Mips::ZERO_64;
3038 } else {
3039 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
3040 ZeroReg = Mips::ZERO;
3041 }
3042
3043 bool UseTraps = useTraps();
3044
3045 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
3046 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
3047 Warning(IDLoc, "dividing zero by zero");
3048 if (IsMips64) {
3049 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
3050 if (UseTraps) {
3051 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
3052 return false;
3053 }
3054
3055 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
3056 return false;
3057 }
3058 } else {
3059 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
3060 return false;
3061 }
3062 }
3063
3064 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
3065 Warning(IDLoc, "division by zero");
3066 if (Signed) {
3067 if (UseTraps) {
3068 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
3069 return false;
3070 }
3071
3072 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
3073 return false;
3074 }
3075 }
3076
3077 // FIXME: The values for these two BranchTarget variables may be different in
3078 // micromips. These magic numbers need to be removed.
3079 unsigned BranchTargetNoTraps;
3080 unsigned BranchTarget;
3081
3082 if (UseTraps) {
3083 BranchTarget = IsMips64 ? 12 : 8;
3084 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
3085 } else {
3086 BranchTarget = IsMips64 ? 20 : 16;
3087 BranchTargetNoTraps = 8;
3088 // Branch to the li instruction.
3089 TOut.emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc, STI);
3090 }
3091
3092 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
3093
3094 if (!UseTraps)
3095 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
3096
3097 if (!Signed) {
3098 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
3099 return false;
3100 }
3101
3102 unsigned ATReg = getATReg(IDLoc);
3103 if (!ATReg)
3104 return true;
3105
3106 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
3107 if (IsMips64) {
3108 // Branch to the mflo instruction.
3109 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3110 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
3111 TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
3112 } else {
3113 // Branch to the mflo instruction.
3114 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3115 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
3116 }
3117
3118 if (UseTraps)
3119 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
3120 else {
3121 // Branch to the mflo instruction.
3122 TOut.emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, STI);
3123 TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
3124 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
3125 }
3126 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
3127 return false;
3128 }
3129
expandTrunc(MCInst & Inst,bool IsDouble,bool Is64FPU,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)3130 bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
3131 SMLoc IDLoc, MCStreamer &Out,
3132 const MCSubtargetInfo *STI) {
3133 MipsTargetStreamer &TOut = getTargetStreamer();
3134
3135 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
3136 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
3137 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
3138
3139 unsigned FirstReg = Inst.getOperand(0).getReg();
3140 unsigned SecondReg = Inst.getOperand(1).getReg();
3141 unsigned ThirdReg = Inst.getOperand(2).getReg();
3142
3143 if (hasMips1() && !hasMips2()) {
3144 unsigned ATReg = getATReg(IDLoc);
3145 if (!ATReg)
3146 return true;
3147 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3148 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3149 TOut.emitNop(IDLoc, STI);
3150 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
3151 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
3152 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
3153 TOut.emitNop(IDLoc, STI);
3154 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
3155 : Mips::CVT_W_S,
3156 FirstReg, SecondReg, IDLoc, STI);
3157 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
3158 TOut.emitNop(IDLoc, STI);
3159 return false;
3160 }
3161
3162 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
3163 : Mips::TRUNC_W_S,
3164 FirstReg, SecondReg, IDLoc, STI);
3165
3166 return false;
3167 }
3168
expandUlh(MCInst & Inst,bool Signed,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)3169 bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
3170 MCStreamer &Out, const MCSubtargetInfo *STI) {
3171 MipsTargetStreamer &TOut = getTargetStreamer();
3172
3173 if (hasMips32r6() || hasMips64r6()) {
3174 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3175 return false;
3176 }
3177
3178 warnIfNoMacro(IDLoc);
3179
3180 const MCOperand &DstRegOp = Inst.getOperand(0);
3181 assert(DstRegOp.isReg() && "expected register operand kind");
3182
3183 const MCOperand &SrcRegOp = Inst.getOperand(1);
3184 assert(SrcRegOp.isReg() && "expected register operand kind");
3185
3186 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3187 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3188
3189 unsigned DstReg = DstRegOp.getReg();
3190 unsigned SrcReg = SrcRegOp.getReg();
3191 int64_t OffsetValue = OffsetImmOp.getImm();
3192
3193 // NOTE: We always need AT for ULHU, as it is always used as the source
3194 // register for one of the LBu's.
3195 unsigned ATReg = getATReg(IDLoc);
3196 if (!ATReg)
3197 return true;
3198
3199 // When the value of offset+1 does not fit in 16 bits, we have to load the
3200 // offset in AT, (D)ADDu the original source register (if there was one), and
3201 // then use AT as the source register for the 2 generated LBu's.
3202 bool LoadedOffsetInAT = false;
3203 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3204 LoadedOffsetInAT = true;
3205
3206 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
3207 true, IDLoc, Out, STI))
3208 return true;
3209
3210 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3211 // because it will make our output more similar to GAS'. For example,
3212 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3213 // instead of just an "ori $1, $9, 32768".
3214 // NOTE: If there is no source register specified in the ULHU, the parser
3215 // will interpret it as $0.
3216 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3217 TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI);
3218 }
3219
3220 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3221 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3222 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3223
3224 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3225 if (isLittle()) {
3226 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3227 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3228 } else {
3229 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3230 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3231 }
3232
3233 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3234
3235 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
3236 FirstLbuOffset, IDLoc, STI);
3237
3238 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
3239 STI);
3240
3241 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
3242
3243 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
3244
3245 return false;
3246 }
3247
expandUlw(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)3248 bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3249 const MCSubtargetInfo *STI) {
3250 MipsTargetStreamer &TOut = getTargetStreamer();
3251
3252 if (hasMips32r6() || hasMips64r6()) {
3253 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3254 return false;
3255 }
3256
3257 const MCOperand &DstRegOp = Inst.getOperand(0);
3258 assert(DstRegOp.isReg() && "expected register operand kind");
3259
3260 const MCOperand &SrcRegOp = Inst.getOperand(1);
3261 assert(SrcRegOp.isReg() && "expected register operand kind");
3262
3263 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3264 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3265
3266 unsigned SrcReg = SrcRegOp.getReg();
3267 int64_t OffsetValue = OffsetImmOp.getImm();
3268 unsigned ATReg = 0;
3269
3270 // When the value of offset+3 does not fit in 16 bits, we have to load the
3271 // offset in AT, (D)ADDu the original source register (if there was one), and
3272 // then use AT as the source register for the generated LWL and LWR.
3273 bool LoadedOffsetInAT = false;
3274 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3275 ATReg = getATReg(IDLoc);
3276 if (!ATReg)
3277 return true;
3278 LoadedOffsetInAT = true;
3279
3280 warnIfNoMacro(IDLoc);
3281
3282 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
3283 true, IDLoc, Out, STI))
3284 return true;
3285
3286 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3287 // because it will make our output more similar to GAS'. For example,
3288 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3289 // instead of just an "ori $1, $9, 32768".
3290 // NOTE: If there is no source register specified in the ULW, the parser
3291 // will interpret it as $0.
3292 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3293 TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI);
3294 }
3295
3296 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3297 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3298 if (isLittle()) {
3299 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3300 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3301 } else {
3302 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3303 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3304 }
3305
3306 TOut.emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
3307 STI);
3308
3309 TOut.emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset,
3310 IDLoc, STI);
3311
3312 return false;
3313 }
3314
expandAliasImmediate(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)3315 bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
3316 MCStreamer &Out,
3317 const MCSubtargetInfo *STI) {
3318 MipsTargetStreamer &TOut = getTargetStreamer();
3319
3320 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3321 assert (Inst.getOperand(0).isReg() &&
3322 Inst.getOperand(1).isReg() &&
3323 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3324
3325 unsigned ATReg = Mips::NoRegister;
3326 unsigned FinalDstReg = Mips::NoRegister;
3327 unsigned DstReg = Inst.getOperand(0).getReg();
3328 unsigned SrcReg = Inst.getOperand(1).getReg();
3329 int64_t ImmValue = Inst.getOperand(2).getImm();
3330
3331 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3332
3333 unsigned FinalOpcode = Inst.getOpcode();
3334
3335 if (DstReg == SrcReg) {
3336 ATReg = getATReg(Inst.getLoc());
3337 if (!ATReg)
3338 return true;
3339 FinalDstReg = DstReg;
3340 DstReg = ATReg;
3341 }
3342
3343 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
3344 switch (FinalOpcode) {
3345 default:
3346 llvm_unreachable("unimplemented expansion");
3347 case (Mips::ADDi):
3348 FinalOpcode = Mips::ADD;
3349 break;
3350 case (Mips::ADDiu):
3351 FinalOpcode = Mips::ADDu;
3352 break;
3353 case (Mips::ANDi):
3354 FinalOpcode = Mips::AND;
3355 break;
3356 case (Mips::NORImm):
3357 FinalOpcode = Mips::NOR;
3358 break;
3359 case (Mips::ORi):
3360 FinalOpcode = Mips::OR;
3361 break;
3362 case (Mips::SLTi):
3363 FinalOpcode = Mips::SLT;
3364 break;
3365 case (Mips::SLTiu):
3366 FinalOpcode = Mips::SLTu;
3367 break;
3368 case (Mips::XORi):
3369 FinalOpcode = Mips::XOR;
3370 break;
3371 }
3372
3373 if (FinalDstReg == Mips::NoRegister)
3374 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
3375 else
3376 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
3377 return false;
3378 }
3379 return true;
3380 }
3381
expandRotation(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)3382 bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3383 const MCSubtargetInfo *STI) {
3384 MipsTargetStreamer &TOut = getTargetStreamer();
3385 unsigned ATReg = Mips::NoRegister;
3386 unsigned DReg = Inst.getOperand(0).getReg();
3387 unsigned SReg = Inst.getOperand(1).getReg();
3388 unsigned TReg = Inst.getOperand(2).getReg();
3389 unsigned TmpReg = DReg;
3390
3391 unsigned FirstShift = Mips::NOP;
3392 unsigned SecondShift = Mips::NOP;
3393
3394 if (hasMips32r2()) {
3395
3396 if (DReg == SReg) {
3397 TmpReg = getATReg(Inst.getLoc());
3398 if (!TmpReg)
3399 return true;
3400 }
3401
3402 if (Inst.getOpcode() == Mips::ROL) {
3403 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3404 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
3405 return false;
3406 }
3407
3408 if (Inst.getOpcode() == Mips::ROR) {
3409 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
3410 return false;
3411 }
3412
3413 return true;
3414 }
3415
3416 if (hasMips32()) {
3417
3418 switch (Inst.getOpcode()) {
3419 default:
3420 llvm_unreachable("unexpected instruction opcode");
3421 case Mips::ROL:
3422 FirstShift = Mips::SRLV;
3423 SecondShift = Mips::SLLV;
3424 break;
3425 case Mips::ROR:
3426 FirstShift = Mips::SLLV;
3427 SecondShift = Mips::SRLV;
3428 break;
3429 }
3430
3431 ATReg = getATReg(Inst.getLoc());
3432 if (!ATReg)
3433 return true;
3434
3435 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3436 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3437 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3438 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
3439
3440 return false;
3441 }
3442
3443 return true;
3444 }
3445
expandRotationImm(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)3446 bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
3447 MCStreamer &Out,
3448 const MCSubtargetInfo *STI) {
3449 MipsTargetStreamer &TOut = getTargetStreamer();
3450 unsigned ATReg = Mips::NoRegister;
3451 unsigned DReg = Inst.getOperand(0).getReg();
3452 unsigned SReg = Inst.getOperand(1).getReg();
3453 int64_t ImmValue = Inst.getOperand(2).getImm();
3454
3455 unsigned FirstShift = Mips::NOP;
3456 unsigned SecondShift = Mips::NOP;
3457
3458 if (hasMips32r2()) {
3459
3460 if (Inst.getOpcode() == Mips::ROLImm) {
3461 uint64_t MaxShift = 32;
3462 uint64_t ShiftValue = ImmValue;
3463 if (ImmValue != 0)
3464 ShiftValue = MaxShift - ImmValue;
3465 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
3466 return false;
3467 }
3468
3469 if (Inst.getOpcode() == Mips::RORImm) {
3470 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
3471 return false;
3472 }
3473
3474 return true;
3475 }
3476
3477 if (hasMips32()) {
3478
3479 if (ImmValue == 0) {
3480 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
3481 return false;
3482 }
3483
3484 switch (Inst.getOpcode()) {
3485 default:
3486 llvm_unreachable("unexpected instruction opcode");
3487 case Mips::ROLImm:
3488 FirstShift = Mips::SLL;
3489 SecondShift = Mips::SRL;
3490 break;
3491 case Mips::RORImm:
3492 FirstShift = Mips::SRL;
3493 SecondShift = Mips::SLL;
3494 break;
3495 }
3496
3497 ATReg = getATReg(Inst.getLoc());
3498 if (!ATReg)
3499 return true;
3500
3501 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
3502 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
3503 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
3504
3505 return false;
3506 }
3507
3508 return true;
3509 }
3510
expandDRotation(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)3511 bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3512 const MCSubtargetInfo *STI) {
3513 MipsTargetStreamer &TOut = getTargetStreamer();
3514 unsigned ATReg = Mips::NoRegister;
3515 unsigned DReg = Inst.getOperand(0).getReg();
3516 unsigned SReg = Inst.getOperand(1).getReg();
3517 unsigned TReg = Inst.getOperand(2).getReg();
3518 unsigned TmpReg = DReg;
3519
3520 unsigned FirstShift = Mips::NOP;
3521 unsigned SecondShift = Mips::NOP;
3522
3523 if (hasMips64r2()) {
3524
3525 if (TmpReg == SReg) {
3526 TmpReg = getATReg(Inst.getLoc());
3527 if (!TmpReg)
3528 return true;
3529 }
3530
3531 if (Inst.getOpcode() == Mips::DROL) {
3532 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3533 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
3534 return false;
3535 }
3536
3537 if (Inst.getOpcode() == Mips::DROR) {
3538 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
3539 return false;
3540 }
3541
3542 return true;
3543 }
3544
3545 if (hasMips64()) {
3546
3547 switch (Inst.getOpcode()) {
3548 default:
3549 llvm_unreachable("unexpected instruction opcode");
3550 case Mips::DROL:
3551 FirstShift = Mips::DSRLV;
3552 SecondShift = Mips::DSLLV;
3553 break;
3554 case Mips::DROR:
3555 FirstShift = Mips::DSLLV;
3556 SecondShift = Mips::DSRLV;
3557 break;
3558 }
3559
3560 ATReg = getATReg(Inst.getLoc());
3561 if (!ATReg)
3562 return true;
3563
3564 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3565 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3566 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3567 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
3568
3569 return false;
3570 }
3571
3572 return true;
3573 }
3574
expandDRotationImm(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)3575 bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
3576 MCStreamer &Out,
3577 const MCSubtargetInfo *STI) {
3578 MipsTargetStreamer &TOut = getTargetStreamer();
3579 unsigned ATReg = Mips::NoRegister;
3580 unsigned DReg = Inst.getOperand(0).getReg();
3581 unsigned SReg = Inst.getOperand(1).getReg();
3582 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
3583
3584 unsigned FirstShift = Mips::NOP;
3585 unsigned SecondShift = Mips::NOP;
3586
3587 MCInst TmpInst;
3588
3589 if (hasMips64r2()) {
3590
3591 unsigned FinalOpcode = Mips::NOP;
3592 if (ImmValue == 0)
3593 FinalOpcode = Mips::DROTR;
3594 else if (ImmValue % 32 == 0)
3595 FinalOpcode = Mips::DROTR32;
3596 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
3597 if (Inst.getOpcode() == Mips::DROLImm)
3598 FinalOpcode = Mips::DROTR32;
3599 else
3600 FinalOpcode = Mips::DROTR;
3601 } else if (ImmValue >= 33) {
3602 if (Inst.getOpcode() == Mips::DROLImm)
3603 FinalOpcode = Mips::DROTR;
3604 else
3605 FinalOpcode = Mips::DROTR32;
3606 }
3607
3608 uint64_t ShiftValue = ImmValue % 32;
3609 if (Inst.getOpcode() == Mips::DROLImm)
3610 ShiftValue = (32 - ImmValue % 32) % 32;
3611
3612 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
3613
3614 return false;
3615 }
3616
3617 if (hasMips64()) {
3618
3619 if (ImmValue == 0) {
3620 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
3621 return false;
3622 }
3623
3624 switch (Inst.getOpcode()) {
3625 default:
3626 llvm_unreachable("unexpected instruction opcode");
3627 case Mips::DROLImm:
3628 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3629 FirstShift = Mips::DSLL;
3630 SecondShift = Mips::DSRL32;
3631 }
3632 if (ImmValue == 32) {
3633 FirstShift = Mips::DSLL32;
3634 SecondShift = Mips::DSRL32;
3635 }
3636 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3637 FirstShift = Mips::DSLL32;
3638 SecondShift = Mips::DSRL;
3639 }
3640 break;
3641 case Mips::DRORImm:
3642 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3643 FirstShift = Mips::DSRL;
3644 SecondShift = Mips::DSLL32;
3645 }
3646 if (ImmValue == 32) {
3647 FirstShift = Mips::DSRL32;
3648 SecondShift = Mips::DSLL32;
3649 }
3650 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3651 FirstShift = Mips::DSRL32;
3652 SecondShift = Mips::DSLL;
3653 }
3654 break;
3655 }
3656
3657 ATReg = getATReg(Inst.getLoc());
3658 if (!ATReg)
3659 return true;
3660
3661 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
3662 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
3663 Inst.getLoc(), STI);
3664 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
3665
3666 return false;
3667 }
3668
3669 return true;
3670 }
3671
expandAbs(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)3672 bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3673 const MCSubtargetInfo *STI) {
3674 MipsTargetStreamer &TOut = getTargetStreamer();
3675 unsigned FirstRegOp = Inst.getOperand(0).getReg();
3676 unsigned SecondRegOp = Inst.getOperand(1).getReg();
3677
3678 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
3679 if (FirstRegOp != SecondRegOp)
3680 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
3681 else
3682 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
3683 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
3684
3685 return false;
3686 }
3687
checkTargetMatchPredicate(MCInst & Inst)3688 unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3689 switch (Inst.getOpcode()) {
3690 // As described by the Mips32r2 spec, the registers Rd and Rs for
3691 // jalr.hb must be different.
3692 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
3693 // and registers Rd and Base for microMIPS lwp instruction
3694 case Mips::JALR_HB:
3695 case Mips::JALRC_HB_MMR6:
3696 case Mips::JALRC_MMR6:
3697 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
3698 return Match_RequiresDifferentSrcAndDst;
3699 return Match_Success;
3700 case Mips::LWP_MM:
3701 case Mips::LWP_MMR6:
3702 if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
3703 return Match_RequiresDifferentSrcAndDst;
3704 return Match_Success;
3705 // As described the MIPSR6 spec, the compact branches that compare registers
3706 // must:
3707 // a) Not use the zero register.
3708 // b) Not use the same register twice.
3709 // c) rs < rt for bnec, beqc.
3710 // NB: For this case, the encoding will swap the operands as their
3711 // ordering doesn't matter. GAS performs this transformation too.
3712 // Hence, that constraint does not have to be enforced.
3713 //
3714 // The compact branches that branch iff the signed addition of two registers
3715 // would overflow must have rs >= rt. That can be handled like beqc/bnec with
3716 // operand swapping. They do not have restriction of using the zero register.
3717 case Mips::BLEZC:
3718 case Mips::BGEZC:
3719 case Mips::BGTZC:
3720 case Mips::BLTZC:
3721 case Mips::BEQZC:
3722 case Mips::BNEZC:
3723 if (Inst.getOperand(0).getReg() == Mips::ZERO)
3724 return Match_RequiresNoZeroRegister;
3725 return Match_Success;
3726 case Mips::BGEC:
3727 case Mips::BLTC:
3728 case Mips::BGEUC:
3729 case Mips::BLTUC:
3730 case Mips::BEQC:
3731 case Mips::BNEC:
3732 if (Inst.getOperand(0).getReg() == Mips::ZERO)
3733 return Match_RequiresNoZeroRegister;
3734 if (Inst.getOperand(1).getReg() == Mips::ZERO)
3735 return Match_RequiresNoZeroRegister;
3736 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
3737 return Match_RequiresDifferentOperands;
3738 return Match_Success;
3739 default:
3740 return Match_Success;
3741 }
3742 }
3743
RefineErrorLoc(const SMLoc Loc,const OperandVector & Operands,uint64_t ErrorInfo)3744 static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
3745 uint64_t ErrorInfo) {
3746 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
3747 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
3748 if (ErrorLoc == SMLoc())
3749 return Loc;
3750 return ErrorLoc;
3751 }
3752 return Loc;
3753 }
3754
MatchAndEmitInstruction(SMLoc IDLoc,unsigned & Opcode,OperandVector & Operands,MCStreamer & Out,uint64_t & ErrorInfo,bool MatchingInlineAsm)3755 bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3756 OperandVector &Operands,
3757 MCStreamer &Out,
3758 uint64_t &ErrorInfo,
3759 bool MatchingInlineAsm) {
3760
3761 MCInst Inst;
3762 unsigned MatchResult =
3763 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
3764
3765 switch (MatchResult) {
3766 case Match_Success: {
3767 if (processInstruction(Inst, IDLoc, Out, STI))
3768 return true;
3769 return false;
3770 }
3771 case Match_MissingFeature:
3772 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3773 return true;
3774 case Match_InvalidOperand: {
3775 SMLoc ErrorLoc = IDLoc;
3776 if (ErrorInfo != ~0ULL) {
3777 if (ErrorInfo >= Operands.size())
3778 return Error(IDLoc, "too few operands for instruction");
3779
3780 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
3781 if (ErrorLoc == SMLoc())
3782 ErrorLoc = IDLoc;
3783 }
3784
3785 return Error(ErrorLoc, "invalid operand for instruction");
3786 }
3787 case Match_MnemonicFail:
3788 return Error(IDLoc, "invalid instruction");
3789 case Match_RequiresDifferentSrcAndDst:
3790 return Error(IDLoc, "source and destination must be different");
3791 case Match_RequiresDifferentOperands:
3792 return Error(IDLoc, "registers must be different");
3793 case Match_RequiresNoZeroRegister:
3794 return Error(IDLoc, "invalid operand ($zero) for instruction");
3795 case Match_Immz:
3796 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
3797 case Match_UImm1_0:
3798 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3799 "expected 1-bit unsigned immediate");
3800 case Match_UImm2_0:
3801 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3802 "expected 2-bit unsigned immediate");
3803 case Match_UImm2_1:
3804 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3805 "expected immediate in range 1 .. 4");
3806 case Match_UImm3_0:
3807 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3808 "expected 3-bit unsigned immediate");
3809 case Match_UImm4_0:
3810 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3811 "expected 4-bit unsigned immediate");
3812 case Match_SImm4_0:
3813 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3814 "expected 4-bit signed immediate");
3815 case Match_UImm5_0:
3816 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3817 "expected 5-bit unsigned immediate");
3818 case Match_SImm5_0:
3819 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3820 "expected 5-bit signed immediate");
3821 case Match_UImm5_1:
3822 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3823 "expected immediate in range 1 .. 32");
3824 case Match_UImm5_32:
3825 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3826 "expected immediate in range 32 .. 63");
3827 case Match_UImm5_33:
3828 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3829 "expected immediate in range 33 .. 64");
3830 case Match_UImm5_0_Report_UImm6:
3831 // This is used on UImm5 operands that have a corresponding UImm5_32
3832 // operand to avoid confusing the user.
3833 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3834 "expected 6-bit unsigned immediate");
3835 case Match_UImm5_Lsl2:
3836 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3837 "expected both 7-bit unsigned immediate and multiple of 4");
3838 case Match_UImmRange2_64:
3839 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3840 "expected immediate in range 2 .. 64");
3841 case Match_UImm6_0:
3842 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3843 "expected 6-bit unsigned immediate");
3844 case Match_UImm6_Lsl2:
3845 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3846 "expected both 8-bit unsigned immediate and multiple of 4");
3847 case Match_SImm6_0:
3848 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3849 "expected 6-bit signed immediate");
3850 case Match_UImm7_0:
3851 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3852 "expected 7-bit unsigned immediate");
3853 case Match_UImm7_N1:
3854 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3855 "expected immediate in range -1 .. 126");
3856 case Match_SImm7_Lsl2:
3857 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3858 "expected both 9-bit signed immediate and multiple of 4");
3859 case Match_UImm8_0:
3860 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3861 "expected 8-bit unsigned immediate");
3862 case Match_UImm10_0:
3863 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3864 "expected 10-bit unsigned immediate");
3865 case Match_SImm10_0:
3866 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3867 "expected 10-bit signed immediate");
3868 case Match_SImm11_0:
3869 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3870 "expected 11-bit signed immediate");
3871 case Match_UImm16:
3872 case Match_UImm16_Relaxed:
3873 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3874 "expected 16-bit unsigned immediate");
3875 case Match_SImm16:
3876 case Match_SImm16_Relaxed:
3877 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3878 "expected 16-bit signed immediate");
3879 case Match_UImm20_0:
3880 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3881 "expected 20-bit unsigned immediate");
3882 case Match_UImm26_0:
3883 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3884 "expected 26-bit unsigned immediate");
3885 case Match_SImm32:
3886 case Match_SImm32_Relaxed:
3887 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3888 "expected 32-bit signed immediate");
3889 case Match_MemSImm9:
3890 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3891 "expected memory with 9-bit signed offset");
3892 case Match_MemSImm10:
3893 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3894 "expected memory with 10-bit signed offset");
3895 case Match_MemSImm10Lsl1:
3896 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3897 "expected memory with 11-bit signed offset and multiple of 2");
3898 case Match_MemSImm10Lsl2:
3899 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3900 "expected memory with 12-bit signed offset and multiple of 4");
3901 case Match_MemSImm10Lsl3:
3902 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3903 "expected memory with 13-bit signed offset and multiple of 8");
3904 case Match_MemSImm11:
3905 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3906 "expected memory with 11-bit signed offset");
3907 case Match_MemSImm12:
3908 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3909 "expected memory with 12-bit signed offset");
3910 case Match_MemSImm16:
3911 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3912 "expected memory with 16-bit signed offset");
3913 }
3914
3915 llvm_unreachable("Implement any new match types added!");
3916 }
3917
warnIfRegIndexIsAT(unsigned RegIndex,SMLoc Loc)3918 void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3919 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3920 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3921 ") without \".set noat\"");
3922 }
3923
warnIfNoMacro(SMLoc Loc)3924 void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3925 if (!AssemblerOptions.back()->isMacro())
3926 Warning(Loc, "macro instruction expanded into multiple instructions");
3927 }
3928
3929 void
printWarningWithFixIt(const Twine & Msg,const Twine & FixMsg,SMRange Range,bool ShowColors)3930 MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3931 SMRange Range, bool ShowColors) {
3932 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
3933 Range, SMFixIt(Range, FixMsg),
3934 ShowColors);
3935 }
3936
matchCPURegisterName(StringRef Name)3937 int MipsAsmParser::matchCPURegisterName(StringRef Name) {
3938 int CC;
3939
3940 CC = StringSwitch<unsigned>(Name)
3941 .Case("zero", 0)
3942 .Case("at", 1)
3943 .Case("a0", 4)
3944 .Case("a1", 5)
3945 .Case("a2", 6)
3946 .Case("a3", 7)
3947 .Case("v0", 2)
3948 .Case("v1", 3)
3949 .Case("s0", 16)
3950 .Case("s1", 17)
3951 .Case("s2", 18)
3952 .Case("s3", 19)
3953 .Case("s4", 20)
3954 .Case("s5", 21)
3955 .Case("s6", 22)
3956 .Case("s7", 23)
3957 .Case("k0", 26)
3958 .Case("k1", 27)
3959 .Case("gp", 28)
3960 .Case("sp", 29)
3961 .Case("fp", 30)
3962 .Case("s8", 30)
3963 .Case("ra", 31)
3964 .Case("t0", 8)
3965 .Case("t1", 9)
3966 .Case("t2", 10)
3967 .Case("t3", 11)
3968 .Case("t4", 12)
3969 .Case("t5", 13)
3970 .Case("t6", 14)
3971 .Case("t7", 15)
3972 .Case("t8", 24)
3973 .Case("t9", 25)
3974 .Default(-1);
3975
3976 if (!(isABI_N32() || isABI_N64()))
3977 return CC;
3978
3979 if (12 <= CC && CC <= 15) {
3980 // Name is one of t4-t7
3981 AsmToken RegTok = getLexer().peekTok();
3982 SMRange RegRange = RegTok.getLocRange();
3983
3984 StringRef FixedName = StringSwitch<StringRef>(Name)
3985 .Case("t4", "t0")
3986 .Case("t5", "t1")
3987 .Case("t6", "t2")
3988 .Case("t7", "t3")
3989 .Default("");
3990 assert(FixedName != "" && "Register name is not one of t4-t7.");
3991
3992 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3993 "Did you mean $" + FixedName + "?", RegRange);
3994 }
3995
3996 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3997 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3998 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3999 if (8 <= CC && CC <= 11)
4000 CC += 4;
4001
4002 if (CC == -1)
4003 CC = StringSwitch<unsigned>(Name)
4004 .Case("a4", 8)
4005 .Case("a5", 9)
4006 .Case("a6", 10)
4007 .Case("a7", 11)
4008 .Case("kt0", 26)
4009 .Case("kt1", 27)
4010 .Default(-1);
4011
4012 return CC;
4013 }
4014
matchHWRegsRegisterName(StringRef Name)4015 int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
4016 int CC;
4017
4018 CC = StringSwitch<unsigned>(Name)
4019 .Case("hwr_cpunum", 0)
4020 .Case("hwr_synci_step", 1)
4021 .Case("hwr_cc", 2)
4022 .Case("hwr_ccres", 3)
4023 .Case("hwr_ulr", 29)
4024 .Default(-1);
4025
4026 return CC;
4027 }
4028
matchFPURegisterName(StringRef Name)4029 int MipsAsmParser::matchFPURegisterName(StringRef Name) {
4030
4031 if (Name[0] == 'f') {
4032 StringRef NumString = Name.substr(1);
4033 unsigned IntVal;
4034 if (NumString.getAsInteger(10, IntVal))
4035 return -1; // This is not an integer.
4036 if (IntVal > 31) // Maximum index for fpu register.
4037 return -1;
4038 return IntVal;
4039 }
4040 return -1;
4041 }
4042
matchFCCRegisterName(StringRef Name)4043 int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
4044
4045 if (Name.startswith("fcc")) {
4046 StringRef NumString = Name.substr(3);
4047 unsigned IntVal;
4048 if (NumString.getAsInteger(10, IntVal))
4049 return -1; // This is not an integer.
4050 if (IntVal > 7) // There are only 8 fcc registers.
4051 return -1;
4052 return IntVal;
4053 }
4054 return -1;
4055 }
4056
matchACRegisterName(StringRef Name)4057 int MipsAsmParser::matchACRegisterName(StringRef Name) {
4058
4059 if (Name.startswith("ac")) {
4060 StringRef NumString = Name.substr(2);
4061 unsigned IntVal;
4062 if (NumString.getAsInteger(10, IntVal))
4063 return -1; // This is not an integer.
4064 if (IntVal > 3) // There are only 3 acc registers.
4065 return -1;
4066 return IntVal;
4067 }
4068 return -1;
4069 }
4070
matchMSA128RegisterName(StringRef Name)4071 int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
4072 unsigned IntVal;
4073
4074 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
4075 return -1;
4076
4077 if (IntVal > 31)
4078 return -1;
4079
4080 return IntVal;
4081 }
4082
matchMSA128CtrlRegisterName(StringRef Name)4083 int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
4084 int CC;
4085
4086 CC = StringSwitch<unsigned>(Name)
4087 .Case("msair", 0)
4088 .Case("msacsr", 1)
4089 .Case("msaaccess", 2)
4090 .Case("msasave", 3)
4091 .Case("msamodify", 4)
4092 .Case("msarequest", 5)
4093 .Case("msamap", 6)
4094 .Case("msaunmap", 7)
4095 .Default(-1);
4096
4097 return CC;
4098 }
4099
getATReg(SMLoc Loc)4100 unsigned MipsAsmParser::getATReg(SMLoc Loc) {
4101 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
4102 if (ATIndex == 0) {
4103 reportParseError(Loc,
4104 "pseudo-instruction requires $at, which is not available");
4105 return 0;
4106 }
4107 unsigned AT = getReg(
4108 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
4109 return AT;
4110 }
4111
getReg(int RC,int RegNo)4112 unsigned MipsAsmParser::getReg(int RC, int RegNo) {
4113 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
4114 }
4115
parseOperand(OperandVector & Operands,StringRef Mnemonic)4116 bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
4117 MCAsmParser &Parser = getParser();
4118 DEBUG(dbgs() << "parseOperand\n");
4119
4120 // Check if the current operand has a custom associated parser, if so, try to
4121 // custom parse the operand, or fallback to the general approach.
4122 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4123 if (ResTy == MatchOperand_Success)
4124 return false;
4125 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4126 // there was a match, but an error occurred, in which case, just return that
4127 // the operand parsing failed.
4128 if (ResTy == MatchOperand_ParseFail)
4129 return true;
4130
4131 DEBUG(dbgs() << ".. Generic Parser\n");
4132
4133 switch (getLexer().getKind()) {
4134 default:
4135 Error(Parser.getTok().getLoc(), "unexpected token in operand");
4136 return true;
4137 case AsmToken::Dollar: {
4138 // Parse the register.
4139 SMLoc S = Parser.getTok().getLoc();
4140
4141 // Almost all registers have been parsed by custom parsers. There is only
4142 // one exception to this. $zero (and it's alias $0) will reach this point
4143 // for div, divu, and similar instructions because it is not an operand
4144 // to the instruction definition but an explicit register. Special case
4145 // this situation for now.
4146 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
4147 return false;
4148
4149 // Maybe it is a symbol reference.
4150 StringRef Identifier;
4151 if (Parser.parseIdentifier(Identifier))
4152 return true;
4153
4154 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4155 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
4156 // Otherwise create a symbol reference.
4157 const MCExpr *Res =
4158 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
4159
4160 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
4161 return false;
4162 }
4163 // Else drop to expression parsing.
4164 case AsmToken::LParen:
4165 case AsmToken::Minus:
4166 case AsmToken::Plus:
4167 case AsmToken::Integer:
4168 case AsmToken::Tilde:
4169 case AsmToken::String: {
4170 DEBUG(dbgs() << ".. generic integer\n");
4171 OperandMatchResultTy ResTy = parseImm(Operands);
4172 return ResTy != MatchOperand_Success;
4173 }
4174 case AsmToken::Percent: {
4175 // It is a symbol reference or constant expression.
4176 const MCExpr *IdVal;
4177 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
4178 if (parseRelocOperand(IdVal))
4179 return true;
4180
4181 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4182
4183 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4184 return false;
4185 } // case AsmToken::Percent
4186 } // switch(getLexer().getKind())
4187 return true;
4188 }
4189
evaluateRelocExpr(const MCExpr * Expr,StringRef RelocStr)4190 const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
4191 StringRef RelocStr) {
4192 if (RelocStr == "hi(%neg(%gp_rel")
4193 return MipsMCExpr::createGpOff(MipsMCExpr::MEK_HI, Expr, getContext());
4194 else if (RelocStr == "lo(%neg(%gp_rel")
4195 return MipsMCExpr::createGpOff(MipsMCExpr::MEK_LO, Expr, getContext());
4196
4197 MipsMCExpr::MipsExprKind Kind =
4198 StringSwitch<MipsMCExpr::MipsExprKind>(RelocStr)
4199 .Case("call16", MipsMCExpr::MEK_GOT_CALL)
4200 .Case("call_hi", MipsMCExpr::MEK_CALL_HI16)
4201 .Case("call_lo", MipsMCExpr::MEK_CALL_LO16)
4202 .Case("dtprel_hi", MipsMCExpr::MEK_DTPREL_HI)
4203 .Case("dtprel_lo", MipsMCExpr::MEK_DTPREL_LO)
4204 .Case("got", MipsMCExpr::MEK_GOT)
4205 .Case("got_disp", MipsMCExpr::MEK_GOT_DISP)
4206 .Case("got_hi", MipsMCExpr::MEK_GOT_HI16)
4207 .Case("got_lo", MipsMCExpr::MEK_GOT_LO16)
4208 .Case("got_ofst", MipsMCExpr::MEK_GOT_OFST)
4209 .Case("got_page", MipsMCExpr::MEK_GOT_PAGE)
4210 .Case("gottprel", MipsMCExpr::MEK_GOTTPREL)
4211 .Case("gp_rel", MipsMCExpr::MEK_GPREL)
4212 .Case("hi", MipsMCExpr::MEK_HI)
4213 .Case("higher", MipsMCExpr::MEK_HIGHER)
4214 .Case("highest", MipsMCExpr::MEK_HIGHEST)
4215 .Case("lo", MipsMCExpr::MEK_LO)
4216 .Case("neg", MipsMCExpr::MEK_NEG)
4217 .Case("pcrel_hi", MipsMCExpr::MEK_PCREL_HI16)
4218 .Case("pcrel_lo", MipsMCExpr::MEK_PCREL_LO16)
4219 .Case("tlsgd", MipsMCExpr::MEK_TLSGD)
4220 .Case("tlsldm", MipsMCExpr::MEK_TLSLDM)
4221 .Case("tprel_hi", MipsMCExpr::MEK_TPREL_HI)
4222 .Case("tprel_lo", MipsMCExpr::MEK_TPREL_LO)
4223 .Default(MipsMCExpr::MEK_None);
4224
4225 assert(Kind != MipsMCExpr::MEK_None);
4226 return MipsMCExpr::create(Kind, Expr, getContext());
4227 }
4228
isEvaluated(const MCExpr * Expr)4229 bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
4230
4231 switch (Expr->getKind()) {
4232 case MCExpr::Constant:
4233 return true;
4234 case MCExpr::SymbolRef:
4235 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
4236 case MCExpr::Binary:
4237 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
4238 if (!isEvaluated(BE->getLHS()))
4239 return false;
4240 return isEvaluated(BE->getRHS());
4241 }
4242 case MCExpr::Unary:
4243 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
4244 case MCExpr::Target:
4245 return true;
4246 }
4247 return false;
4248 }
4249
parseRelocOperand(const MCExpr * & Res)4250 bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
4251 MCAsmParser &Parser = getParser();
4252 Parser.Lex(); // Eat the % token.
4253 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
4254 if (Tok.isNot(AsmToken::Identifier))
4255 return true;
4256
4257 std::string Str = Tok.getIdentifier();
4258
4259 Parser.Lex(); // Eat the identifier.
4260 // Now make an expression from the rest of the operand.
4261 const MCExpr *IdVal;
4262 SMLoc EndLoc;
4263
4264 if (getLexer().getKind() == AsmToken::LParen) {
4265 while (1) {
4266 Parser.Lex(); // Eat the '(' token.
4267 if (getLexer().getKind() == AsmToken::Percent) {
4268 Parser.Lex(); // Eat the % token.
4269 const AsmToken &nextTok = Parser.getTok();
4270 if (nextTok.isNot(AsmToken::Identifier))
4271 return true;
4272 Str += "(%";
4273 Str += nextTok.getIdentifier();
4274 Parser.Lex(); // Eat the identifier.
4275 if (getLexer().getKind() != AsmToken::LParen)
4276 return true;
4277 } else
4278 break;
4279 }
4280 if (getParser().parseParenExpression(IdVal, EndLoc))
4281 return true;
4282
4283 while (getLexer().getKind() == AsmToken::RParen)
4284 Parser.Lex(); // Eat the ')' token.
4285
4286 } else
4287 return true; // Parenthesis must follow the relocation operand.
4288
4289 Res = evaluateRelocExpr(IdVal, Str);
4290 return false;
4291 }
4292
ParseRegister(unsigned & RegNo,SMLoc & StartLoc,SMLoc & EndLoc)4293 bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
4294 SMLoc &EndLoc) {
4295 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
4296 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
4297 if (ResTy == MatchOperand_Success) {
4298 assert(Operands.size() == 1);
4299 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
4300 StartLoc = Operand.getStartLoc();
4301 EndLoc = Operand.getEndLoc();
4302
4303 // AFAIK, we only support numeric registers and named GPR's in CFI
4304 // directives.
4305 // Don't worry about eating tokens before failing. Using an unrecognised
4306 // register is a parse error.
4307 if (Operand.isGPRAsmReg()) {
4308 // Resolve to GPR32 or GPR64 appropriately.
4309 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
4310 }
4311
4312 return (RegNo == (unsigned)-1);
4313 }
4314
4315 assert(Operands.size() == 0);
4316 return (RegNo == (unsigned)-1);
4317 }
4318
parseMemOffset(const MCExpr * & Res,bool isParenExpr)4319 bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
4320 MCAsmParser &Parser = getParser();
4321 SMLoc S;
4322 bool Result = true;
4323 unsigned NumOfLParen = 0;
4324
4325 while (getLexer().getKind() == AsmToken::LParen) {
4326 Parser.Lex();
4327 ++NumOfLParen;
4328 }
4329
4330 switch (getLexer().getKind()) {
4331 default:
4332 return true;
4333 case AsmToken::Identifier:
4334 case AsmToken::LParen:
4335 case AsmToken::Integer:
4336 case AsmToken::Minus:
4337 case AsmToken::Plus:
4338 if (isParenExpr)
4339 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
4340 else
4341 Result = (getParser().parseExpression(Res));
4342 while (getLexer().getKind() == AsmToken::RParen)
4343 Parser.Lex();
4344 break;
4345 case AsmToken::Percent:
4346 Result = parseRelocOperand(Res);
4347 }
4348 return Result;
4349 }
4350
4351 MipsAsmParser::OperandMatchResultTy
parseMemOperand(OperandVector & Operands)4352 MipsAsmParser::parseMemOperand(OperandVector &Operands) {
4353 MCAsmParser &Parser = getParser();
4354 DEBUG(dbgs() << "parseMemOperand\n");
4355 const MCExpr *IdVal = nullptr;
4356 SMLoc S;
4357 bool isParenExpr = false;
4358 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
4359 // First operand is the offset.
4360 S = Parser.getTok().getLoc();
4361
4362 if (getLexer().getKind() == AsmToken::LParen) {
4363 Parser.Lex();
4364 isParenExpr = true;
4365 }
4366
4367 if (getLexer().getKind() != AsmToken::Dollar) {
4368 if (parseMemOffset(IdVal, isParenExpr))
4369 return MatchOperand_ParseFail;
4370
4371 const AsmToken &Tok = Parser.getTok(); // Get the next token.
4372 if (Tok.isNot(AsmToken::LParen)) {
4373 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
4374 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
4375 SMLoc E =
4376 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4377 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4378 return MatchOperand_Success;
4379 }
4380 if (Tok.is(AsmToken::EndOfStatement)) {
4381 SMLoc E =
4382 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4383
4384 // Zero register assumed, add a memory operand with ZERO as its base.
4385 // "Base" will be managed by k_Memory.
4386 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
4387 S, E, *this);
4388 Operands.push_back(
4389 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
4390 return MatchOperand_Success;
4391 }
4392 Error(Parser.getTok().getLoc(), "'(' expected");
4393 return MatchOperand_ParseFail;
4394 }
4395
4396 Parser.Lex(); // Eat the '(' token.
4397 }
4398
4399 Res = parseAnyRegister(Operands);
4400 if (Res != MatchOperand_Success)
4401 return Res;
4402
4403 if (Parser.getTok().isNot(AsmToken::RParen)) {
4404 Error(Parser.getTok().getLoc(), "')' expected");
4405 return MatchOperand_ParseFail;
4406 }
4407
4408 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4409
4410 Parser.Lex(); // Eat the ')' token.
4411
4412 if (!IdVal)
4413 IdVal = MCConstantExpr::create(0, getContext());
4414
4415 // Replace the register operand with the memory operand.
4416 std::unique_ptr<MipsOperand> op(
4417 static_cast<MipsOperand *>(Operands.back().release()));
4418 // Remove the register from the operands.
4419 // "op" will be managed by k_Memory.
4420 Operands.pop_back();
4421 // Add the memory operand.
4422 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
4423 int64_t Imm;
4424 if (IdVal->evaluateAsAbsolute(Imm))
4425 IdVal = MCConstantExpr::create(Imm, getContext());
4426 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
4427 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
4428 getContext());
4429 }
4430
4431 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
4432 return MatchOperand_Success;
4433 }
4434
searchSymbolAlias(OperandVector & Operands)4435 bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
4436 MCAsmParser &Parser = getParser();
4437 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
4438 if (Sym) {
4439 SMLoc S = Parser.getTok().getLoc();
4440 const MCExpr *Expr;
4441 if (Sym->isVariable())
4442 Expr = Sym->getVariableValue();
4443 else
4444 return false;
4445 if (Expr->getKind() == MCExpr::SymbolRef) {
4446 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
4447 StringRef DefSymbol = Ref->getSymbol().getName();
4448 if (DefSymbol.startswith("$")) {
4449 OperandMatchResultTy ResTy =
4450 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
4451 if (ResTy == MatchOperand_Success) {
4452 Parser.Lex();
4453 return true;
4454 } else if (ResTy == MatchOperand_ParseFail)
4455 llvm_unreachable("Should never ParseFail");
4456 return false;
4457 }
4458 }
4459 }
4460 return false;
4461 }
4462
4463 MipsAsmParser::OperandMatchResultTy
matchAnyRegisterNameWithoutDollar(OperandVector & Operands,StringRef Identifier,SMLoc S)4464 MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
4465 StringRef Identifier,
4466 SMLoc S) {
4467 int Index = matchCPURegisterName(Identifier);
4468 if (Index != -1) {
4469 Operands.push_back(MipsOperand::createGPRReg(
4470 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4471 return MatchOperand_Success;
4472 }
4473
4474 Index = matchHWRegsRegisterName(Identifier);
4475 if (Index != -1) {
4476 Operands.push_back(MipsOperand::createHWRegsReg(
4477 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4478 return MatchOperand_Success;
4479 }
4480
4481 Index = matchFPURegisterName(Identifier);
4482 if (Index != -1) {
4483 Operands.push_back(MipsOperand::createFGRReg(
4484 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4485 return MatchOperand_Success;
4486 }
4487
4488 Index = matchFCCRegisterName(Identifier);
4489 if (Index != -1) {
4490 Operands.push_back(MipsOperand::createFCCReg(
4491 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4492 return MatchOperand_Success;
4493 }
4494
4495 Index = matchACRegisterName(Identifier);
4496 if (Index != -1) {
4497 Operands.push_back(MipsOperand::createACCReg(
4498 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4499 return MatchOperand_Success;
4500 }
4501
4502 Index = matchMSA128RegisterName(Identifier);
4503 if (Index != -1) {
4504 Operands.push_back(MipsOperand::createMSA128Reg(
4505 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4506 return MatchOperand_Success;
4507 }
4508
4509 Index = matchMSA128CtrlRegisterName(Identifier);
4510 if (Index != -1) {
4511 Operands.push_back(MipsOperand::createMSACtrlReg(
4512 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4513 return MatchOperand_Success;
4514 }
4515
4516 return MatchOperand_NoMatch;
4517 }
4518
4519 MipsAsmParser::OperandMatchResultTy
matchAnyRegisterWithoutDollar(OperandVector & Operands,SMLoc S)4520 MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
4521 MCAsmParser &Parser = getParser();
4522 auto Token = Parser.getLexer().peekTok(false);
4523
4524 if (Token.is(AsmToken::Identifier)) {
4525 DEBUG(dbgs() << ".. identifier\n");
4526 StringRef Identifier = Token.getIdentifier();
4527 OperandMatchResultTy ResTy =
4528 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
4529 return ResTy;
4530 } else if (Token.is(AsmToken::Integer)) {
4531 DEBUG(dbgs() << ".. integer\n");
4532 Operands.push_back(MipsOperand::createNumericReg(
4533 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
4534 *this));
4535 return MatchOperand_Success;
4536 }
4537
4538 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
4539
4540 return MatchOperand_NoMatch;
4541 }
4542
4543 MipsAsmParser::OperandMatchResultTy
parseAnyRegister(OperandVector & Operands)4544 MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
4545 MCAsmParser &Parser = getParser();
4546 DEBUG(dbgs() << "parseAnyRegister\n");
4547
4548 auto Token = Parser.getTok();
4549
4550 SMLoc S = Token.getLoc();
4551
4552 if (Token.isNot(AsmToken::Dollar)) {
4553 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4554 if (Token.is(AsmToken::Identifier)) {
4555 if (searchSymbolAlias(Operands))
4556 return MatchOperand_Success;
4557 }
4558 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4559 return MatchOperand_NoMatch;
4560 }
4561 DEBUG(dbgs() << ".. $\n");
4562
4563 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
4564 if (ResTy == MatchOperand_Success) {
4565 Parser.Lex(); // $
4566 Parser.Lex(); // identifier
4567 }
4568 return ResTy;
4569 }
4570
4571 MipsAsmParser::OperandMatchResultTy
parseImm(OperandVector & Operands)4572 MipsAsmParser::parseImm(OperandVector &Operands) {
4573 MCAsmParser &Parser = getParser();
4574 switch (getLexer().getKind()) {
4575 default:
4576 return MatchOperand_NoMatch;
4577 case AsmToken::LParen:
4578 case AsmToken::Minus:
4579 case AsmToken::Plus:
4580 case AsmToken::Integer:
4581 case AsmToken::Tilde:
4582 case AsmToken::String:
4583 break;
4584 }
4585
4586 const MCExpr *IdVal;
4587 SMLoc S = Parser.getTok().getLoc();
4588 if (getParser().parseExpression(IdVal))
4589 return MatchOperand_ParseFail;
4590
4591 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4592 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4593 return MatchOperand_Success;
4594 }
4595
4596 MipsAsmParser::OperandMatchResultTy
parseJumpTarget(OperandVector & Operands)4597 MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
4598 MCAsmParser &Parser = getParser();
4599 DEBUG(dbgs() << "parseJumpTarget\n");
4600
4601 SMLoc S = getLexer().getLoc();
4602
4603 // Integers and expressions are acceptable
4604 OperandMatchResultTy ResTy = parseImm(Operands);
4605 if (ResTy != MatchOperand_NoMatch)
4606 return ResTy;
4607
4608 // Registers are a valid target and have priority over symbols.
4609 ResTy = parseAnyRegister(Operands);
4610 if (ResTy != MatchOperand_NoMatch)
4611 return ResTy;
4612
4613 const MCExpr *Expr = nullptr;
4614 if (Parser.parseExpression(Expr)) {
4615 // We have no way of knowing if a symbol was consumed so we must ParseFail
4616 return MatchOperand_ParseFail;
4617 }
4618 Operands.push_back(
4619 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
4620 return MatchOperand_Success;
4621 }
4622
4623 MipsAsmParser::OperandMatchResultTy
parseInvNum(OperandVector & Operands)4624 MipsAsmParser::parseInvNum(OperandVector &Operands) {
4625 MCAsmParser &Parser = getParser();
4626 const MCExpr *IdVal;
4627 // If the first token is '$' we may have register operand.
4628 if (Parser.getTok().is(AsmToken::Dollar))
4629 return MatchOperand_NoMatch;
4630 SMLoc S = Parser.getTok().getLoc();
4631 if (getParser().parseExpression(IdVal))
4632 return MatchOperand_ParseFail;
4633 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
4634 assert(MCE && "Unexpected MCExpr type.");
4635 int64_t Val = MCE->getValue();
4636 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4637 Operands.push_back(MipsOperand::CreateImm(
4638 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
4639 return MatchOperand_Success;
4640 }
4641
4642 MipsAsmParser::OperandMatchResultTy
parseRegisterList(OperandVector & Operands)4643 MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4644 MCAsmParser &Parser = getParser();
4645 SmallVector<unsigned, 10> Regs;
4646 unsigned RegNo;
4647 unsigned PrevReg = Mips::NoRegister;
4648 bool RegRange = false;
4649 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4650
4651 if (Parser.getTok().isNot(AsmToken::Dollar))
4652 return MatchOperand_ParseFail;
4653
4654 SMLoc S = Parser.getTok().getLoc();
4655 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4656 SMLoc E = getLexer().getLoc();
4657 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4658 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4659 if (RegRange) {
4660 // Remove last register operand because registers from register range
4661 // should be inserted first.
4662 if ((isGP64bit() && RegNo == Mips::RA_64) ||
4663 (!isGP64bit() && RegNo == Mips::RA)) {
4664 Regs.push_back(RegNo);
4665 } else {
4666 unsigned TmpReg = PrevReg + 1;
4667 while (TmpReg <= RegNo) {
4668 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
4669 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
4670 isGP64bit())) {
4671 Error(E, "invalid register operand");
4672 return MatchOperand_ParseFail;
4673 }
4674
4675 PrevReg = TmpReg;
4676 Regs.push_back(TmpReg++);
4677 }
4678 }
4679
4680 RegRange = false;
4681 } else {
4682 if ((PrevReg == Mips::NoRegister) &&
4683 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
4684 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
4685 Error(E, "$16 or $31 expected");
4686 return MatchOperand_ParseFail;
4687 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
4688 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
4689 !isGP64bit()) ||
4690 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
4691 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
4692 isGP64bit()))) {
4693 Error(E, "invalid register operand");
4694 return MatchOperand_ParseFail;
4695 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
4696 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
4697 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
4698 isGP64bit()))) {
4699 Error(E, "consecutive register numbers expected");
4700 return MatchOperand_ParseFail;
4701 }
4702
4703 Regs.push_back(RegNo);
4704 }
4705
4706 if (Parser.getTok().is(AsmToken::Minus))
4707 RegRange = true;
4708
4709 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4710 !Parser.getTok().isNot(AsmToken::Comma)) {
4711 Error(E, "',' or '-' expected");
4712 return MatchOperand_ParseFail;
4713 }
4714
4715 Lex(); // Consume comma or minus
4716 if (Parser.getTok().isNot(AsmToken::Dollar))
4717 break;
4718
4719 PrevReg = RegNo;
4720 }
4721
4722 SMLoc E = Parser.getTok().getLoc();
4723 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4724 parseMemOperand(Operands);
4725 return MatchOperand_Success;
4726 }
4727
4728 MipsAsmParser::OperandMatchResultTy
parseRegisterPair(OperandVector & Operands)4729 MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4730 MCAsmParser &Parser = getParser();
4731
4732 SMLoc S = Parser.getTok().getLoc();
4733 if (parseAnyRegister(Operands) != MatchOperand_Success)
4734 return MatchOperand_ParseFail;
4735
4736 SMLoc E = Parser.getTok().getLoc();
4737 MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
4738
4739 Operands.pop_back();
4740 Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
4741 return MatchOperand_Success;
4742 }
4743
4744 MipsAsmParser::OperandMatchResultTy
parseMovePRegPair(OperandVector & Operands)4745 MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4746 MCAsmParser &Parser = getParser();
4747 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4748 SmallVector<unsigned, 10> Regs;
4749
4750 if (Parser.getTok().isNot(AsmToken::Dollar))
4751 return MatchOperand_ParseFail;
4752
4753 SMLoc S = Parser.getTok().getLoc();
4754
4755 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4756 return MatchOperand_ParseFail;
4757
4758 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4759 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4760 Regs.push_back(RegNo);
4761
4762 SMLoc E = Parser.getTok().getLoc();
4763 if (Parser.getTok().isNot(AsmToken::Comma)) {
4764 Error(E, "',' expected");
4765 return MatchOperand_ParseFail;
4766 }
4767
4768 // Remove comma.
4769 Parser.Lex();
4770
4771 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4772 return MatchOperand_ParseFail;
4773
4774 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4775 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4776 Regs.push_back(RegNo);
4777
4778 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4779
4780 return MatchOperand_Success;
4781 }
4782
4783 /// Sometimes (i.e. load/stores) the operand may be followed immediately by
4784 /// either this.
4785 /// ::= '(', register, ')'
4786 /// handle it before we iterate so we don't get tripped up by the lack of
4787 /// a comma.
parseParenSuffix(StringRef Name,OperandVector & Operands)4788 bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
4789 MCAsmParser &Parser = getParser();
4790 if (getLexer().is(AsmToken::LParen)) {
4791 Operands.push_back(
4792 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4793 Parser.Lex();
4794 if (parseOperand(Operands, Name)) {
4795 SMLoc Loc = getLexer().getLoc();
4796 Parser.eatToEndOfStatement();
4797 return Error(Loc, "unexpected token in argument list");
4798 }
4799 if (Parser.getTok().isNot(AsmToken::RParen)) {
4800 SMLoc Loc = getLexer().getLoc();
4801 Parser.eatToEndOfStatement();
4802 return Error(Loc, "unexpected token, expected ')'");
4803 }
4804 Operands.push_back(
4805 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4806 Parser.Lex();
4807 }
4808 return false;
4809 }
4810
4811 /// Sometimes (i.e. in MSA) the operand may be followed immediately by
4812 /// either one of these.
4813 /// ::= '[', register, ']'
4814 /// ::= '[', integer, ']'
4815 /// handle it before we iterate so we don't get tripped up by the lack of
4816 /// a comma.
parseBracketSuffix(StringRef Name,OperandVector & Operands)4817 bool MipsAsmParser::parseBracketSuffix(StringRef Name,
4818 OperandVector &Operands) {
4819 MCAsmParser &Parser = getParser();
4820 if (getLexer().is(AsmToken::LBrac)) {
4821 Operands.push_back(
4822 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4823 Parser.Lex();
4824 if (parseOperand(Operands, Name)) {
4825 SMLoc Loc = getLexer().getLoc();
4826 Parser.eatToEndOfStatement();
4827 return Error(Loc, "unexpected token in argument list");
4828 }
4829 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4830 SMLoc Loc = getLexer().getLoc();
4831 Parser.eatToEndOfStatement();
4832 return Error(Loc, "unexpected token, expected ']'");
4833 }
4834 Operands.push_back(
4835 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4836 Parser.Lex();
4837 }
4838 return false;
4839 }
4840
ParseInstruction(ParseInstructionInfo & Info,StringRef Name,SMLoc NameLoc,OperandVector & Operands)4841 bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4842 SMLoc NameLoc, OperandVector &Operands) {
4843 MCAsmParser &Parser = getParser();
4844 DEBUG(dbgs() << "ParseInstruction\n");
4845
4846 // We have reached first instruction, module directive are now forbidden.
4847 getTargetStreamer().forbidModuleDirective();
4848
4849 // Check if we have valid mnemonic
4850 if (!mnemonicIsValid(Name, 0)) {
4851 Parser.eatToEndOfStatement();
4852 return Error(NameLoc, "unknown instruction");
4853 }
4854 // First operand in MCInst is instruction mnemonic.
4855 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
4856
4857 // Read the remaining operands.
4858 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4859 // Read the first operand.
4860 if (parseOperand(Operands, Name)) {
4861 SMLoc Loc = getLexer().getLoc();
4862 Parser.eatToEndOfStatement();
4863 return Error(Loc, "unexpected token in argument list");
4864 }
4865 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
4866 return true;
4867 // AFAIK, parenthesis suffixes are never on the first operand
4868
4869 while (getLexer().is(AsmToken::Comma)) {
4870 Parser.Lex(); // Eat the comma.
4871 // Parse and remember the operand.
4872 if (parseOperand(Operands, Name)) {
4873 SMLoc Loc = getLexer().getLoc();
4874 Parser.eatToEndOfStatement();
4875 return Error(Loc, "unexpected token in argument list");
4876 }
4877 // Parse bracket and parenthesis suffixes before we iterate
4878 if (getLexer().is(AsmToken::LBrac)) {
4879 if (parseBracketSuffix(Name, Operands))
4880 return true;
4881 } else if (getLexer().is(AsmToken::LParen) &&
4882 parseParenSuffix(Name, Operands))
4883 return true;
4884 }
4885 }
4886 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4887 SMLoc Loc = getLexer().getLoc();
4888 Parser.eatToEndOfStatement();
4889 return Error(Loc, "unexpected token in argument list");
4890 }
4891 Parser.Lex(); // Consume the EndOfStatement.
4892 return false;
4893 }
4894
4895 // FIXME: Given that these have the same name, these should both be
4896 // consistent on affecting the Parser.
reportParseError(Twine ErrorMsg)4897 bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
4898 MCAsmParser &Parser = getParser();
4899 SMLoc Loc = getLexer().getLoc();
4900 Parser.eatToEndOfStatement();
4901 return Error(Loc, ErrorMsg);
4902 }
4903
reportParseError(SMLoc Loc,Twine ErrorMsg)4904 bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
4905 return Error(Loc, ErrorMsg);
4906 }
4907
parseSetNoAtDirective()4908 bool MipsAsmParser::parseSetNoAtDirective() {
4909 MCAsmParser &Parser = getParser();
4910 // Line should look like: ".set noat".
4911
4912 // Set the $at register to $0.
4913 AssemblerOptions.back()->setATRegIndex(0);
4914
4915 Parser.Lex(); // Eat "noat".
4916
4917 // If this is not the end of the statement, report an error.
4918 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4919 reportParseError("unexpected token, expected end of statement");
4920 return false;
4921 }
4922
4923 getTargetStreamer().emitDirectiveSetNoAt();
4924 Parser.Lex(); // Consume the EndOfStatement.
4925 return false;
4926 }
4927
parseSetAtDirective()4928 bool MipsAsmParser::parseSetAtDirective() {
4929 // Line can be: ".set at", which sets $at to $1
4930 // or ".set at=$reg", which sets $at to $reg.
4931 MCAsmParser &Parser = getParser();
4932 Parser.Lex(); // Eat "at".
4933
4934 if (getLexer().is(AsmToken::EndOfStatement)) {
4935 // No register was specified, so we set $at to $1.
4936 AssemblerOptions.back()->setATRegIndex(1);
4937
4938 getTargetStreamer().emitDirectiveSetAt();
4939 Parser.Lex(); // Consume the EndOfStatement.
4940 return false;
4941 }
4942
4943 if (getLexer().isNot(AsmToken::Equal)) {
4944 reportParseError("unexpected token, expected equals sign");
4945 return false;
4946 }
4947 Parser.Lex(); // Eat "=".
4948
4949 if (getLexer().isNot(AsmToken::Dollar)) {
4950 if (getLexer().is(AsmToken::EndOfStatement)) {
4951 reportParseError("no register specified");
4952 return false;
4953 } else {
4954 reportParseError("unexpected token, expected dollar sign '$'");
4955 return false;
4956 }
4957 }
4958 Parser.Lex(); // Eat "$".
4959
4960 // Find out what "reg" is.
4961 unsigned AtRegNo;
4962 const AsmToken &Reg = Parser.getTok();
4963 if (Reg.is(AsmToken::Identifier)) {
4964 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4965 } else if (Reg.is(AsmToken::Integer)) {
4966 AtRegNo = Reg.getIntVal();
4967 } else {
4968 reportParseError("unexpected token, expected identifier or integer");
4969 return false;
4970 }
4971
4972 // Check if $reg is a valid register. If it is, set $at to $reg.
4973 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
4974 reportParseError("invalid register");
4975 return false;
4976 }
4977 Parser.Lex(); // Eat "reg".
4978
4979 // If this is not the end of the statement, report an error.
4980 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4981 reportParseError("unexpected token, expected end of statement");
4982 return false;
4983 }
4984
4985 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4986
4987 Parser.Lex(); // Consume the EndOfStatement.
4988 return false;
4989 }
4990
parseSetReorderDirective()4991 bool MipsAsmParser::parseSetReorderDirective() {
4992 MCAsmParser &Parser = getParser();
4993 Parser.Lex();
4994 // If this is not the end of the statement, report an error.
4995 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4996 reportParseError("unexpected token, expected end of statement");
4997 return false;
4998 }
4999 AssemblerOptions.back()->setReorder();
5000 getTargetStreamer().emitDirectiveSetReorder();
5001 Parser.Lex(); // Consume the EndOfStatement.
5002 return false;
5003 }
5004
parseSetNoReorderDirective()5005 bool MipsAsmParser::parseSetNoReorderDirective() {
5006 MCAsmParser &Parser = getParser();
5007 Parser.Lex();
5008 // If this is not the end of the statement, report an error.
5009 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5010 reportParseError("unexpected token, expected end of statement");
5011 return false;
5012 }
5013 AssemblerOptions.back()->setNoReorder();
5014 getTargetStreamer().emitDirectiveSetNoReorder();
5015 Parser.Lex(); // Consume the EndOfStatement.
5016 return false;
5017 }
5018
parseSetMacroDirective()5019 bool MipsAsmParser::parseSetMacroDirective() {
5020 MCAsmParser &Parser = getParser();
5021 Parser.Lex();
5022 // If this is not the end of the statement, report an error.
5023 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5024 reportParseError("unexpected token, expected end of statement");
5025 return false;
5026 }
5027 AssemblerOptions.back()->setMacro();
5028 getTargetStreamer().emitDirectiveSetMacro();
5029 Parser.Lex(); // Consume the EndOfStatement.
5030 return false;
5031 }
5032
parseSetNoMacroDirective()5033 bool MipsAsmParser::parseSetNoMacroDirective() {
5034 MCAsmParser &Parser = getParser();
5035 Parser.Lex();
5036 // If this is not the end of the statement, report an error.
5037 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5038 reportParseError("unexpected token, expected end of statement");
5039 return false;
5040 }
5041 if (AssemblerOptions.back()->isReorder()) {
5042 reportParseError("`noreorder' must be set before `nomacro'");
5043 return false;
5044 }
5045 AssemblerOptions.back()->setNoMacro();
5046 getTargetStreamer().emitDirectiveSetNoMacro();
5047 Parser.Lex(); // Consume the EndOfStatement.
5048 return false;
5049 }
5050
parseSetMsaDirective()5051 bool MipsAsmParser::parseSetMsaDirective() {
5052 MCAsmParser &Parser = getParser();
5053 Parser.Lex();
5054
5055 // If this is not the end of the statement, report an error.
5056 if (getLexer().isNot(AsmToken::EndOfStatement))
5057 return reportParseError("unexpected token, expected end of statement");
5058
5059 setFeatureBits(Mips::FeatureMSA, "msa");
5060 getTargetStreamer().emitDirectiveSetMsa();
5061 return false;
5062 }
5063
parseSetNoMsaDirective()5064 bool MipsAsmParser::parseSetNoMsaDirective() {
5065 MCAsmParser &Parser = getParser();
5066 Parser.Lex();
5067
5068 // If this is not the end of the statement, report an error.
5069 if (getLexer().isNot(AsmToken::EndOfStatement))
5070 return reportParseError("unexpected token, expected end of statement");
5071
5072 clearFeatureBits(Mips::FeatureMSA, "msa");
5073 getTargetStreamer().emitDirectiveSetNoMsa();
5074 return false;
5075 }
5076
parseSetNoDspDirective()5077 bool MipsAsmParser::parseSetNoDspDirective() {
5078 MCAsmParser &Parser = getParser();
5079 Parser.Lex(); // Eat "nodsp".
5080
5081 // If this is not the end of the statement, report an error.
5082 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5083 reportParseError("unexpected token, expected end of statement");
5084 return false;
5085 }
5086
5087 clearFeatureBits(Mips::FeatureDSP, "dsp");
5088 getTargetStreamer().emitDirectiveSetNoDsp();
5089 return false;
5090 }
5091
parseSetMips16Directive()5092 bool MipsAsmParser::parseSetMips16Directive() {
5093 MCAsmParser &Parser = getParser();
5094 Parser.Lex(); // Eat "mips16".
5095
5096 // If this is not the end of the statement, report an error.
5097 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5098 reportParseError("unexpected token, expected end of statement");
5099 return false;
5100 }
5101
5102 setFeatureBits(Mips::FeatureMips16, "mips16");
5103 getTargetStreamer().emitDirectiveSetMips16();
5104 Parser.Lex(); // Consume the EndOfStatement.
5105 return false;
5106 }
5107
parseSetNoMips16Directive()5108 bool MipsAsmParser::parseSetNoMips16Directive() {
5109 MCAsmParser &Parser = getParser();
5110 Parser.Lex(); // Eat "nomips16".
5111
5112 // If this is not the end of the statement, report an error.
5113 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5114 reportParseError("unexpected token, expected end of statement");
5115 return false;
5116 }
5117
5118 clearFeatureBits(Mips::FeatureMips16, "mips16");
5119 getTargetStreamer().emitDirectiveSetNoMips16();
5120 Parser.Lex(); // Consume the EndOfStatement.
5121 return false;
5122 }
5123
parseSetFpDirective()5124 bool MipsAsmParser::parseSetFpDirective() {
5125 MCAsmParser &Parser = getParser();
5126 MipsABIFlagsSection::FpABIKind FpAbiVal;
5127 // Line can be: .set fp=32
5128 // .set fp=xx
5129 // .set fp=64
5130 Parser.Lex(); // Eat fp token
5131 AsmToken Tok = Parser.getTok();
5132 if (Tok.isNot(AsmToken::Equal)) {
5133 reportParseError("unexpected token, expected equals sign '='");
5134 return false;
5135 }
5136 Parser.Lex(); // Eat '=' token.
5137 Tok = Parser.getTok();
5138
5139 if (!parseFpABIValue(FpAbiVal, ".set"))
5140 return false;
5141
5142 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5143 reportParseError("unexpected token, expected end of statement");
5144 return false;
5145 }
5146 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
5147 Parser.Lex(); // Consume the EndOfStatement.
5148 return false;
5149 }
5150
parseSetOddSPRegDirective()5151 bool MipsAsmParser::parseSetOddSPRegDirective() {
5152 MCAsmParser &Parser = getParser();
5153
5154 Parser.Lex(); // Eat "oddspreg".
5155 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5156 reportParseError("unexpected token, expected end of statement");
5157 return false;
5158 }
5159
5160 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5161 getTargetStreamer().emitDirectiveSetOddSPReg();
5162 return false;
5163 }
5164
parseSetNoOddSPRegDirective()5165 bool MipsAsmParser::parseSetNoOddSPRegDirective() {
5166 MCAsmParser &Parser = getParser();
5167
5168 Parser.Lex(); // Eat "nooddspreg".
5169 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5170 reportParseError("unexpected token, expected end of statement");
5171 return false;
5172 }
5173
5174 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5175 getTargetStreamer().emitDirectiveSetNoOddSPReg();
5176 return false;
5177 }
5178
parseSetPopDirective()5179 bool MipsAsmParser::parseSetPopDirective() {
5180 MCAsmParser &Parser = getParser();
5181 SMLoc Loc = getLexer().getLoc();
5182
5183 Parser.Lex();
5184 if (getLexer().isNot(AsmToken::EndOfStatement))
5185 return reportParseError("unexpected token, expected end of statement");
5186
5187 // Always keep an element on the options "stack" to prevent the user
5188 // from changing the initial options. This is how we remember them.
5189 if (AssemblerOptions.size() == 2)
5190 return reportParseError(Loc, ".set pop with no .set push");
5191
5192 MCSubtargetInfo &STI = copySTI();
5193 AssemblerOptions.pop_back();
5194 setAvailableFeatures(
5195 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
5196 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
5197
5198 getTargetStreamer().emitDirectiveSetPop();
5199 return false;
5200 }
5201
parseSetPushDirective()5202 bool MipsAsmParser::parseSetPushDirective() {
5203 MCAsmParser &Parser = getParser();
5204 Parser.Lex();
5205 if (getLexer().isNot(AsmToken::EndOfStatement))
5206 return reportParseError("unexpected token, expected end of statement");
5207
5208 // Create a copy of the current assembler options environment and push it.
5209 AssemblerOptions.push_back(
5210 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
5211
5212 getTargetStreamer().emitDirectiveSetPush();
5213 return false;
5214 }
5215
parseSetSoftFloatDirective()5216 bool MipsAsmParser::parseSetSoftFloatDirective() {
5217 MCAsmParser &Parser = getParser();
5218 Parser.Lex();
5219 if (getLexer().isNot(AsmToken::EndOfStatement))
5220 return reportParseError("unexpected token, expected end of statement");
5221
5222 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5223 getTargetStreamer().emitDirectiveSetSoftFloat();
5224 return false;
5225 }
5226
parseSetHardFloatDirective()5227 bool MipsAsmParser::parseSetHardFloatDirective() {
5228 MCAsmParser &Parser = getParser();
5229 Parser.Lex();
5230 if (getLexer().isNot(AsmToken::EndOfStatement))
5231 return reportParseError("unexpected token, expected end of statement");
5232
5233 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5234 getTargetStreamer().emitDirectiveSetHardFloat();
5235 return false;
5236 }
5237
parseSetAssignment()5238 bool MipsAsmParser::parseSetAssignment() {
5239 StringRef Name;
5240 const MCExpr *Value;
5241 MCAsmParser &Parser = getParser();
5242
5243 if (Parser.parseIdentifier(Name))
5244 reportParseError("expected identifier after .set");
5245
5246 if (getLexer().isNot(AsmToken::Comma))
5247 return reportParseError("unexpected token, expected comma");
5248 Lex(); // Eat comma
5249
5250 if (Parser.parseExpression(Value))
5251 return reportParseError("expected valid expression after comma");
5252
5253 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
5254 Sym->setVariableValue(Value);
5255
5256 return false;
5257 }
5258
parseSetMips0Directive()5259 bool MipsAsmParser::parseSetMips0Directive() {
5260 MCAsmParser &Parser = getParser();
5261 Parser.Lex();
5262 if (getLexer().isNot(AsmToken::EndOfStatement))
5263 return reportParseError("unexpected token, expected end of statement");
5264
5265 // Reset assembler options to their initial values.
5266 MCSubtargetInfo &STI = copySTI();
5267 setAvailableFeatures(
5268 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
5269 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
5270 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
5271
5272 getTargetStreamer().emitDirectiveSetMips0();
5273 return false;
5274 }
5275
parseSetArchDirective()5276 bool MipsAsmParser::parseSetArchDirective() {
5277 MCAsmParser &Parser = getParser();
5278 Parser.Lex();
5279 if (getLexer().isNot(AsmToken::Equal))
5280 return reportParseError("unexpected token, expected equals sign");
5281
5282 Parser.Lex();
5283 StringRef Arch;
5284 if (Parser.parseIdentifier(Arch))
5285 return reportParseError("expected arch identifier");
5286
5287 StringRef ArchFeatureName =
5288 StringSwitch<StringRef>(Arch)
5289 .Case("mips1", "mips1")
5290 .Case("mips2", "mips2")
5291 .Case("mips3", "mips3")
5292 .Case("mips4", "mips4")
5293 .Case("mips5", "mips5")
5294 .Case("mips32", "mips32")
5295 .Case("mips32r2", "mips32r2")
5296 .Case("mips32r3", "mips32r3")
5297 .Case("mips32r5", "mips32r5")
5298 .Case("mips32r6", "mips32r6")
5299 .Case("mips64", "mips64")
5300 .Case("mips64r2", "mips64r2")
5301 .Case("mips64r3", "mips64r3")
5302 .Case("mips64r5", "mips64r5")
5303 .Case("mips64r6", "mips64r6")
5304 .Case("octeon", "cnmips")
5305 .Case("r4000", "mips3") // This is an implementation of Mips3.
5306 .Default("");
5307
5308 if (ArchFeatureName.empty())
5309 return reportParseError("unsupported architecture");
5310
5311 selectArch(ArchFeatureName);
5312 getTargetStreamer().emitDirectiveSetArch(Arch);
5313 return false;
5314 }
5315
parseSetFeature(uint64_t Feature)5316 bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
5317 MCAsmParser &Parser = getParser();
5318 Parser.Lex();
5319 if (getLexer().isNot(AsmToken::EndOfStatement))
5320 return reportParseError("unexpected token, expected end of statement");
5321
5322 switch (Feature) {
5323 default:
5324 llvm_unreachable("Unimplemented feature");
5325 case Mips::FeatureDSP:
5326 setFeatureBits(Mips::FeatureDSP, "dsp");
5327 getTargetStreamer().emitDirectiveSetDsp();
5328 break;
5329 case Mips::FeatureMicroMips:
5330 setFeatureBits(Mips::FeatureMicroMips, "micromips");
5331 getTargetStreamer().emitDirectiveSetMicroMips();
5332 break;
5333 case Mips::FeatureMips1:
5334 selectArch("mips1");
5335 getTargetStreamer().emitDirectiveSetMips1();
5336 break;
5337 case Mips::FeatureMips2:
5338 selectArch("mips2");
5339 getTargetStreamer().emitDirectiveSetMips2();
5340 break;
5341 case Mips::FeatureMips3:
5342 selectArch("mips3");
5343 getTargetStreamer().emitDirectiveSetMips3();
5344 break;
5345 case Mips::FeatureMips4:
5346 selectArch("mips4");
5347 getTargetStreamer().emitDirectiveSetMips4();
5348 break;
5349 case Mips::FeatureMips5:
5350 selectArch("mips5");
5351 getTargetStreamer().emitDirectiveSetMips5();
5352 break;
5353 case Mips::FeatureMips32:
5354 selectArch("mips32");
5355 getTargetStreamer().emitDirectiveSetMips32();
5356 break;
5357 case Mips::FeatureMips32r2:
5358 selectArch("mips32r2");
5359 getTargetStreamer().emitDirectiveSetMips32R2();
5360 break;
5361 case Mips::FeatureMips32r3:
5362 selectArch("mips32r3");
5363 getTargetStreamer().emitDirectiveSetMips32R3();
5364 break;
5365 case Mips::FeatureMips32r5:
5366 selectArch("mips32r5");
5367 getTargetStreamer().emitDirectiveSetMips32R5();
5368 break;
5369 case Mips::FeatureMips32r6:
5370 selectArch("mips32r6");
5371 getTargetStreamer().emitDirectiveSetMips32R6();
5372 break;
5373 case Mips::FeatureMips64:
5374 selectArch("mips64");
5375 getTargetStreamer().emitDirectiveSetMips64();
5376 break;
5377 case Mips::FeatureMips64r2:
5378 selectArch("mips64r2");
5379 getTargetStreamer().emitDirectiveSetMips64R2();
5380 break;
5381 case Mips::FeatureMips64r3:
5382 selectArch("mips64r3");
5383 getTargetStreamer().emitDirectiveSetMips64R3();
5384 break;
5385 case Mips::FeatureMips64r5:
5386 selectArch("mips64r5");
5387 getTargetStreamer().emitDirectiveSetMips64R5();
5388 break;
5389 case Mips::FeatureMips64r6:
5390 selectArch("mips64r6");
5391 getTargetStreamer().emitDirectiveSetMips64R6();
5392 break;
5393 }
5394 return false;
5395 }
5396
eatComma(StringRef ErrorStr)5397 bool MipsAsmParser::eatComma(StringRef ErrorStr) {
5398 MCAsmParser &Parser = getParser();
5399 if (getLexer().isNot(AsmToken::Comma)) {
5400 SMLoc Loc = getLexer().getLoc();
5401 Parser.eatToEndOfStatement();
5402 return Error(Loc, ErrorStr);
5403 }
5404
5405 Parser.Lex(); // Eat the comma.
5406 return true;
5407 }
5408
5409 // Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
5410 // In this class, it is only used for .cprestore.
5411 // FIXME: Only keep track of IsPicEnabled in one place, instead of in both
5412 // MipsTargetELFStreamer and MipsAsmParser.
isPicAndNotNxxAbi()5413 bool MipsAsmParser::isPicAndNotNxxAbi() {
5414 return inPicMode() && !(isABI_N32() || isABI_N64());
5415 }
5416
parseDirectiveCpLoad(SMLoc Loc)5417 bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
5418 if (AssemblerOptions.back()->isReorder())
5419 Warning(Loc, ".cpload should be inside a noreorder section");
5420
5421 if (inMips16Mode()) {
5422 reportParseError(".cpload is not supported in Mips16 mode");
5423 return false;
5424 }
5425
5426 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
5427 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
5428 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5429 reportParseError("expected register containing function address");
5430 return false;
5431 }
5432
5433 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
5434 if (!RegOpnd.isGPRAsmReg()) {
5435 reportParseError(RegOpnd.getStartLoc(), "invalid register");
5436 return false;
5437 }
5438
5439 // If this is not the end of the statement, report an error.
5440 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5441 reportParseError("unexpected token, expected end of statement");
5442 return false;
5443 }
5444
5445 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
5446 return false;
5447 }
5448
parseDirectiveCpRestore(SMLoc Loc)5449 bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5450 MCAsmParser &Parser = getParser();
5451
5452 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5453 // is used in non-PIC mode.
5454
5455 if (inMips16Mode()) {
5456 reportParseError(".cprestore is not supported in Mips16 mode");
5457 return false;
5458 }
5459
5460 // Get the stack offset value.
5461 const MCExpr *StackOffset;
5462 int64_t StackOffsetVal;
5463 if (Parser.parseExpression(StackOffset)) {
5464 reportParseError("expected stack offset value");
5465 return false;
5466 }
5467
5468 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5469 reportParseError("stack offset is not an absolute expression");
5470 return false;
5471 }
5472
5473 if (StackOffsetVal < 0) {
5474 Warning(Loc, ".cprestore with negative stack offset has no effect");
5475 IsCpRestoreSet = false;
5476 } else {
5477 IsCpRestoreSet = true;
5478 CpRestoreOffset = StackOffsetVal;
5479 }
5480
5481 // If this is not the end of the statement, report an error.
5482 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5483 reportParseError("unexpected token, expected end of statement");
5484 return false;
5485 }
5486
5487 if (!getTargetStreamer().emitDirectiveCpRestore(
5488 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
5489 return true;
5490 Parser.Lex(); // Consume the EndOfStatement.
5491 return false;
5492 }
5493
parseDirectiveCPSetup()5494 bool MipsAsmParser::parseDirectiveCPSetup() {
5495 MCAsmParser &Parser = getParser();
5496 unsigned FuncReg;
5497 unsigned Save;
5498 bool SaveIsReg = true;
5499
5500 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
5501 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
5502 if (ResTy == MatchOperand_NoMatch) {
5503 reportParseError("expected register containing function address");
5504 return false;
5505 }
5506
5507 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5508 if (!FuncRegOpnd.isGPRAsmReg()) {
5509 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
5510 Parser.eatToEndOfStatement();
5511 return false;
5512 }
5513
5514 FuncReg = FuncRegOpnd.getGPR32Reg();
5515 TmpReg.clear();
5516
5517 if (!eatComma("unexpected token, expected comma"))
5518 return true;
5519
5520 ResTy = parseAnyRegister(TmpReg);
5521 if (ResTy == MatchOperand_NoMatch) {
5522 const MCExpr *OffsetExpr;
5523 int64_t OffsetVal;
5524 SMLoc ExprLoc = getLexer().getLoc();
5525
5526 if (Parser.parseExpression(OffsetExpr) ||
5527 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5528 reportParseError(ExprLoc, "expected save register or stack offset");
5529 Parser.eatToEndOfStatement();
5530 return false;
5531 }
5532
5533 Save = OffsetVal;
5534 SaveIsReg = false;
5535 } else {
5536 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5537 if (!SaveOpnd.isGPRAsmReg()) {
5538 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5539 Parser.eatToEndOfStatement();
5540 return false;
5541 }
5542 Save = SaveOpnd.getGPR32Reg();
5543 }
5544
5545 if (!eatComma("unexpected token, expected comma"))
5546 return true;
5547
5548 const MCExpr *Expr;
5549 if (Parser.parseExpression(Expr)) {
5550 reportParseError("expected expression");
5551 return false;
5552 }
5553
5554 if (Expr->getKind() != MCExpr::SymbolRef) {
5555 reportParseError("expected symbol");
5556 return false;
5557 }
5558 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5559
5560 CpSaveLocation = Save;
5561 CpSaveLocationIsRegister = SaveIsReg;
5562
5563 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5564 SaveIsReg);
5565 return false;
5566 }
5567
parseDirectiveCPReturn()5568 bool MipsAsmParser::parseDirectiveCPReturn() {
5569 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5570 CpSaveLocationIsRegister);
5571 return false;
5572 }
5573
parseDirectiveNaN()5574 bool MipsAsmParser::parseDirectiveNaN() {
5575 MCAsmParser &Parser = getParser();
5576 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5577 const AsmToken &Tok = Parser.getTok();
5578
5579 if (Tok.getString() == "2008") {
5580 Parser.Lex();
5581 getTargetStreamer().emitDirectiveNaN2008();
5582 return false;
5583 } else if (Tok.getString() == "legacy") {
5584 Parser.Lex();
5585 getTargetStreamer().emitDirectiveNaNLegacy();
5586 return false;
5587 }
5588 }
5589 // If we don't recognize the option passed to the .nan
5590 // directive (e.g. no option or unknown option), emit an error.
5591 reportParseError("invalid option in .nan directive");
5592 return false;
5593 }
5594
parseDirectiveSet()5595 bool MipsAsmParser::parseDirectiveSet() {
5596 MCAsmParser &Parser = getParser();
5597 // Get the next token.
5598 const AsmToken &Tok = Parser.getTok();
5599
5600 if (Tok.getString() == "noat") {
5601 return parseSetNoAtDirective();
5602 } else if (Tok.getString() == "at") {
5603 return parseSetAtDirective();
5604 } else if (Tok.getString() == "arch") {
5605 return parseSetArchDirective();
5606 } else if (Tok.getString() == "fp") {
5607 return parseSetFpDirective();
5608 } else if (Tok.getString() == "oddspreg") {
5609 return parseSetOddSPRegDirective();
5610 } else if (Tok.getString() == "nooddspreg") {
5611 return parseSetNoOddSPRegDirective();
5612 } else if (Tok.getString() == "pop") {
5613 return parseSetPopDirective();
5614 } else if (Tok.getString() == "push") {
5615 return parseSetPushDirective();
5616 } else if (Tok.getString() == "reorder") {
5617 return parseSetReorderDirective();
5618 } else if (Tok.getString() == "noreorder") {
5619 return parseSetNoReorderDirective();
5620 } else if (Tok.getString() == "macro") {
5621 return parseSetMacroDirective();
5622 } else if (Tok.getString() == "nomacro") {
5623 return parseSetNoMacroDirective();
5624 } else if (Tok.getString() == "mips16") {
5625 return parseSetMips16Directive();
5626 } else if (Tok.getString() == "nomips16") {
5627 return parseSetNoMips16Directive();
5628 } else if (Tok.getString() == "nomicromips") {
5629 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
5630 getTargetStreamer().emitDirectiveSetNoMicroMips();
5631 Parser.eatToEndOfStatement();
5632 return false;
5633 } else if (Tok.getString() == "micromips") {
5634 return parseSetFeature(Mips::FeatureMicroMips);
5635 } else if (Tok.getString() == "mips0") {
5636 return parseSetMips0Directive();
5637 } else if (Tok.getString() == "mips1") {
5638 return parseSetFeature(Mips::FeatureMips1);
5639 } else if (Tok.getString() == "mips2") {
5640 return parseSetFeature(Mips::FeatureMips2);
5641 } else if (Tok.getString() == "mips3") {
5642 return parseSetFeature(Mips::FeatureMips3);
5643 } else if (Tok.getString() == "mips4") {
5644 return parseSetFeature(Mips::FeatureMips4);
5645 } else if (Tok.getString() == "mips5") {
5646 return parseSetFeature(Mips::FeatureMips5);
5647 } else if (Tok.getString() == "mips32") {
5648 return parseSetFeature(Mips::FeatureMips32);
5649 } else if (Tok.getString() == "mips32r2") {
5650 return parseSetFeature(Mips::FeatureMips32r2);
5651 } else if (Tok.getString() == "mips32r3") {
5652 return parseSetFeature(Mips::FeatureMips32r3);
5653 } else if (Tok.getString() == "mips32r5") {
5654 return parseSetFeature(Mips::FeatureMips32r5);
5655 } else if (Tok.getString() == "mips32r6") {
5656 return parseSetFeature(Mips::FeatureMips32r6);
5657 } else if (Tok.getString() == "mips64") {
5658 return parseSetFeature(Mips::FeatureMips64);
5659 } else if (Tok.getString() == "mips64r2") {
5660 return parseSetFeature(Mips::FeatureMips64r2);
5661 } else if (Tok.getString() == "mips64r3") {
5662 return parseSetFeature(Mips::FeatureMips64r3);
5663 } else if (Tok.getString() == "mips64r5") {
5664 return parseSetFeature(Mips::FeatureMips64r5);
5665 } else if (Tok.getString() == "mips64r6") {
5666 return parseSetFeature(Mips::FeatureMips64r6);
5667 } else if (Tok.getString() == "dsp") {
5668 return parseSetFeature(Mips::FeatureDSP);
5669 } else if (Tok.getString() == "nodsp") {
5670 return parseSetNoDspDirective();
5671 } else if (Tok.getString() == "msa") {
5672 return parseSetMsaDirective();
5673 } else if (Tok.getString() == "nomsa") {
5674 return parseSetNoMsaDirective();
5675 } else if (Tok.getString() == "softfloat") {
5676 return parseSetSoftFloatDirective();
5677 } else if (Tok.getString() == "hardfloat") {
5678 return parseSetHardFloatDirective();
5679 } else {
5680 // It is just an identifier, look for an assignment.
5681 parseSetAssignment();
5682 return false;
5683 }
5684
5685 return true;
5686 }
5687
5688 /// parseDataDirective
5689 /// ::= .word [ expression (, expression)* ]
parseDataDirective(unsigned Size,SMLoc L)5690 bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
5691 MCAsmParser &Parser = getParser();
5692 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5693 for (;;) {
5694 const MCExpr *Value;
5695 if (getParser().parseExpression(Value))
5696 return true;
5697
5698 getParser().getStreamer().EmitValue(Value, Size);
5699
5700 if (getLexer().is(AsmToken::EndOfStatement))
5701 break;
5702
5703 if (getLexer().isNot(AsmToken::Comma))
5704 return Error(L, "unexpected token, expected comma");
5705 Parser.Lex();
5706 }
5707 }
5708
5709 Parser.Lex();
5710 return false;
5711 }
5712
5713 /// parseDirectiveGpWord
5714 /// ::= .gpword local_sym
parseDirectiveGpWord()5715 bool MipsAsmParser::parseDirectiveGpWord() {
5716 MCAsmParser &Parser = getParser();
5717 const MCExpr *Value;
5718 // EmitGPRel32Value requires an expression, so we are using base class
5719 // method to evaluate the expression.
5720 if (getParser().parseExpression(Value))
5721 return true;
5722 getParser().getStreamer().EmitGPRel32Value(Value);
5723
5724 if (getLexer().isNot(AsmToken::EndOfStatement))
5725 return Error(getLexer().getLoc(),
5726 "unexpected token, expected end of statement");
5727 Parser.Lex(); // Eat EndOfStatement token.
5728 return false;
5729 }
5730
5731 /// parseDirectiveGpDWord
5732 /// ::= .gpdword local_sym
parseDirectiveGpDWord()5733 bool MipsAsmParser::parseDirectiveGpDWord() {
5734 MCAsmParser &Parser = getParser();
5735 const MCExpr *Value;
5736 // EmitGPRel64Value requires an expression, so we are using base class
5737 // method to evaluate the expression.
5738 if (getParser().parseExpression(Value))
5739 return true;
5740 getParser().getStreamer().EmitGPRel64Value(Value);
5741
5742 if (getLexer().isNot(AsmToken::EndOfStatement))
5743 return Error(getLexer().getLoc(),
5744 "unexpected token, expected end of statement");
5745 Parser.Lex(); // Eat EndOfStatement token.
5746 return false;
5747 }
5748
parseDirectiveOption()5749 bool MipsAsmParser::parseDirectiveOption() {
5750 MCAsmParser &Parser = getParser();
5751 // Get the option token.
5752 AsmToken Tok = Parser.getTok();
5753 // At the moment only identifiers are supported.
5754 if (Tok.isNot(AsmToken::Identifier)) {
5755 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
5756 Parser.eatToEndOfStatement();
5757 return false;
5758 }
5759
5760 StringRef Option = Tok.getIdentifier();
5761
5762 if (Option == "pic0") {
5763 // MipsAsmParser needs to know if the current PIC mode changes.
5764 IsPicEnabled = false;
5765
5766 getTargetStreamer().emitDirectiveOptionPic0();
5767 Parser.Lex();
5768 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5769 Error(Parser.getTok().getLoc(),
5770 "unexpected token, expected end of statement");
5771 Parser.eatToEndOfStatement();
5772 }
5773 return false;
5774 }
5775
5776 if (Option == "pic2") {
5777 // MipsAsmParser needs to know if the current PIC mode changes.
5778 IsPicEnabled = true;
5779
5780 getTargetStreamer().emitDirectiveOptionPic2();
5781 Parser.Lex();
5782 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5783 Error(Parser.getTok().getLoc(),
5784 "unexpected token, expected end of statement");
5785 Parser.eatToEndOfStatement();
5786 }
5787 return false;
5788 }
5789
5790 // Unknown option.
5791 Warning(Parser.getTok().getLoc(),
5792 "unknown option, expected 'pic0' or 'pic2'");
5793 Parser.eatToEndOfStatement();
5794 return false;
5795 }
5796
5797 /// parseInsnDirective
5798 /// ::= .insn
parseInsnDirective()5799 bool MipsAsmParser::parseInsnDirective() {
5800 // If this is not the end of the statement, report an error.
5801 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5802 reportParseError("unexpected token, expected end of statement");
5803 return false;
5804 }
5805
5806 // The actual label marking happens in
5807 // MipsELFStreamer::createPendingLabelRelocs().
5808 getTargetStreamer().emitDirectiveInsn();
5809
5810 getParser().Lex(); // Eat EndOfStatement token.
5811 return false;
5812 }
5813
5814 /// parseSSectionDirective
5815 /// ::= .sbss
5816 /// ::= .sdata
parseSSectionDirective(StringRef Section,unsigned Type)5817 bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
5818 // If this is not the end of the statement, report an error.
5819 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5820 reportParseError("unexpected token, expected end of statement");
5821 return false;
5822 }
5823
5824 MCSection *ELFSection = getContext().getELFSection(
5825 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
5826 getParser().getStreamer().SwitchSection(ELFSection);
5827
5828 getParser().Lex(); // Eat EndOfStatement token.
5829 return false;
5830 }
5831
5832 /// parseDirectiveModule
5833 /// ::= .module oddspreg
5834 /// ::= .module nooddspreg
5835 /// ::= .module fp=value
5836 /// ::= .module softfloat
5837 /// ::= .module hardfloat
parseDirectiveModule()5838 bool MipsAsmParser::parseDirectiveModule() {
5839 MCAsmParser &Parser = getParser();
5840 MCAsmLexer &Lexer = getLexer();
5841 SMLoc L = Lexer.getLoc();
5842
5843 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
5844 // TODO : get a better message.
5845 reportParseError(".module directive must appear before any code");
5846 return false;
5847 }
5848
5849 StringRef Option;
5850 if (Parser.parseIdentifier(Option)) {
5851 reportParseError("expected .module option identifier");
5852 return false;
5853 }
5854
5855 if (Option == "oddspreg") {
5856 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5857
5858 // Synchronize the abiflags information with the FeatureBits information we
5859 // changed above.
5860 getTargetStreamer().updateABIInfo(*this);
5861
5862 // If printing assembly, use the recently updated abiflags information.
5863 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5864 // emitted at the end).
5865 getTargetStreamer().emitDirectiveModuleOddSPReg();
5866
5867 // If this is not the end of the statement, report an error.
5868 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5869 reportParseError("unexpected token, expected end of statement");
5870 return false;
5871 }
5872
5873 return false; // parseDirectiveModule has finished successfully.
5874 } else if (Option == "nooddspreg") {
5875 if (!isABI_O32()) {
5876 Error(L, "'.module nooddspreg' requires the O32 ABI");
5877 return false;
5878 }
5879
5880 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5881
5882 // Synchronize the abiflags information with the FeatureBits information we
5883 // changed above.
5884 getTargetStreamer().updateABIInfo(*this);
5885
5886 // If printing assembly, use the recently updated abiflags information.
5887 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5888 // emitted at the end).
5889 getTargetStreamer().emitDirectiveModuleOddSPReg();
5890
5891 // If this is not the end of the statement, report an error.
5892 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5893 reportParseError("unexpected token, expected end of statement");
5894 return false;
5895 }
5896
5897 return false; // parseDirectiveModule has finished successfully.
5898 } else if (Option == "fp") {
5899 return parseDirectiveModuleFP();
5900 } else if (Option == "softfloat") {
5901 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5902
5903 // Synchronize the ABI Flags information with the FeatureBits information we
5904 // updated above.
5905 getTargetStreamer().updateABIInfo(*this);
5906
5907 // If printing assembly, use the recently updated ABI Flags information.
5908 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5909 // emitted later).
5910 getTargetStreamer().emitDirectiveModuleSoftFloat();
5911
5912 // If this is not the end of the statement, report an error.
5913 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5914 reportParseError("unexpected token, expected end of statement");
5915 return false;
5916 }
5917
5918 return false; // parseDirectiveModule has finished successfully.
5919 } else if (Option == "hardfloat") {
5920 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5921
5922 // Synchronize the ABI Flags information with the FeatureBits information we
5923 // updated above.
5924 getTargetStreamer().updateABIInfo(*this);
5925
5926 // If printing assembly, use the recently updated ABI Flags information.
5927 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5928 // emitted later).
5929 getTargetStreamer().emitDirectiveModuleHardFloat();
5930
5931 // If this is not the end of the statement, report an error.
5932 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5933 reportParseError("unexpected token, expected end of statement");
5934 return false;
5935 }
5936
5937 return false; // parseDirectiveModule has finished successfully.
5938 } else {
5939 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5940 }
5941 }
5942
5943 /// parseDirectiveModuleFP
5944 /// ::= =32
5945 /// ::= =xx
5946 /// ::= =64
parseDirectiveModuleFP()5947 bool MipsAsmParser::parseDirectiveModuleFP() {
5948 MCAsmParser &Parser = getParser();
5949 MCAsmLexer &Lexer = getLexer();
5950
5951 if (Lexer.isNot(AsmToken::Equal)) {
5952 reportParseError("unexpected token, expected equals sign '='");
5953 return false;
5954 }
5955 Parser.Lex(); // Eat '=' token.
5956
5957 MipsABIFlagsSection::FpABIKind FpABI;
5958 if (!parseFpABIValue(FpABI, ".module"))
5959 return false;
5960
5961 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5962 reportParseError("unexpected token, expected end of statement");
5963 return false;
5964 }
5965
5966 // Synchronize the abiflags information with the FeatureBits information we
5967 // changed above.
5968 getTargetStreamer().updateABIInfo(*this);
5969
5970 // If printing assembly, use the recently updated abiflags information.
5971 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5972 // emitted at the end).
5973 getTargetStreamer().emitDirectiveModuleFP();
5974
5975 Parser.Lex(); // Consume the EndOfStatement.
5976 return false;
5977 }
5978
parseFpABIValue(MipsABIFlagsSection::FpABIKind & FpABI,StringRef Directive)5979 bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
5980 StringRef Directive) {
5981 MCAsmParser &Parser = getParser();
5982 MCAsmLexer &Lexer = getLexer();
5983 bool ModuleLevelOptions = Directive == ".module";
5984
5985 if (Lexer.is(AsmToken::Identifier)) {
5986 StringRef Value = Parser.getTok().getString();
5987 Parser.Lex();
5988
5989 if (Value != "xx") {
5990 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5991 return false;
5992 }
5993
5994 if (!isABI_O32()) {
5995 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5996 return false;
5997 }
5998
5999 FpABI = MipsABIFlagsSection::FpABIKind::XX;
6000 if (ModuleLevelOptions) {
6001 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6002 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6003 } else {
6004 setFeatureBits(Mips::FeatureFPXX, "fpxx");
6005 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6006 }
6007 return true;
6008 }
6009
6010 if (Lexer.is(AsmToken::Integer)) {
6011 unsigned Value = Parser.getTok().getIntVal();
6012 Parser.Lex();
6013
6014 if (Value != 32 && Value != 64) {
6015 reportParseError("unsupported value, expected 'xx', '32' or '64'");
6016 return false;
6017 }
6018
6019 if (Value == 32) {
6020 if (!isABI_O32()) {
6021 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
6022 return false;
6023 }
6024
6025 FpABI = MipsABIFlagsSection::FpABIKind::S32;
6026 if (ModuleLevelOptions) {
6027 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6028 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6029 } else {
6030 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6031 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6032 }
6033 } else {
6034 FpABI = MipsABIFlagsSection::FpABIKind::S64;
6035 if (ModuleLevelOptions) {
6036 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6037 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6038 } else {
6039 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6040 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
6041 }
6042 }
6043
6044 return true;
6045 }
6046
6047 return false;
6048 }
6049
ParseDirective(AsmToken DirectiveID)6050 bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
6051 // This returns false if this function recognizes the directive
6052 // regardless of whether it is successfully handles or reports an
6053 // error. Otherwise it returns true to give the generic parser a
6054 // chance at recognizing it.
6055
6056 MCAsmParser &Parser = getParser();
6057 StringRef IDVal = DirectiveID.getString();
6058
6059 if (IDVal == ".cpload") {
6060 parseDirectiveCpLoad(DirectiveID.getLoc());
6061 return false;
6062 }
6063 if (IDVal == ".cprestore") {
6064 parseDirectiveCpRestore(DirectiveID.getLoc());
6065 return false;
6066 }
6067 if (IDVal == ".dword") {
6068 parseDataDirective(8, DirectiveID.getLoc());
6069 return false;
6070 }
6071 if (IDVal == ".ent") {
6072 StringRef SymbolName;
6073
6074 if (Parser.parseIdentifier(SymbolName)) {
6075 reportParseError("expected identifier after .ent");
6076 return false;
6077 }
6078
6079 // There's an undocumented extension that allows an integer to
6080 // follow the name of the procedure which AFAICS is ignored by GAS.
6081 // Example: .ent foo,2
6082 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6083 if (getLexer().isNot(AsmToken::Comma)) {
6084 // Even though we accept this undocumented extension for compatibility
6085 // reasons, the additional integer argument does not actually change
6086 // the behaviour of the '.ent' directive, so we would like to discourage
6087 // its use. We do this by not referring to the extended version in
6088 // error messages which are not directly related to its use.
6089 reportParseError("unexpected token, expected end of statement");
6090 return false;
6091 }
6092 Parser.Lex(); // Eat the comma.
6093 const MCExpr *DummyNumber;
6094 int64_t DummyNumberVal;
6095 // If the user was explicitly trying to use the extended version,
6096 // we still give helpful extension-related error messages.
6097 if (Parser.parseExpression(DummyNumber)) {
6098 reportParseError("expected number after comma");
6099 return false;
6100 }
6101 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
6102 reportParseError("expected an absolute expression after comma");
6103 return false;
6104 }
6105 }
6106
6107 // If this is not the end of the statement, report an error.
6108 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6109 reportParseError("unexpected token, expected end of statement");
6110 return false;
6111 }
6112
6113 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
6114
6115 getTargetStreamer().emitDirectiveEnt(*Sym);
6116 CurrentFn = Sym;
6117 IsCpRestoreSet = false;
6118 return false;
6119 }
6120
6121 if (IDVal == ".end") {
6122 StringRef SymbolName;
6123
6124 if (Parser.parseIdentifier(SymbolName)) {
6125 reportParseError("expected identifier after .end");
6126 return false;
6127 }
6128
6129 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6130 reportParseError("unexpected token, expected end of statement");
6131 return false;
6132 }
6133
6134 if (CurrentFn == nullptr) {
6135 reportParseError(".end used without .ent");
6136 return false;
6137 }
6138
6139 if ((SymbolName != CurrentFn->getName())) {
6140 reportParseError(".end symbol does not match .ent symbol");
6141 return false;
6142 }
6143
6144 getTargetStreamer().emitDirectiveEnd(SymbolName);
6145 CurrentFn = nullptr;
6146 IsCpRestoreSet = false;
6147 return false;
6148 }
6149
6150 if (IDVal == ".frame") {
6151 // .frame $stack_reg, frame_size_in_bytes, $return_reg
6152 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
6153 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
6154 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6155 reportParseError("expected stack register");
6156 return false;
6157 }
6158
6159 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6160 if (!StackRegOpnd.isGPRAsmReg()) {
6161 reportParseError(StackRegOpnd.getStartLoc(),
6162 "expected general purpose register");
6163 return false;
6164 }
6165 unsigned StackReg = StackRegOpnd.getGPR32Reg();
6166
6167 if (Parser.getTok().is(AsmToken::Comma))
6168 Parser.Lex();
6169 else {
6170 reportParseError("unexpected token, expected comma");
6171 return false;
6172 }
6173
6174 // Parse the frame size.
6175 const MCExpr *FrameSize;
6176 int64_t FrameSizeVal;
6177
6178 if (Parser.parseExpression(FrameSize)) {
6179 reportParseError("expected frame size value");
6180 return false;
6181 }
6182
6183 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
6184 reportParseError("frame size not an absolute expression");
6185 return false;
6186 }
6187
6188 if (Parser.getTok().is(AsmToken::Comma))
6189 Parser.Lex();
6190 else {
6191 reportParseError("unexpected token, expected comma");
6192 return false;
6193 }
6194
6195 // Parse the return register.
6196 TmpReg.clear();
6197 ResTy = parseAnyRegister(TmpReg);
6198 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6199 reportParseError("expected return register");
6200 return false;
6201 }
6202
6203 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6204 if (!ReturnRegOpnd.isGPRAsmReg()) {
6205 reportParseError(ReturnRegOpnd.getStartLoc(),
6206 "expected general purpose register");
6207 return false;
6208 }
6209
6210 // If this is not the end of the statement, report an error.
6211 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6212 reportParseError("unexpected token, expected end of statement");
6213 return false;
6214 }
6215
6216 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
6217 ReturnRegOpnd.getGPR32Reg());
6218 IsCpRestoreSet = false;
6219 return false;
6220 }
6221
6222 if (IDVal == ".set") {
6223 parseDirectiveSet();
6224 return false;
6225 }
6226
6227 if (IDVal == ".mask" || IDVal == ".fmask") {
6228 // .mask bitmask, frame_offset
6229 // bitmask: One bit for each register used.
6230 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
6231 // first register is expected to be saved.
6232 // Examples:
6233 // .mask 0x80000000, -4
6234 // .fmask 0x80000000, -4
6235 //
6236
6237 // Parse the bitmask
6238 const MCExpr *BitMask;
6239 int64_t BitMaskVal;
6240
6241 if (Parser.parseExpression(BitMask)) {
6242 reportParseError("expected bitmask value");
6243 return false;
6244 }
6245
6246 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
6247 reportParseError("bitmask not an absolute expression");
6248 return false;
6249 }
6250
6251 if (Parser.getTok().is(AsmToken::Comma))
6252 Parser.Lex();
6253 else {
6254 reportParseError("unexpected token, expected comma");
6255 return false;
6256 }
6257
6258 // Parse the frame_offset
6259 const MCExpr *FrameOffset;
6260 int64_t FrameOffsetVal;
6261
6262 if (Parser.parseExpression(FrameOffset)) {
6263 reportParseError("expected frame offset value");
6264 return false;
6265 }
6266
6267 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
6268 reportParseError("frame offset not an absolute expression");
6269 return false;
6270 }
6271
6272 // If this is not the end of the statement, report an error.
6273 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6274 reportParseError("unexpected token, expected end of statement");
6275 return false;
6276 }
6277
6278 if (IDVal == ".mask")
6279 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
6280 else
6281 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
6282 return false;
6283 }
6284
6285 if (IDVal == ".nan")
6286 return parseDirectiveNaN();
6287
6288 if (IDVal == ".gpword") {
6289 parseDirectiveGpWord();
6290 return false;
6291 }
6292
6293 if (IDVal == ".gpdword") {
6294 parseDirectiveGpDWord();
6295 return false;
6296 }
6297
6298 if (IDVal == ".word") {
6299 parseDataDirective(4, DirectiveID.getLoc());
6300 return false;
6301 }
6302
6303 if (IDVal == ".hword") {
6304 parseDataDirective(2, DirectiveID.getLoc());
6305 return false;
6306 }
6307
6308 if (IDVal == ".option") {
6309 parseDirectiveOption();
6310 return false;
6311 }
6312
6313 if (IDVal == ".abicalls") {
6314 getTargetStreamer().emitDirectiveAbiCalls();
6315 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
6316 Error(Parser.getTok().getLoc(),
6317 "unexpected token, expected end of statement");
6318 // Clear line
6319 Parser.eatToEndOfStatement();
6320 }
6321 return false;
6322 }
6323
6324 if (IDVal == ".cpsetup") {
6325 parseDirectiveCPSetup();
6326 return false;
6327 }
6328 if (IDVal == ".cpreturn") {
6329 parseDirectiveCPReturn();
6330 return false;
6331 }
6332 if (IDVal == ".module") {
6333 parseDirectiveModule();
6334 return false;
6335 }
6336 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
6337 parseInternalDirectiveReallowModule();
6338 return false;
6339 }
6340 if (IDVal == ".insn") {
6341 parseInsnDirective();
6342 return false;
6343 }
6344 if (IDVal == ".sbss") {
6345 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
6346 return false;
6347 }
6348 if (IDVal == ".sdata") {
6349 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
6350 return false;
6351 }
6352
6353 return true;
6354 }
6355
parseInternalDirectiveReallowModule()6356 bool MipsAsmParser::parseInternalDirectiveReallowModule() {
6357 // If this is not the end of the statement, report an error.
6358 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6359 reportParseError("unexpected token, expected end of statement");
6360 return false;
6361 }
6362
6363 getTargetStreamer().reallowModuleDirective();
6364
6365 getParser().Lex(); // Eat EndOfStatement token.
6366 return false;
6367 }
6368
LLVMInitializeMipsAsmParser()6369 extern "C" void LLVMInitializeMipsAsmParser() {
6370 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
6371 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
6372 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
6373 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
6374 }
6375
6376 #define GET_REGISTER_MATCHER
6377 #define GET_MATCHER_IMPLEMENTATION
6378 #include "MipsGenAsmMatcher.inc"
6379