Bug Summary

File:llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
Warning:line 2815, column 5
Value stored to 'Is32BitAddress' is never read

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