Bug Summary

File:lib/Target/Mips/AsmParser/MipsAsmParser.cpp
Warning:line 3785, column 31
The left operand of '==' is a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

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