Bug Summary

File:llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
Warning:line 2685, column 18
The result of the right shift is undefined due to shifting by '4294967295', which is greater or equal to the width of type 'uint64_t'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -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 -mframe-pointer=none -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/build-llvm -resource-dir /usr/lib/llvm-14/lib/clang/14.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I lib/Target/Mips/AsmParser -I /build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser -I /build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips -I lib/Target/Mips -I include -I /build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/include -D NDEBUG -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-14/lib/clang/14.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-command-line-argument -Wno-unknown-warning-option -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/build-llvm -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -fgnuc-version=4.2.1 -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2021-09-26-234817-15343-1 -x c++ /build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp

/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/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 assert(getParser().getStreamer().getTargetStreamer() &&(static_cast <bool> (getParser().getStreamer().getTargetStreamer
() && "do not have a target streamer") ? void (0) : __assert_fail
("getParser().getStreamer().getTargetStreamer() && \"do not have a target streamer\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 138, __extension__ __PRETTY_FUNCTION__))
138 "do not have a target streamer")(static_cast <bool> (getParser().getStreamer().getTargetStreamer
() && "do not have a target streamer") ? void (0) : __assert_fail
("getParser().getStreamer().getTargetStreamer() && \"do not have a target streamer\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 138, __extension__ __PRETTY_FUNCTION__))
;
139 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
140 return static_cast<MipsTargetStreamer &>(TS);
141 }
142
143 MipsABIInfo ABI;
144 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
145 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
146 // nullptr, which indicates that no function is currently
147 // selected. This usually happens after an '.end func'
148 // directive.
149 bool IsLittleEndian;
150 bool IsPicEnabled;
151 bool IsCpRestoreSet;
152 int CpRestoreOffset;
153 unsigned GPReg;
154 unsigned CpSaveLocation;
155 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
156 bool CpSaveLocationIsRegister;
157
158 // Map of register aliases created via the .set directive.
159 StringMap<AsmToken> RegisterSets;
160
161 // Print a warning along with its fix-it message at the given range.
162 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
163 SMRange Range, bool ShowColors = true);
164
165 void ConvertXWPOperands(MCInst &Inst, const OperandVector &Operands);
166
167#define GET_ASSEMBLER_HEADER
168#include "MipsGenAsmMatcher.inc"
169
170 unsigned
171 checkEarlyTargetMatchPredicate(MCInst &Inst,
172 const OperandVector &Operands) override;
173 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
174
175 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
176 OperandVector &Operands, MCStreamer &Out,
177 uint64_t &ErrorInfo,
178 bool MatchingInlineAsm) override;
179
180 /// Parse a register as used in CFI directives
181 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
182 OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
183 SMLoc &EndLoc) override;
184
185 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
186
187 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
188
189 bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);
190
191 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
192 SMLoc NameLoc, OperandVector &Operands) override;
193
194 bool ParseDirective(AsmToken DirectiveID) override;
195
196 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
197 OperandMatchResultTy
198 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
199 StringRef Identifier, SMLoc S);
200 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
201 const AsmToken &Token,
202 SMLoc S);
203 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
204 SMLoc S);
205 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
206 OperandMatchResultTy parseImm(OperandVector &Operands);
207 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
208 OperandMatchResultTy parseInvNum(OperandVector &Operands);
209 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
210
211 bool searchSymbolAlias(OperandVector &Operands);
212
213 bool parseOperand(OperandVector &, StringRef Mnemonic);
214
215 enum MacroExpanderResultTy {
216 MER_NotAMacro,
217 MER_Success,
218 MER_Fail,
219 };
220
221 // Expands assembly pseudo instructions.
222 MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
223 MCStreamer &Out,
224 const MCSubtargetInfo *STI);
225
226 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
227 const MCSubtargetInfo *STI);
228
229 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
230 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
231 MCStreamer &Out, const MCSubtargetInfo *STI);
232
233 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
234 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
235 MCStreamer &Out, const MCSubtargetInfo *STI);
236
237 bool emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc, MCSymbol *Sym);
238
239 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
240 MCStreamer &Out, const MCSubtargetInfo *STI);
241
242 bool expandLoadSingleImmToGPR(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
243 const MCSubtargetInfo *STI);
244 bool expandLoadSingleImmToFPR(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
245 const MCSubtargetInfo *STI);
246 bool expandLoadDoubleImmToGPR(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
247 const MCSubtargetInfo *STI);
248 bool expandLoadDoubleImmToFPR(MCInst &Inst, bool Is64FPU, SMLoc IDLoc,
249 MCStreamer &Out, const MCSubtargetInfo *STI);
250
251 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
252 const MCOperand &Offset, bool Is32BitAddress,
253 SMLoc IDLoc, MCStreamer &Out,
254 const MCSubtargetInfo *STI);
255
256 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
257 const MCSubtargetInfo *STI);
258
259 void expandMem16Inst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
260 const MCSubtargetInfo *STI, bool IsLoad);
261 void expandMem9Inst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
262 const MCSubtargetInfo *STI, bool IsLoad);
263
264 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
265 const MCSubtargetInfo *STI);
266
267 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
268 const MCSubtargetInfo *STI);
269
270 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
271 const MCSubtargetInfo *STI);
272
273 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
274 const MCSubtargetInfo *STI);
275
276 bool expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
277 const MCSubtargetInfo *STI, const bool IsMips64,
278 const bool Signed);
279
280 bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
281 MCStreamer &Out, const MCSubtargetInfo *STI);
282
283 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out,
284 const MCSubtargetInfo *STI);
285
286 bool expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
287 const MCSubtargetInfo *STI);
288
289 bool expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
290 const MCSubtargetInfo *STI);
291
292 bool expandSge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
293 const MCSubtargetInfo *STI);
294
295 bool expandSgeImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
296 const MCSubtargetInfo *STI);
297
298 bool expandSgtImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
299 const MCSubtargetInfo *STI);
300
301 bool expandSle(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
302 const MCSubtargetInfo *STI);
303
304 bool expandSleImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
305 const MCSubtargetInfo *STI);
306
307 bool expandRotation(MCInst &Inst, SMLoc IDLoc,
308 MCStreamer &Out, const MCSubtargetInfo *STI);
309 bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
310 const MCSubtargetInfo *STI);
311 bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
312 const MCSubtargetInfo *STI);
313 bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
314 const MCSubtargetInfo *STI);
315
316 bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
317 const MCSubtargetInfo *STI);
318
319 bool expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
320 const MCSubtargetInfo *STI);
321
322 bool expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
323 const MCSubtargetInfo *STI);
324
325 bool expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
326 const MCSubtargetInfo *STI);
327
328 bool expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
329 const MCSubtargetInfo *STI);
330
331 bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
332 const MCSubtargetInfo *STI, bool IsLoad);
333
334 bool expandStoreDM1Macro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
335 const MCSubtargetInfo *STI);
336
337 bool expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
338 const MCSubtargetInfo *STI);
339
340 bool expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
341 const MCSubtargetInfo *STI);
342
343 bool expandSne(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
344 const MCSubtargetInfo *STI);
345
346 bool expandSneI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
347 const MCSubtargetInfo *STI);
348
349 bool expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
350 const MCSubtargetInfo *STI);
351
352 bool expandSaaAddr(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
353 const MCSubtargetInfo *STI);
354
355 bool reportParseError(const Twine &ErrorMsg);
356 bool reportParseError(SMLoc Loc, const Twine &ErrorMsg);
357
358 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
359
360 bool parseSetMips0Directive();
361 bool parseSetArchDirective();
362 bool parseSetFeature(uint64_t Feature);
363 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
364 bool parseDirectiveCpAdd(SMLoc Loc);
365 bool parseDirectiveCpLoad(SMLoc Loc);
366 bool parseDirectiveCpLocal(SMLoc Loc);
367 bool parseDirectiveCpRestore(SMLoc Loc);
368 bool parseDirectiveCPSetup();
369 bool parseDirectiveCPReturn();
370 bool parseDirectiveNaN();
371 bool parseDirectiveSet();
372 bool parseDirectiveOption();
373 bool parseInsnDirective();
374 bool parseRSectionDirective(StringRef Section);
375 bool parseSSectionDirective(StringRef Section, unsigned Type);
376
377 bool parseSetAtDirective();
378 bool parseSetNoAtDirective();
379 bool parseSetMacroDirective();
380 bool parseSetNoMacroDirective();
381 bool parseSetMsaDirective();
382 bool parseSetNoMsaDirective();
383 bool parseSetNoDspDirective();
384 bool parseSetNoMips3DDirective();
385 bool parseSetReorderDirective();
386 bool parseSetNoReorderDirective();
387 bool parseSetMips16Directive();
388 bool parseSetNoMips16Directive();
389 bool parseSetFpDirective();
390 bool parseSetOddSPRegDirective();
391 bool parseSetNoOddSPRegDirective();
392 bool parseSetPopDirective();
393 bool parseSetPushDirective();
394 bool parseSetSoftFloatDirective();
395 bool parseSetHardFloatDirective();
396 bool parseSetMtDirective();
397 bool parseSetNoMtDirective();
398 bool parseSetNoCRCDirective();
399 bool parseSetNoVirtDirective();
400 bool parseSetNoGINVDirective();
401
402 bool parseSetAssignment();
403
404 bool parseDirectiveGpWord();
405 bool parseDirectiveGpDWord();
406 bool parseDirectiveDtpRelWord();
407 bool parseDirectiveDtpRelDWord();
408 bool parseDirectiveTpRelWord();
409 bool parseDirectiveTpRelDWord();
410 bool parseDirectiveModule();
411 bool parseDirectiveModuleFP();
412 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
413 StringRef Directive);
414
415 bool parseInternalDirectiveReallowModule();
416
417 bool eatComma(StringRef ErrorStr);
418
419 int matchCPURegisterName(StringRef Symbol);
420
421 int matchHWRegsRegisterName(StringRef Symbol);
422
423 int matchFPURegisterName(StringRef Name);
424
425 int matchFCCRegisterName(StringRef Name);
426
427 int matchACRegisterName(StringRef Name);
428
429 int matchMSA128RegisterName(StringRef Name);
430
431 int matchMSA128CtrlRegisterName(StringRef Name);
432
433 unsigned getReg(int RC, int RegNo);
434
435 /// Returns the internal register number for the current AT. Also checks if
436 /// the current AT is unavailable (set to $0) and gives an error if it is.
437 /// This should be used in pseudo-instruction expansions which need AT.
438 unsigned getATReg(SMLoc Loc);
439
440 bool canUseATReg();
441
442 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
443 const MCSubtargetInfo *STI);
444
445 // Helper function that checks if the value of a vector index is within the
446 // boundaries of accepted values for each RegisterKind
447 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
448 bool validateMSAIndex(int Val, int RegKind);
449
450 // Selects a new architecture by updating the FeatureBits with the necessary
451 // info including implied dependencies.
452 // Internally, it clears all the feature bits related to *any* architecture
453 // and selects the new one using the ToggleFeature functionality of the
454 // MCSubtargetInfo object that handles implied dependencies. The reason we
455 // clear all the arch related bits manually is because ToggleFeature only
456 // clears the features that imply the feature being cleared and not the
457 // features implied by the feature being cleared. This is easier to see
458 // with an example:
459 // --------------------------------------------------
460 // | Feature | Implies |
461 // | -------------------------------------------------|
462 // | FeatureMips1 | None |
463 // | FeatureMips2 | FeatureMips1 |
464 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
465 // | FeatureMips4 | FeatureMips3 |
466 // | ... | |
467 // --------------------------------------------------
468 //
469 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
470 // FeatureMipsGP64 | FeatureMips1)
471 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
472 void selectArch(StringRef ArchFeature) {
473 MCSubtargetInfo &STI = copySTI();
474 FeatureBitset FeatureBits = STI.getFeatureBits();
475 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
476 STI.setFeatureBits(FeatureBits);
477 setAvailableFeatures(
478 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
479 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
480 }
481
482 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
483 if (!(getSTI().getFeatureBits()[Feature])) {
484 MCSubtargetInfo &STI = copySTI();
485 setAvailableFeatures(
486 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
487 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
488 }
489 }
490
491 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
492 if (getSTI().getFeatureBits()[Feature]) {
493 MCSubtargetInfo &STI = copySTI();
494 setAvailableFeatures(
495 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
496 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
497 }
498 }
499
500 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
501 setFeatureBits(Feature, FeatureString);
502 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
503 }
504
505 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
506 clearFeatureBits(Feature, FeatureString);
507 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
508 }
509
510public:
511 enum MipsMatchResultTy {
512 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
513 Match_RequiresDifferentOperands,
514 Match_RequiresNoZeroRegister,
515 Match_RequiresSameSrcAndDst,
516 Match_NoFCCRegisterForCurrentISA,
517 Match_NonZeroOperandForSync,
518 Match_NonZeroOperandForMTCX,
519 Match_RequiresPosSizeRange0_32,
520 Match_RequiresPosSizeRange33_64,
521 Match_RequiresPosSizeUImm6,
522#define GET_OPERAND_DIAGNOSTIC_TYPES
523#include "MipsGenAsmMatcher.inc"
524#undef GET_OPERAND_DIAGNOSTIC_TYPES
525 };
526
527 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
528 const MCInstrInfo &MII, const MCTargetOptions &Options)
529 : MCTargetAsmParser(Options, sti, MII),
530 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
531 sti.getCPU(), Options)) {
532 MCAsmParserExtension::Initialize(parser);
533
534 parser.addAliasForDirective(".asciiz", ".asciz");
535 parser.addAliasForDirective(".hword", ".2byte");
536 parser.addAliasForDirective(".word", ".4byte");
537 parser.addAliasForDirective(".dword", ".8byte");
538
539 // Initialize the set of available features.
540 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
541
542 // Remember the initial assembler options. The user can not modify these.
543 AssemblerOptions.push_back(
544 std::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
545
546 // Create an assembler options environment for the user to modify.
547 AssemblerOptions.push_back(
548 std::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
549
550 getTargetStreamer().updateABIInfo(*this);
551
552 if (!isABI_O32() && !useOddSPReg() != 0)
553 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
554
555 CurrentFn = nullptr;
556
557 IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
558
559 IsCpRestoreSet = false;
560 CpRestoreOffset = -1;
561 GPReg = ABI.GetGlobalPtr();
562
563 const Triple &TheTriple = sti.getTargetTriple();
564 IsLittleEndian = TheTriple.isLittleEndian();
565
566 if (getSTI().getCPU() == "mips64r6" && inMicroMipsMode())
567 report_fatal_error("microMIPS64R6 is not supported", false);
568
569 if (!isABI_O32() && inMicroMipsMode())
570 report_fatal_error("microMIPS64 is not supported", false);
571 }
572
573 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
574 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
575
576 bool isGP64bit() const {
577 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
578 }
579
580 bool isFP64bit() const {
581 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
582 }
583
584 bool isJalrRelocAvailable(const MCExpr *JalExpr) {
585 if (!EmitJalrReloc)
586 return false;
587 MCValue Res;
588 if (!JalExpr->evaluateAsRelocatable(Res, nullptr, nullptr))
589 return false;
590 if (Res.getSymB() != nullptr)
591 return false;
592 if (Res.getConstant() != 0)
593 return ABI.IsN32() || ABI.IsN64();
594 return true;
595 }
596
597 const MipsABIInfo &getABI() const { return ABI; }
598 bool isABI_N32() const { return ABI.IsN32(); }
599 bool isABI_N64() const { return ABI.IsN64(); }
600 bool isABI_O32() const { return ABI.IsO32(); }
601 bool isABI_FPXX() const {
602 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
603 }
604
605 bool useOddSPReg() const {
606 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
607 }
608
609 bool inMicroMipsMode() const {
610 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
611 }
612
613 bool hasMips1() const {
614 return getSTI().getFeatureBits()[Mips::FeatureMips1];
615 }
616
617 bool hasMips2() const {
618 return getSTI().getFeatureBits()[Mips::FeatureMips2];
619 }
620
621 bool hasMips3() const {
622 return getSTI().getFeatureBits()[Mips::FeatureMips3];
623 }
624
625 bool hasMips4() const {
626 return getSTI().getFeatureBits()[Mips::FeatureMips4];
627 }
628
629 bool hasMips5() const {
630 return getSTI().getFeatureBits()[Mips::FeatureMips5];
631 }
632
633 bool hasMips32() const {
634 return getSTI().getFeatureBits()[Mips::FeatureMips32];
635 }
636
637 bool hasMips64() const {
638 return getSTI().getFeatureBits()[Mips::FeatureMips64];
639 }
640
641 bool hasMips32r2() const {
642 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
643 }
644
645 bool hasMips64r2() const {
646 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
647 }
648
649 bool hasMips32r3() const {
650 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
651 }
652
653 bool hasMips64r3() const {
654 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
655 }
656
657 bool hasMips32r5() const {
658 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
659 }
660
661 bool hasMips64r5() const {
662 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
663 }
664
665 bool hasMips32r6() const {
666 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
667 }
668
669 bool hasMips64r6() const {
670 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
671 }
672
673 bool hasDSP() const {
674 return getSTI().getFeatureBits()[Mips::FeatureDSP];
675 }
676
677 bool hasDSPR2() const {
678 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
679 }
680
681 bool hasDSPR3() const {
682 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
683 }
684
685 bool hasMSA() const {
686 return getSTI().getFeatureBits()[Mips::FeatureMSA];
687 }
688
689 bool hasCnMips() const {
690 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
691 }
692
693 bool hasCnMipsP() const {
694 return (getSTI().getFeatureBits()[Mips::FeatureCnMipsP]);
695 }
696
697 bool inPicMode() {
698 return IsPicEnabled;
699 }
700
701 bool inMips16Mode() const {
702 return getSTI().getFeatureBits()[Mips::FeatureMips16];
703 }
704
705 bool useTraps() const {
706 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
707 }
708
709 bool useSoftFloat() const {
710 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
711 }
712 bool hasMT() const {
713 return getSTI().getFeatureBits()[Mips::FeatureMT];
714 }
715
716 bool hasCRC() const {
717 return getSTI().getFeatureBits()[Mips::FeatureCRC];
718 }
719
720 bool hasVirt() const {
721 return getSTI().getFeatureBits()[Mips::FeatureVirt];
722 }
723
724 bool hasGINV() const {
725 return getSTI().getFeatureBits()[Mips::FeatureGINV];
726 }
727
728 /// Warn if RegIndex is the same as the current AT.
729 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
730
731 void warnIfNoMacro(SMLoc Loc);
732
733 bool isLittle() const { return IsLittleEndian; }
734
735 const MCExpr *createTargetUnaryExpr(const MCExpr *E,
736 AsmToken::TokenKind OperatorToken,
737 MCContext &Ctx) override {
738 switch(OperatorToken) {
739 default:
740 llvm_unreachable("Unknown token")::llvm::llvm_unreachable_internal("Unknown token", "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 740)
;
741 return nullptr;
742 case AsmToken::PercentCall16:
743 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, E, Ctx);
744 case AsmToken::PercentCall_Hi:
745 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16, E, Ctx);
746 case AsmToken::PercentCall_Lo:
747 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16, E, Ctx);
748 case AsmToken::PercentDtprel_Hi:
749 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_HI, E, Ctx);
750 case AsmToken::PercentDtprel_Lo:
751 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_LO, E, Ctx);
752 case AsmToken::PercentGot:
753 return MipsMCExpr::create(MipsMCExpr::MEK_GOT, E, Ctx);
754 case AsmToken::PercentGot_Disp:
755 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, E, Ctx);
756 case AsmToken::PercentGot_Hi:
757 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, E, Ctx);
758 case AsmToken::PercentGot_Lo:
759 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_LO16, E, Ctx);
760 case AsmToken::PercentGot_Ofst:
761 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_OFST, E, Ctx);
762 case AsmToken::PercentGot_Page:
763 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_PAGE, E, Ctx);
764 case AsmToken::PercentGottprel:
765 return MipsMCExpr::create(MipsMCExpr::MEK_GOTTPREL, E, Ctx);
766 case AsmToken::PercentGp_Rel:
767 return MipsMCExpr::create(MipsMCExpr::MEK_GPREL, E, Ctx);
768 case AsmToken::PercentHi:
769 return MipsMCExpr::create(MipsMCExpr::MEK_HI, E, Ctx);
770 case AsmToken::PercentHigher:
771 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, E, Ctx);
772 case AsmToken::PercentHighest:
773 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, E, Ctx);
774 case AsmToken::PercentLo:
775 return MipsMCExpr::create(MipsMCExpr::MEK_LO, E, Ctx);
776 case AsmToken::PercentNeg:
777 return MipsMCExpr::create(MipsMCExpr::MEK_NEG, E, Ctx);
778 case AsmToken::PercentPcrel_Hi:
779 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_HI16, E, Ctx);
780 case AsmToken::PercentPcrel_Lo:
781 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_LO16, E, Ctx);
782 case AsmToken::PercentTlsgd:
783 return MipsMCExpr::create(MipsMCExpr::MEK_TLSGD, E, Ctx);
784 case AsmToken::PercentTlsldm:
785 return MipsMCExpr::create(MipsMCExpr::MEK_TLSLDM, E, Ctx);
786 case AsmToken::PercentTprel_Hi:
787 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_HI, E, Ctx);
788 case AsmToken::PercentTprel_Lo:
789 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_LO, E, Ctx);
790 }
791 }
792};
793
794/// MipsOperand - Instances of this class represent a parsed Mips machine
795/// instruction.
796class MipsOperand : public MCParsedAsmOperand {
797public:
798 /// Broad categories of register classes
799 /// The exact class is finalized by the render method.
800 enum RegKind {
801 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
802 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
803 /// isFP64bit())
804 RegKind_FCC = 4, /// FCC
805 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
806 RegKind_MSACtrl = 16, /// MSA control registers
807 RegKind_COP2 = 32, /// COP2
808 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
809 /// context).
810 RegKind_CCR = 128, /// CCR
811 RegKind_HWRegs = 256, /// HWRegs
812 RegKind_COP3 = 512, /// COP3
813 RegKind_COP0 = 1024, /// COP0
814 /// Potentially any (e.g. $1)
815 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
816 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
817 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
818 };
819
820private:
821 enum KindTy {
822 k_Immediate, /// An immediate (possibly involving symbol references)
823 k_Memory, /// Base + Offset Memory Address
824 k_RegisterIndex, /// A register index in one or more RegKind.
825 k_Token, /// A simple token
826 k_RegList, /// A physical register list
827 } Kind;
828
829public:
830 MipsOperand(KindTy K, MipsAsmParser &Parser)
831 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
832
833 ~MipsOperand() override {
834 switch (Kind) {
835 case k_Memory:
836 delete Mem.Base;
837 break;
838 case k_RegList:
839 delete RegList.List;
840 break;
841 case k_Immediate:
842 case k_RegisterIndex:
843 case k_Token:
844 break;
845 }
846 }
847
848private:
849 /// For diagnostics, and checking the assembler temporary
850 MipsAsmParser &AsmParser;
851
852 struct Token {
853 const char *Data;
854 unsigned Length;
855 };
856
857 struct RegIdxOp {
858 unsigned Index; /// Index into the register class
859 RegKind Kind; /// Bitfield of the kinds it could possibly be
860 struct Token Tok; /// The input token this operand originated from.
861 const MCRegisterInfo *RegInfo;
862 };
863
864 struct ImmOp {
865 const MCExpr *Val;
866 };
867
868 struct MemOp {
869 MipsOperand *Base;
870 const MCExpr *Off;
871 };
872
873 struct RegListOp {
874 SmallVector<unsigned, 10> *List;
875 };
876
877 union {
878 struct Token Tok;
879 struct RegIdxOp RegIdx;
880 struct ImmOp Imm;
881 struct MemOp Mem;
882 struct RegListOp RegList;
883 };
884
885 SMLoc StartLoc, EndLoc;
886
887 /// Internal constructor for register kinds
888 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str,
889 RegKind RegKind,
890 const MCRegisterInfo *RegInfo,
891 SMLoc S, SMLoc E,
892 MipsAsmParser &Parser) {
893 auto Op = std::make_unique<MipsOperand>(k_RegisterIndex, Parser);
894 Op->RegIdx.Index = Index;
895 Op->RegIdx.RegInfo = RegInfo;
896 Op->RegIdx.Kind = RegKind;
897 Op->RegIdx.Tok.Data = Str.data();
898 Op->RegIdx.Tok.Length = Str.size();
899 Op->StartLoc = S;
900 Op->EndLoc = E;
901 return Op;
902 }
903
904public:
905 /// Coerce the register to GPR32 and return the real register for the current
906 /// target.
907 unsigned getGPR32Reg() const {
908 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!")(static_cast <bool> (isRegIdx() && (RegIdx.Kind
& RegKind_GPR) && "Invalid access!") ? void (0) :
__assert_fail ("isRegIdx() && (RegIdx.Kind & RegKind_GPR) && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 908, __extension__ __PRETTY_FUNCTION__))
;
909 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
910 unsigned ClassID = Mips::GPR32RegClassID;
911 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
912 }
913
914 /// Coerce the register to GPR32 and return the real register for the current
915 /// target.
916 unsigned getGPRMM16Reg() const {
917 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!")(static_cast <bool> (isRegIdx() && (RegIdx.Kind
& RegKind_GPR) && "Invalid access!") ? void (0) :
__assert_fail ("isRegIdx() && (RegIdx.Kind & RegKind_GPR) && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 917, __extension__ __PRETTY_FUNCTION__))
;
918 unsigned ClassID = Mips::GPR32RegClassID;
919 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
920 }
921
922 /// Coerce the register to GPR64 and return the real register for the current
923 /// target.
924 unsigned getGPR64Reg() const {
925 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!")(static_cast <bool> (isRegIdx() && (RegIdx.Kind
& RegKind_GPR) && "Invalid access!") ? void (0) :
__assert_fail ("isRegIdx() && (RegIdx.Kind & RegKind_GPR) && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 925, __extension__ __PRETTY_FUNCTION__))
;
926 unsigned ClassID = Mips::GPR64RegClassID;
927 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
928 }
929
930private:
931 /// Coerce the register to AFGR64 and return the real register for the current
932 /// target.
933 unsigned getAFGR64Reg() const {
934 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!")(static_cast <bool> (isRegIdx() && (RegIdx.Kind
& RegKind_FGR) && "Invalid access!") ? void (0) :
__assert_fail ("isRegIdx() && (RegIdx.Kind & RegKind_FGR) && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 934, __extension__ __PRETTY_FUNCTION__))
;
935 if (RegIdx.Index % 2 != 0)
936 AsmParser.Warning(StartLoc, "Float register should be even.");
937 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
938 .getRegister(RegIdx.Index / 2);
939 }
940
941 /// Coerce the register to FGR64 and return the real register for the current
942 /// target.
943 unsigned getFGR64Reg() const {
944 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!")(static_cast <bool> (isRegIdx() && (RegIdx.Kind
& RegKind_FGR) && "Invalid access!") ? void (0) :
__assert_fail ("isRegIdx() && (RegIdx.Kind & RegKind_FGR) && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 944, __extension__ __PRETTY_FUNCTION__))
;
945 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
946 .getRegister(RegIdx.Index);
947 }
948
949 /// Coerce the register to FGR32 and return the real register for the current
950 /// target.
951 unsigned getFGR32Reg() const {
952 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!")(static_cast <bool> (isRegIdx() && (RegIdx.Kind
& RegKind_FGR) && "Invalid access!") ? void (0) :
__assert_fail ("isRegIdx() && (RegIdx.Kind & RegKind_FGR) && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 952, __extension__ __PRETTY_FUNCTION__))
;
953 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
954 .getRegister(RegIdx.Index);
955 }
956
957 /// Coerce the register to FCC and return the real register for the current
958 /// target.
959 unsigned getFCCReg() const {
960 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!")(static_cast <bool> (isRegIdx() && (RegIdx.Kind
& RegKind_FCC) && "Invalid access!") ? void (0) :
__assert_fail ("isRegIdx() && (RegIdx.Kind & RegKind_FCC) && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 960, __extension__ __PRETTY_FUNCTION__))
;
961 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
962 .getRegister(RegIdx.Index);
963 }
964
965 /// Coerce the register to MSA128 and return the real register for the current
966 /// target.
967 unsigned getMSA128Reg() const {
968 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!")(static_cast <bool> (isRegIdx() && (RegIdx.Kind
& RegKind_MSA128) && "Invalid access!") ? void (
0) : __assert_fail ("isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 968, __extension__ __PRETTY_FUNCTION__))
;
969 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
970 // identical
971 unsigned ClassID = Mips::MSA128BRegClassID;
972 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
973 }
974
975 /// Coerce the register to MSACtrl and return the real register for the
976 /// current target.
977 unsigned getMSACtrlReg() const {
978 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!")(static_cast <bool> (isRegIdx() && (RegIdx.Kind
& RegKind_MSACtrl) && "Invalid access!") ? void (
0) : __assert_fail ("isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 978, __extension__ __PRETTY_FUNCTION__))
;
979 unsigned ClassID = Mips::MSACtrlRegClassID;
980 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
981 }
982
983 /// Coerce the register to COP0 and return the real register for the
984 /// current target.
985 unsigned getCOP0Reg() const {
986 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!")(static_cast <bool> (isRegIdx() && (RegIdx.Kind
& RegKind_COP0) && "Invalid access!") ? void (0)
: __assert_fail ("isRegIdx() && (RegIdx.Kind & RegKind_COP0) && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 986, __extension__ __PRETTY_FUNCTION__))
;
987 unsigned ClassID = Mips::COP0RegClassID;
988 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
989 }
990
991 /// Coerce the register to COP2 and return the real register for the
992 /// current target.
993 unsigned getCOP2Reg() const {
994 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!")(static_cast <bool> (isRegIdx() && (RegIdx.Kind
& RegKind_COP2) && "Invalid access!") ? void (0)
: __assert_fail ("isRegIdx() && (RegIdx.Kind & RegKind_COP2) && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 994, __extension__ __PRETTY_FUNCTION__))
;
995 unsigned ClassID = Mips::COP2RegClassID;
996 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
997 }
998
999 /// Coerce the register to COP3 and return the real register for the
1000 /// current target.
1001 unsigned getCOP3Reg() const {
1002 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!")(static_cast <bool> (isRegIdx() && (RegIdx.Kind
& RegKind_COP3) && "Invalid access!") ? void (0)
: __assert_fail ("isRegIdx() && (RegIdx.Kind & RegKind_COP3) && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1002, __extension__ __PRETTY_FUNCTION__))
;
1003 unsigned ClassID = Mips::COP3RegClassID;
1004 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
1005 }
1006
1007 /// Coerce the register to ACC64DSP and return the real register for the
1008 /// current target.
1009 unsigned getACC64DSPReg() const {
1010 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!")(static_cast <bool> (isRegIdx() && (RegIdx.Kind
& RegKind_ACC) && "Invalid access!") ? void (0) :
__assert_fail ("isRegIdx() && (RegIdx.Kind & RegKind_ACC) && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1010, __extension__ __PRETTY_FUNCTION__))
;
1011 unsigned ClassID = Mips::ACC64DSPRegClassID;
1012 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
1013 }
1014
1015 /// Coerce the register to HI32DSP and return the real register for the
1016 /// current target.
1017 unsigned getHI32DSPReg() const {
1018 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!")(static_cast <bool> (isRegIdx() && (RegIdx.Kind
& RegKind_ACC) && "Invalid access!") ? void (0) :
__assert_fail ("isRegIdx() && (RegIdx.Kind & RegKind_ACC) && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1018, __extension__ __PRETTY_FUNCTION__))
;
1019 unsigned ClassID = Mips::HI32DSPRegClassID;
1020 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
1021 }
1022
1023 /// Coerce the register to LO32DSP and return the real register for the
1024 /// current target.
1025 unsigned getLO32DSPReg() const {
1026 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!")(static_cast <bool> (isRegIdx() && (RegIdx.Kind
& RegKind_ACC) && "Invalid access!") ? void (0) :
__assert_fail ("isRegIdx() && (RegIdx.Kind & RegKind_ACC) && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1026, __extension__ __PRETTY_FUNCTION__))
;
1027 unsigned ClassID = Mips::LO32DSPRegClassID;
1028 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
1029 }
1030
1031 /// Coerce the register to CCR and return the real register for the
1032 /// current target.
1033 unsigned getCCRReg() const {
1034 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!")(static_cast <bool> (isRegIdx() && (RegIdx.Kind
& RegKind_CCR) && "Invalid access!") ? void (0) :
__assert_fail ("isRegIdx() && (RegIdx.Kind & RegKind_CCR) && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1034, __extension__ __PRETTY_FUNCTION__))
;
1035 unsigned ClassID = Mips::CCRRegClassID;
1036 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
1037 }
1038
1039 /// Coerce the register to HWRegs and return the real register for the
1040 /// current target.
1041 unsigned getHWRegsReg() const {
1042 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!")(static_cast <bool> (isRegIdx() && (RegIdx.Kind
& RegKind_HWRegs) && "Invalid access!") ? void (
0) : __assert_fail ("isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1042, __extension__ __PRETTY_FUNCTION__))
;
1043 unsigned ClassID = Mips::HWRegsRegClassID;
1044 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
1045 }
1046
1047public:
1048 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1049 // Add as immediate when possible. Null MCExpr = 0.
1050 if (!Expr)
1051 Inst.addOperand(MCOperand::createImm(0));
1052 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
1053 Inst.addOperand(MCOperand::createImm(CE->getValue()));
1054 else
1055 Inst.addOperand(MCOperand::createExpr(Expr));
1056 }
1057
1058 void addRegOperands(MCInst &Inst, unsigned N) const {
1059 llvm_unreachable("Use a custom parser instead")::llvm::llvm_unreachable_internal("Use a custom parser instead"
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1059)
;
1060 }
1061
1062 /// Render the operand to an MCInst as a GPR32
1063 /// Asserts if the wrong number of operands are requested, or the operand
1064 /// is not a k_RegisterIndex compatible with RegKind_GPR
1065 void addGPR32ZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
1066 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1066, __extension__ __PRETTY_FUNCTION__))
;
1067 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
1068 }
1069
1070 void addGPR32NonZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
1071 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1071, __extension__ __PRETTY_FUNCTION__))
;
1072 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
1073 }
1074
1075 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1076 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1076, __extension__ __PRETTY_FUNCTION__))
;
1077 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
1078 }
1079
1080 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
1081 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1081, __extension__ __PRETTY_FUNCTION__))
;
1082 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
1083 }
1084
1085 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
1086 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1086, __extension__ __PRETTY_FUNCTION__))
;
1087 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
1088 }
1089
1090 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
1091 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1091, __extension__ __PRETTY_FUNCTION__))
;
1092 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
1093 }
1094
1095 void addGPRMM16AsmRegMovePPairFirstOperands(MCInst &Inst, unsigned N) const {
1096 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1096, __extension__ __PRETTY_FUNCTION__))
;
1097 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
1098 }
1099
1100 void addGPRMM16AsmRegMovePPairSecondOperands(MCInst &Inst,
1101 unsigned N) const {
1102 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1102, __extension__ __PRETTY_FUNCTION__))
;
1103 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
1104 }
1105
1106 /// Render the operand to an MCInst as a GPR64
1107 /// Asserts if the wrong number of operands are requested, or the operand
1108 /// is not a k_RegisterIndex compatible with RegKind_GPR
1109 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1110 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1110, __extension__ __PRETTY_FUNCTION__))
;
1111 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
1112 }
1113
1114 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1115 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1115, __extension__ __PRETTY_FUNCTION__))
;
1116 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
1117 }
1118
1119 void addStrictlyAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1120 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1120, __extension__ __PRETTY_FUNCTION__))
;
1121 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
1122 }
1123
1124 void addStrictlyFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1125 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1125, __extension__ __PRETTY_FUNCTION__))
;
1126 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
1127 }
1128
1129 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1130 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1130, __extension__ __PRETTY_FUNCTION__))
;
1131 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
1132 }
1133
1134 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1135 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1135, __extension__ __PRETTY_FUNCTION__))
;
1136 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
1137 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
1138 // FIXME: This should propagate failure up to parseStatement.
1139 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
1140 AsmParser.getParser().printError(
1141 StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1142 "registers");
1143 }
1144
1145 void addStrictlyFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1146 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1146, __extension__ __PRETTY_FUNCTION__))
;
1147 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
1148 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
1149 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
1150 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1151 "registers");
1152 }
1153
1154 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
1155 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1155, __extension__ __PRETTY_FUNCTION__))
;
1156 Inst.addOperand(MCOperand::createReg(getFCCReg()));
1157 }
1158
1159 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
1160 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1160, __extension__ __PRETTY_FUNCTION__))
;
1161 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
1162 }
1163
1164 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
1165 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1165, __extension__ __PRETTY_FUNCTION__))
;
1166 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
1167 }
1168
1169 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
1170 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1170, __extension__ __PRETTY_FUNCTION__))
;
1171 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
1172 }
1173
1174 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
1175 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1175, __extension__ __PRETTY_FUNCTION__))
;
1176 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
1177 }
1178
1179 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
1180 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1180, __extension__ __PRETTY_FUNCTION__))
;
1181 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
1182 }
1183
1184 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1185 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1185, __extension__ __PRETTY_FUNCTION__))
;
1186 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
1187 }
1188
1189 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1190 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1190, __extension__ __PRETTY_FUNCTION__))
;
1191 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
1192 }
1193
1194 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1195 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1195, __extension__ __PRETTY_FUNCTION__))
;
1196 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
1197 }
1198
1199 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
1200 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1200, __extension__ __PRETTY_FUNCTION__))
;
1201 Inst.addOperand(MCOperand::createReg(getCCRReg()));
1202 }
1203
1204 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
1205 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1205, __extension__ __PRETTY_FUNCTION__))
;
1206 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
1207 }
1208
1209 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
1210 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
1211 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1211, __extension__ __PRETTY_FUNCTION__))
;
1212 uint64_t Imm = getConstantImm() - Offset;
1213 Imm &= (1ULL << Bits) - 1;
1214 Imm += Offset;
1215 Imm += AdjustOffset;
1216 Inst.addOperand(MCOperand::createImm(Imm));
1217 }
1218
1219 template <unsigned Bits>
1220 void addSImmOperands(MCInst &Inst, unsigned N) const {
1221 if (isImm() && !isConstantImm()) {
1222 addExpr(Inst, getImm());
1223 return;
1224 }
1225 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
1226 }
1227
1228 template <unsigned Bits>
1229 void addUImmOperands(MCInst &Inst, unsigned N) const {
1230 if (isImm() && !isConstantImm()) {
1231 addExpr(Inst, getImm());
1232 return;
1233 }
1234 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
1235 }
1236
1237 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
1238 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
1239 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1239, __extension__ __PRETTY_FUNCTION__))
;
1240 int64_t Imm = getConstantImm() - Offset;
1241 Imm = SignExtend64<Bits>(Imm);
1242 Imm += Offset;
1243 Imm += AdjustOffset;
1244 Inst.addOperand(MCOperand::createImm(Imm));
1245 }
1246
1247 void addImmOperands(MCInst &Inst, unsigned N) const {
1248 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1248, __extension__ __PRETTY_FUNCTION__))
;
1249 const MCExpr *Expr = getImm();
1250 addExpr(Inst, Expr);
1251 }
1252
1253 void addMemOperands(MCInst &Inst, unsigned N) const {
1254 assert(N == 2 && "Invalid number of operands!")(static_cast <bool> (N == 2 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 2 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1254, __extension__ __PRETTY_FUNCTION__))
;
1255
1256 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
1257 ? getMemBase()->getGPR64Reg()
1258 : getMemBase()->getGPR32Reg()));
1259
1260 const MCExpr *Expr = getMemOff();
1261 addExpr(Inst, Expr);
1262 }
1263
1264 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
1265 assert(N == 2 && "Invalid number of operands!")(static_cast <bool> (N == 2 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 2 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1265, __extension__ __PRETTY_FUNCTION__))
;
1266
1267 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
1268
1269 const MCExpr *Expr = getMemOff();
1270 addExpr(Inst, Expr);
1271 }
1272
1273 void addRegListOperands(MCInst &Inst, unsigned N) const {
1274 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1274, __extension__ __PRETTY_FUNCTION__))
;
1275
1276 for (auto RegNo : getRegList())
1277 Inst.addOperand(MCOperand::createReg(RegNo));
1278 }
1279
1280 bool isReg() const override {
1281 // As a special case until we sort out the definition of div/divu, accept
1282 // $0/$zero here so that MCK_ZERO works correctly.
1283 return isGPRAsmReg() && RegIdx.Index == 0;
1284 }
1285
1286 bool isRegIdx() const { return Kind == k_RegisterIndex; }
1287 bool isImm() const override { return Kind == k_Immediate; }
1288
1289 bool isConstantImm() const {
1290 int64_t Res;
1291 return isImm() && getImm()->evaluateAsAbsolute(Res);
1292 }
1293
1294 bool isConstantImmz() const {
1295 return isConstantImm() && getConstantImm() == 0;
1296 }
1297
1298 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1299 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1300 }
1301
1302 template <unsigned Bits> bool isSImm() const {
1303 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1304 }
1305
1306 template <unsigned Bits> bool isUImm() const {
1307 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1308 }
1309
1310 template <unsigned Bits> bool isAnyImm() const {
1311 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1312 isUInt<Bits>(getConstantImm()))
1313 : isImm();
1314 }
1315
1316 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1317 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
1318 }
1319
1320 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1321 return isConstantImm() && getConstantImm() >= Bottom &&
1322 getConstantImm() <= Top;
1323 }
1324
1325 bool isToken() const override {
1326 // Note: It's not possible to pretend that other operand kinds are tokens.
1327 // The matcher emitter checks tokens first.
1328 return Kind == k_Token;
1329 }
1330
1331 bool isMem() const override { return Kind == k_Memory; }
1332
1333 bool isConstantMemOff() const {
1334 return isMem() && isa<MCConstantExpr>(getMemOff());
1335 }
1336
1337 // Allow relocation operators.
1338 template <unsigned Bits, unsigned ShiftAmount = 0>
1339 bool isMemWithSimmOffset() const {
1340 if (!isMem())
1341 return false;
1342 if (!getMemBase()->isGPRAsmReg())
1343 return false;
1344 if (isa<MCTargetExpr>(getMemOff()) ||
1345 (isConstantMemOff() &&
1346 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
1347 return true;
1348 MCValue Res;
1349 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1350 return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
1351 }
1352
1353 bool isMemWithPtrSizeOffset() const {
1354 if (!isMem())
1355 return false;
1356 if (!getMemBase()->isGPRAsmReg())
1357 return false;
1358 const unsigned PtrBits = AsmParser.getABI().ArePtrs64bit() ? 64 : 32;
1359 if (isa<MCTargetExpr>(getMemOff()) ||
1360 (isConstantMemOff() && isIntN(PtrBits, getConstantMemOff())))
1361 return true;
1362 MCValue Res;
1363 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1364 return IsReloc && isIntN(PtrBits, Res.getConstant());
1365 }
1366
1367 bool isMemWithGRPMM16Base() const {
1368 return isMem() && getMemBase()->isMM16AsmReg();
1369 }
1370
1371 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1372 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1373 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1374 }
1375
1376 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1377 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1378 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1379 && (getMemBase()->getGPR32Reg() == Mips::SP);
1380 }
1381
1382 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
1383 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1384 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1385 && (getMemBase()->getGPR32Reg() == Mips::GP);
1386 }
1387
1388 template <unsigned Bits, unsigned ShiftLeftAmount>
1389 bool isScaledUImm() const {
1390 return isConstantImm() &&
1391 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
1392 }
1393
1394 template <unsigned Bits, unsigned ShiftLeftAmount>
1395 bool isScaledSImm() const {
1396 if (isConstantImm() &&
1397 isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
1398 return true;
1399 // Operand can also be a symbol or symbol plus
1400 // offset in case of relocations.
1401 if (Kind != k_Immediate)
1402 return false;
1403 MCValue Res;
1404 bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr);
1405 return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
1406 }
1407
1408 bool isRegList16() const {
1409 if (!isRegList())
1410 return false;
1411
1412 int Size = RegList.List->size();
1413 if (Size < 2 || Size > 5)
1414 return false;
1415
1416 unsigned R0 = RegList.List->front();
1417 unsigned R1 = RegList.List->back();
1418 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1419 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
1420 return false;
1421
1422 int PrevReg = *RegList.List->begin();
1423 for (int i = 1; i < Size - 1; i++) {
1424 int Reg = (*(RegList.List))[i];
1425 if ( Reg != PrevReg + 1)
1426 return false;
1427 PrevReg = Reg;
1428 }
1429
1430 return true;
1431 }
1432
1433 bool isInvNum() const { return Kind == k_Immediate; }
1434
1435 bool isLSAImm() const {
1436 if (!isConstantImm())
1437 return false;
1438 int64_t Val = getConstantImm();
1439 return 1 <= Val && Val <= 4;
1440 }
1441
1442 bool isRegList() const { return Kind == k_RegList; }
1443
1444 StringRef getToken() const {
1445 assert(Kind == k_Token && "Invalid access!")(static_cast <bool> (Kind == k_Token && "Invalid access!"
) ? void (0) : __assert_fail ("Kind == k_Token && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1445, __extension__ __PRETTY_FUNCTION__))
;
1446 return StringRef(Tok.Data, Tok.Length);
1447 }
1448
1449 unsigned getReg() const override {
1450 // As a special case until we sort out the definition of div/divu, accept
1451 // $0/$zero here so that MCK_ZERO works correctly.
1452 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1453 RegIdx.Kind & RegKind_GPR)
1454 return getGPR32Reg(); // FIXME: GPR64 too
1455
1456 llvm_unreachable("Invalid access!")::llvm::llvm_unreachable_internal("Invalid access!", "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1456)
;
1457 return 0;
1458 }
1459
1460 const MCExpr *getImm() const {
1461 assert((Kind == k_Immediate) && "Invalid access!")(static_cast <bool> ((Kind == k_Immediate) && "Invalid access!"
) ? void (0) : __assert_fail ("(Kind == k_Immediate) && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1461, __extension__ __PRETTY_FUNCTION__))
;
1462 return Imm.Val;
1463 }
1464
1465 int64_t getConstantImm() const {
1466 const MCExpr *Val = getImm();
1467 int64_t Value = 0;
1468 (void)Val->evaluateAsAbsolute(Value);
1469 return Value;
1470 }
1471
1472 MipsOperand *getMemBase() const {
1473 assert((Kind == k_Memory) && "Invalid access!")(static_cast <bool> ((Kind == k_Memory) && "Invalid access!"
) ? void (0) : __assert_fail ("(Kind == k_Memory) && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1473, __extension__ __PRETTY_FUNCTION__))
;
1474 return Mem.Base;
1475 }
1476
1477 const MCExpr *getMemOff() const {
1478 assert((Kind == k_Memory) && "Invalid access!")(static_cast <bool> ((Kind == k_Memory) && "Invalid access!"
) ? void (0) : __assert_fail ("(Kind == k_Memory) && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1478, __extension__ __PRETTY_FUNCTION__))
;
1479 return Mem.Off;
1480 }
1481
1482 int64_t getConstantMemOff() const {
1483 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1484 }
1485
1486 const SmallVectorImpl<unsigned> &getRegList() const {
1487 assert((Kind == k_RegList) && "Invalid access!")(static_cast <bool> ((Kind == k_RegList) && "Invalid access!"
) ? void (0) : __assert_fail ("(Kind == k_RegList) && \"Invalid access!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1487, __extension__ __PRETTY_FUNCTION__))
;
1488 return *(RegList.List);
1489 }
1490
1491 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1492 MipsAsmParser &Parser) {
1493 auto Op = std::make_unique<MipsOperand>(k_Token, Parser);
1494 Op->Tok.Data = Str.data();
1495 Op->Tok.Length = Str.size();
1496 Op->StartLoc = S;
1497 Op->EndLoc = S;
1498 return Op;
1499 }
1500
1501 /// Create a numeric register (e.g. $1). The exact register remains
1502 /// unresolved until an instruction successfully matches
1503 static std::unique_ptr<MipsOperand>
1504 createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1505 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1506 LLVM_DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("mips-asm-parser")) { dbgs() << "createNumericReg(" <<
Index << ", ...)\n"; } } while (false)
;
1507 return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);
1508 }
1509
1510 /// Create a register that is definitely a GPR.
1511 /// This is typically only used for named registers such as $gp.
1512 static std::unique_ptr<MipsOperand>
1513 createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1514 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1515 return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser);
1516 }
1517
1518 /// Create a register that is definitely a FGR.
1519 /// This is typically only used for named registers such as $f0.
1520 static std::unique_ptr<MipsOperand>
1521 createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1522 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1523 return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser);
1524 }
1525
1526 /// Create a register that is definitely a HWReg.
1527 /// This is typically only used for named registers such as $hwr_cpunum.
1528 static std::unique_ptr<MipsOperand>
1529 createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1530 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1531 return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, Parser);
1532 }
1533
1534 /// Create a register that is definitely an FCC.
1535 /// This is typically only used for named registers such as $fcc0.
1536 static std::unique_ptr<MipsOperand>
1537 createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1538 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1539 return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser);
1540 }
1541
1542 /// Create a register that is definitely an ACC.
1543 /// This is typically only used for named registers such as $ac0.
1544 static std::unique_ptr<MipsOperand>
1545 createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1546 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1547 return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser);
1548 }
1549
1550 /// Create a register that is definitely an MSA128.
1551 /// This is typically only used for named registers such as $w0.
1552 static std::unique_ptr<MipsOperand>
1553 createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1554 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1555 return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser);
1556 }
1557
1558 /// Create a register that is definitely an MSACtrl.
1559 /// This is typically only used for named registers such as $msaaccess.
1560 static std::unique_ptr<MipsOperand>
1561 createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1562 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1563 return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser);
1564 }
1565
1566 static std::unique_ptr<MipsOperand>
1567 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1568 auto Op = std::make_unique<MipsOperand>(k_Immediate, Parser);
1569 Op->Imm.Val = Val;
1570 Op->StartLoc = S;
1571 Op->EndLoc = E;
1572 return Op;
1573 }
1574
1575 static std::unique_ptr<MipsOperand>
1576 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1577 SMLoc E, MipsAsmParser &Parser) {
1578 auto Op = std::make_unique<MipsOperand>(k_Memory, Parser);
1579 Op->Mem.Base = Base.release();
1580 Op->Mem.Off = Off;
1581 Op->StartLoc = S;
1582 Op->EndLoc = E;
1583 return Op;
1584 }
1585
1586 static std::unique_ptr<MipsOperand>
1587 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1588 MipsAsmParser &Parser) {
1589 assert(Regs.size() > 0 && "Empty list not allowed")(static_cast <bool> (Regs.size() > 0 && "Empty list not allowed"
) ? void (0) : __assert_fail ("Regs.size() > 0 && \"Empty list not allowed\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1589, __extension__ __PRETTY_FUNCTION__))
;
1590
1591 auto Op = std::make_unique<MipsOperand>(k_RegList, Parser);
1592 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
1593 Op->StartLoc = StartLoc;
1594 Op->EndLoc = EndLoc;
1595 return Op;
1596 }
1597
1598 bool isGPRZeroAsmReg() const {
1599 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index == 0;
1600 }
1601
1602 bool isGPRNonZeroAsmReg() const {
1603 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index > 0 &&
1604 RegIdx.Index <= 31;
1605 }
1606
1607 bool isGPRAsmReg() const {
1608 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
1609 }
1610
1611 bool isMM16AsmReg() const {
1612 if (!(isRegIdx() && RegIdx.Kind))
1613 return false;
1614 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1615 || RegIdx.Index == 16 || RegIdx.Index == 17);
1616
1617 }
1618 bool isMM16AsmRegZero() const {
1619 if (!(isRegIdx() && RegIdx.Kind))
1620 return false;
1621 return (RegIdx.Index == 0 ||
1622 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1623 RegIdx.Index == 17);
1624 }
1625
1626 bool isMM16AsmRegMoveP() const {
1627 if (!(isRegIdx() && RegIdx.Kind))
1628 return false;
1629 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1630 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1631 }
1632
1633 bool isMM16AsmRegMovePPairFirst() const {
1634 if (!(isRegIdx() && RegIdx.Kind))
1635 return false;
1636 return RegIdx.Index >= 4 && RegIdx.Index <= 6;
1637 }
1638
1639 bool isMM16AsmRegMovePPairSecond() const {
1640 if (!(isRegIdx() && RegIdx.Kind))
1641 return false;
1642 return (RegIdx.Index == 21 || RegIdx.Index == 22 ||
1643 (RegIdx.Index >= 5 && RegIdx.Index <= 7));
1644 }
1645
1646 bool isFGRAsmReg() const {
1647 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1648 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
1649 }
1650
1651 bool isStrictlyFGRAsmReg() const {
1652 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1653 return isRegIdx() && RegIdx.Kind == RegKind_FGR && RegIdx.Index <= 31;
1654 }
1655
1656 bool isHWRegsAsmReg() const {
1657 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
1658 }
1659
1660 bool isCCRAsmReg() const {
1661 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
1662 }
1663
1664 bool isFCCAsmReg() const {
1665 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1666 return false;
1667 return RegIdx.Index <= 7;
1668 }
1669
1670 bool isACCAsmReg() const {
1671 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
1672 }
1673
1674 bool isCOP0AsmReg() const {
1675 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1676 }
1677
1678 bool isCOP2AsmReg() const {
1679 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
1680 }
1681
1682 bool isCOP3AsmReg() const {
1683 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1684 }
1685
1686 bool isMSA128AsmReg() const {
1687 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
1688 }
1689
1690 bool isMSACtrlAsmReg() const {
1691 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
1692 }
1693
1694 /// getStartLoc - Get the location of the first token of this operand.
1695 SMLoc getStartLoc() const override { return StartLoc; }
1696 /// getEndLoc - Get the location of the last token of this operand.
1697 SMLoc getEndLoc() const override { return EndLoc; }
1698
1699 void print(raw_ostream &OS) const override {
1700 switch (Kind) {
1701 case k_Immediate:
1702 OS << "Imm<";
1703 OS << *Imm.Val;
1704 OS << ">";
1705 break;
1706 case k_Memory:
1707 OS << "Mem<";
1708 Mem.Base->print(OS);
1709 OS << ", ";
1710 OS << *Mem.Off;
1711 OS << ">";
1712 break;
1713 case k_RegisterIndex:
1714 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "
1715 << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";
1716 break;
1717 case k_Token:
1718 OS << getToken();
1719 break;
1720 case k_RegList:
1721 OS << "RegList< ";
1722 for (auto Reg : (*RegList.List))
1723 OS << Reg << " ";
1724 OS << ">";
1725 break;
1726 }
1727 }
1728
1729 bool isValidForTie(const MipsOperand &Other) const {
1730 if (Kind != Other.Kind)
1731 return false;
1732
1733 switch (Kind) {
1734 default:
1735 llvm_unreachable("Unexpected kind")::llvm::llvm_unreachable_internal("Unexpected kind", "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1735)
;
1736 return false;
1737 case k_RegisterIndex: {
1738 StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);
1739 StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);
1740 return Token == OtherToken;
1741 }
1742 }
1743 }
1744}; // class MipsOperand
1745
1746} // end anonymous namespace
1747
1748namespace llvm {
1749
1750extern const MCInstrDesc MipsInsts[];
1751
1752} // end namespace llvm
1753
1754static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1755 return MipsInsts[Opcode];
1756}
1757
1758static bool hasShortDelaySlot(MCInst &Inst) {
1759 switch (Inst.getOpcode()) {
1760 case Mips::BEQ_MM:
1761 case Mips::BNE_MM:
1762 case Mips::BLTZ_MM:
1763 case Mips::BGEZ_MM:
1764 case Mips::BLEZ_MM:
1765 case Mips::BGTZ_MM:
1766 case Mips::JRC16_MM:
1767 case Mips::JALS_MM:
1768 case Mips::JALRS_MM:
1769 case Mips::JALRS16_MM:
1770 case Mips::BGEZALS_MM:
1771 case Mips::BLTZALS_MM:
1772 return true;
1773 case Mips::J_MM:
1774 return !Inst.getOperand(0).isReg();
1775 default:
1776 return false;
1777 }
1778}
1779
1780static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1781 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1782 return &SRExpr->getSymbol();
1783 }
1784
1785 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1786 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1787 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1788
1789 if (LHSSym)
1790 return LHSSym;
1791
1792 if (RHSSym)
1793 return RHSSym;
1794
1795 return nullptr;
1796 }
1797
1798 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1799 return getSingleMCSymbol(UExpr->getSubExpr());
1800
1801 return nullptr;
1802}
1803
1804static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1805 if (isa<MCSymbolRefExpr>(Expr))
1806 return 1;
1807
1808 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1809 return countMCSymbolRefExpr(BExpr->getLHS()) +
1810 countMCSymbolRefExpr(BExpr->getRHS());
1811
1812 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1813 return countMCSymbolRefExpr(UExpr->getSubExpr());
1814
1815 return 0;
1816}
1817
1818static bool isEvaluated(const MCExpr *Expr) {
1819 switch (Expr->getKind()) {
1820 case MCExpr::Constant:
1821 return true;
1822 case MCExpr::SymbolRef:
1823 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1824 case MCExpr::Binary: {
1825 const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
1826 if (!isEvaluated(BE->getLHS()))
1827 return false;
1828 return isEvaluated(BE->getRHS());
1829 }
1830 case MCExpr::Unary:
1831 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
1832 case MCExpr::Target:
1833 return true;
1834 }
1835 return false;
1836}
1837
1838static bool needsExpandMemInst(MCInst &Inst) {
1839 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
1840
1841 unsigned NumOp = MCID.getNumOperands();
1842 if (NumOp != 3 && NumOp != 4)
1843 return false;
1844
1845 const MCOperandInfo &OpInfo = MCID.OpInfo[NumOp - 1];
1846 if (OpInfo.OperandType != MCOI::OPERAND_MEMORY &&
1847 OpInfo.OperandType != MCOI::OPERAND_UNKNOWN &&
1848 OpInfo.OperandType != MipsII::OPERAND_MEM_SIMM9)
1849 return false;
1850
1851 MCOperand &Op = Inst.getOperand(NumOp - 1);
1852 if (Op.isImm()) {
1853 if (OpInfo.OperandType == MipsII::OPERAND_MEM_SIMM9)
1854 return !isInt<9>(Op.getImm());
1855 // Offset can't exceed 16bit value.
1856 return !isInt<16>(Op.getImm());
1857 }
1858
1859 if (Op.isExpr()) {
1860 const MCExpr *Expr = Op.getExpr();
1861 if (Expr->getKind() != MCExpr::SymbolRef)
1862 return !isEvaluated(Expr);
1863
1864 // Expand symbol.
1865 const MCSymbolRefExpr *SR = static_cast<const MCSymbolRefExpr *>(Expr);
1866 return SR->getKind() == MCSymbolRefExpr::VK_None;
1867 }
1868
1869 return false;
1870}
1871
1872bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
1873 MCStreamer &Out,
1874 const MCSubtargetInfo *STI) {
1875 MipsTargetStreamer &TOut = getTargetStreamer();
1876 const unsigned Opcode = Inst.getOpcode();
1877 const MCInstrDesc &MCID = getInstDesc(Opcode);
1878 bool ExpandedJalSym = false;
1879
1880 Inst.setLoc(IDLoc);
1881
1882 if (MCID.isBranch() || MCID.isCall()) {
1883 MCOperand Offset;
1884
1885 switch (Opcode) {
1886 default:
1887 break;
1888 case Mips::BBIT0:
1889 case Mips::BBIT032:
1890 case Mips::BBIT1:
1891 case Mips::BBIT132:
1892 assert(hasCnMips() && "instruction only valid for octeon cpus")(static_cast <bool> (hasCnMips() && "instruction only valid for octeon cpus"
) ? void (0) : __assert_fail ("hasCnMips() && \"instruction only valid for octeon cpus\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1892, __extension__ __PRETTY_FUNCTION__))
;
1893 LLVM_FALLTHROUGH[[gnu::fallthrough]];
1894
1895 case Mips::BEQ:
1896 case Mips::BNE:
1897 case Mips::BEQ_MM:
1898 case Mips::BNE_MM:
1899 assert(MCID.getNumOperands() == 3 && "unexpected number of operands")(static_cast <bool> (MCID.getNumOperands() == 3 &&
"unexpected number of operands") ? void (0) : __assert_fail (
"MCID.getNumOperands() == 3 && \"unexpected number of operands\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1899, __extension__ __PRETTY_FUNCTION__))
;
1900 Offset = Inst.getOperand(2);
1901 if (!Offset.isImm())
1902 break; // We'll deal with this situation later on when applying fixups.
1903 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
1904 return Error(IDLoc, "branch target out of range");
1905 if (offsetToAlignment(Offset.getImm(),
1906 (inMicroMipsMode() ? Align(2) : Align(4))))
1907 return Error(IDLoc, "branch to misaligned address");
1908 break;
1909 case Mips::BGEZ:
1910 case Mips::BGTZ:
1911 case Mips::BLEZ:
1912 case Mips::BLTZ:
1913 case Mips::BGEZAL:
1914 case Mips::BLTZAL:
1915 case Mips::BC1F:
1916 case Mips::BC1T:
1917 case Mips::BGEZ_MM:
1918 case Mips::BGTZ_MM:
1919 case Mips::BLEZ_MM:
1920 case Mips::BLTZ_MM:
1921 case Mips::BGEZAL_MM:
1922 case Mips::BLTZAL_MM:
1923 case Mips::BC1F_MM:
1924 case Mips::BC1T_MM:
1925 case Mips::BC1EQZC_MMR6:
1926 case Mips::BC1NEZC_MMR6:
1927 case Mips::BC2EQZC_MMR6:
1928 case Mips::BC2NEZC_MMR6:
1929 assert(MCID.getNumOperands() == 2 && "unexpected number of operands")(static_cast <bool> (MCID.getNumOperands() == 2 &&
"unexpected number of operands") ? void (0) : __assert_fail (
"MCID.getNumOperands() == 2 && \"unexpected number of operands\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1929, __extension__ __PRETTY_FUNCTION__))
;
1930 Offset = Inst.getOperand(1);
1931 if (!Offset.isImm())
1932 break; // We'll deal with this situation later on when applying fixups.
1933 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
1934 return Error(IDLoc, "branch target out of range");
1935 if (offsetToAlignment(Offset.getImm(),
1936 (inMicroMipsMode() ? Align(2) : Align(4))))
1937 return Error(IDLoc, "branch to misaligned address");
1938 break;
1939 case Mips::BGEC: case Mips::BGEC_MMR6:
1940 case Mips::BLTC: case Mips::BLTC_MMR6:
1941 case Mips::BGEUC: case Mips::BGEUC_MMR6:
1942 case Mips::BLTUC: case Mips::BLTUC_MMR6:
1943 case Mips::BEQC: case Mips::BEQC_MMR6:
1944 case Mips::BNEC: case Mips::BNEC_MMR6:
1945 assert(MCID.getNumOperands() == 3 && "unexpected number of operands")(static_cast <bool> (MCID.getNumOperands() == 3 &&
"unexpected number of operands") ? void (0) : __assert_fail (
"MCID.getNumOperands() == 3 && \"unexpected number of operands\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1945, __extension__ __PRETTY_FUNCTION__))
;
1946 Offset = Inst.getOperand(2);
1947 if (!Offset.isImm())
1948 break; // We'll deal with this situation later on when applying fixups.
1949 if (!isIntN(18, Offset.getImm()))
1950 return Error(IDLoc, "branch target out of range");
1951 if (offsetToAlignment(Offset.getImm(), Align(4)))
1952 return Error(IDLoc, "branch to misaligned address");
1953 break;
1954 case Mips::BLEZC: case Mips::BLEZC_MMR6:
1955 case Mips::BGEZC: case Mips::BGEZC_MMR6:
1956 case Mips::BGTZC: case Mips::BGTZC_MMR6:
1957 case Mips::BLTZC: case Mips::BLTZC_MMR6:
1958 assert(MCID.getNumOperands() == 2 && "unexpected number of operands")(static_cast <bool> (MCID.getNumOperands() == 2 &&
"unexpected number of operands") ? void (0) : __assert_fail (
"MCID.getNumOperands() == 2 && \"unexpected number of operands\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1958, __extension__ __PRETTY_FUNCTION__))
;
1959 Offset = Inst.getOperand(1);
1960 if (!Offset.isImm())
1961 break; // We'll deal with this situation later on when applying fixups.
1962 if (!isIntN(18, Offset.getImm()))
1963 return Error(IDLoc, "branch target out of range");
1964 if (offsetToAlignment(Offset.getImm(), Align(4)))
1965 return Error(IDLoc, "branch to misaligned address");
1966 break;
1967 case Mips::BEQZC: case Mips::BEQZC_MMR6:
1968 case Mips::BNEZC: case Mips::BNEZC_MMR6:
1969 assert(MCID.getNumOperands() == 2 && "unexpected number of operands")(static_cast <bool> (MCID.getNumOperands() == 2 &&
"unexpected number of operands") ? void (0) : __assert_fail (
"MCID.getNumOperands() == 2 && \"unexpected number of operands\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1969, __extension__ __PRETTY_FUNCTION__))
;
1970 Offset = Inst.getOperand(1);
1971 if (!Offset.isImm())
1972 break; // We'll deal with this situation later on when applying fixups.
1973 if (!isIntN(23, Offset.getImm()))
1974 return Error(IDLoc, "branch target out of range");
1975 if (offsetToAlignment(Offset.getImm(), Align(4)))
1976 return Error(IDLoc, "branch to misaligned address");
1977 break;
1978 case Mips::BEQZ16_MM:
1979 case Mips::BEQZC16_MMR6:
1980 case Mips::BNEZ16_MM:
1981 case Mips::BNEZC16_MMR6:
1982 assert(MCID.getNumOperands() == 2 && "unexpected number of operands")(static_cast <bool> (MCID.getNumOperands() == 2 &&
"unexpected number of operands") ? void (0) : __assert_fail (
"MCID.getNumOperands() == 2 && \"unexpected number of operands\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 1982, __extension__ __PRETTY_FUNCTION__))
;
1983 Offset = Inst.getOperand(1);
1984 if (!Offset.isImm())
1985 break; // We'll deal with this situation later on when applying fixups.
1986 if (!isInt<8>(Offset.getImm()))
1987 return Error(IDLoc, "branch target out of range");
1988 if (offsetToAlignment(Offset.getImm(), Align(2)))
1989 return Error(IDLoc, "branch to misaligned address");
1990 break;
1991 }
1992 }
1993
1994 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1995 // We still accept it but it is a normal nop.
1996 if (hasMips32r6() && Opcode == Mips::SSNOP) {
1997 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1998 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1999 "nop instruction");
2000 }
2001
2002 if (hasCnMips()) {
2003 MCOperand Opnd;
2004 int Imm;
2005
2006 switch (Opcode) {
2007 default:
2008 break;
2009
2010 case Mips::BBIT0:
2011 case Mips::BBIT032:
2012 case Mips::BBIT1:
2013 case Mips::BBIT132:
2014 assert(MCID.getNumOperands() == 3 && "unexpected number of operands")(static_cast <bool> (MCID.getNumOperands() == 3 &&
"unexpected number of operands") ? void (0) : __assert_fail (
"MCID.getNumOperands() == 3 && \"unexpected number of operands\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 2014, __extension__ __PRETTY_FUNCTION__))
;
2015 // The offset is handled above
2016 Opnd = Inst.getOperand(1);
2017 if (!Opnd.isImm())
2018 return Error(IDLoc, "expected immediate operand kind");
2019 Imm = Opnd.getImm();
2020 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
2021 Opcode == Mips::BBIT1 ? 63 : 31))
2022 return Error(IDLoc, "immediate operand value out of range");
2023 if (Imm > 31) {
2024 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
2025 : Mips::BBIT132);
2026 Inst.getOperand(1).setImm(Imm - 32);
2027 }
2028 break;
2029
2030 case Mips::SEQi:
2031 case Mips::SNEi:
2032 assert(MCID.getNumOperands() == 3 && "unexpected number of operands")(static_cast <bool> (MCID.getNumOperands() == 3 &&
"unexpected number of operands") ? void (0) : __assert_fail (
"MCID.getNumOperands() == 3 && \"unexpected number of operands\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 2032, __extension__ __PRETTY_FUNCTION__))
;
2033 Opnd = Inst.getOperand(2);
2034 if (!Opnd.isImm())
2035 return Error(IDLoc, "expected immediate operand kind");
2036 Imm = Opnd.getImm();
2037 if (!isInt<10>(Imm))
2038 return Error(IDLoc, "immediate operand value out of range");
2039 break;
2040 }
2041 }
2042
2043 // Warn on division by zero. We're checking here as all instructions get
2044 // processed here, not just the macros that need expansion.
2045 //
2046 // The MIPS backend models most of the divison instructions and macros as
2047 // three operand instructions. The pre-R6 divide instructions however have
2048 // two operands and explicitly define HI/LO as part of the instruction,
2049 // not in the operands.
2050 unsigned FirstOp = 1;
2051 unsigned SecondOp = 2;
2052 switch (Opcode) {
2053 default:
2054 break;
2055 case Mips::SDivIMacro:
2056 case Mips::UDivIMacro:
2057 case Mips::DSDivIMacro:
2058 case Mips::DUDivIMacro:
2059 if (Inst.getOperand(2).getImm() == 0) {
2060 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
2061 Inst.getOperand(1).getReg() == Mips::ZERO_64)
2062 Warning(IDLoc, "dividing zero by zero");
2063 else
2064 Warning(IDLoc, "division by zero");
2065 }
2066 break;
2067 case Mips::DSDIV:
2068 case Mips::SDIV:
2069 case Mips::UDIV:
2070 case Mips::DUDIV:
2071 case Mips::UDIV_MM:
2072 case Mips::SDIV_MM:
2073 FirstOp = 0;
2074 SecondOp = 1;
2075 LLVM_FALLTHROUGH[[gnu::fallthrough]];
2076 case Mips::SDivMacro:
2077 case Mips::DSDivMacro:
2078 case Mips::UDivMacro:
2079 case Mips::DUDivMacro:
2080 case Mips::DIV:
2081 case Mips::DIVU:
2082 case Mips::DDIV:
2083 case Mips::DDIVU:
2084 case Mips::DIVU_MMR6:
2085 case Mips::DIV_MMR6:
2086 if (Inst.getOperand(SecondOp).getReg() == Mips::ZERO ||
2087 Inst.getOperand(SecondOp).getReg() == Mips::ZERO_64) {
2088 if (Inst.getOperand(FirstOp).getReg() == Mips::ZERO ||
2089 Inst.getOperand(FirstOp).getReg() == Mips::ZERO_64)
2090 Warning(IDLoc, "dividing zero by zero");
2091 else
2092 Warning(IDLoc, "division by zero");
2093 }
2094 break;
2095 }
2096
2097 // For PIC code convert unconditional jump to unconditional branch.
2098 if ((Opcode == Mips::J || Opcode == Mips::J_MM) && inPicMode()) {
2099 MCInst BInst;
2100 BInst.setOpcode(inMicroMipsMode() ? Mips::BEQ_MM : Mips::BEQ);
2101 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
2102 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
2103 BInst.addOperand(Inst.getOperand(0));
2104 Inst = BInst;
2105 }
2106
2107 // This expansion is not in a function called by tryExpandInstruction()
2108 // because the pseudo-instruction doesn't have a distinct opcode.
2109 if ((Opcode == Mips::JAL || Opcode == Mips::JAL_MM) && inPicMode()) {
2110 warnIfNoMacro(IDLoc);
2111
2112 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
2113
2114 // We can do this expansion if there's only 1 symbol in the argument
2115 // expression.
2116 if (countMCSymbolRefExpr(JalExpr) > 1)
2117 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
2118
2119 // FIXME: This is checking the expression can be handled by the later stages
2120 // of the assembler. We ought to leave it to those later stages.
2121 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
2122
2123 if (expandLoadAddress(Mips::T9, Mips::NoRegister, Inst.getOperand(0),
2124 !isGP64bit(), IDLoc, Out, STI))
2125 return true;
2126
2127 MCInst JalrInst;
2128 if (inMicroMipsMode())
2129 JalrInst.setOpcode(IsCpRestoreSet ? Mips::JALRS_MM : Mips::JALR_MM);
2130 else
2131 JalrInst.setOpcode(Mips::JALR);
2132 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
2133 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
2134
2135 if (isJalrRelocAvailable(JalExpr)) {
2136 // As an optimization hint for the linker, before the JALR we add:
2137 // .reloc tmplabel, R_{MICRO}MIPS_JALR, symbol
2138 // tmplabel:
2139 MCSymbol *TmpLabel = getContext().createTempSymbol();
2140 const MCExpr *TmpExpr = MCSymbolRefExpr::create(TmpLabel, getContext());
2141 const MCExpr *RelocJalrExpr =
2142 MCSymbolRefExpr::create(JalSym, MCSymbolRefExpr::VK_None,
2143 getContext(), IDLoc);
2144
2145 TOut.getStreamer().emitRelocDirective(
2146 *TmpExpr, inMicroMipsMode() ? "R_MICROMIPS_JALR" : "R_MIPS_JALR",
2147 RelocJalrExpr, IDLoc, *STI);
2148 TOut.getStreamer().emitLabel(TmpLabel);
2149 }
2150
2151 Inst = JalrInst;
2152 ExpandedJalSym = true;
2153 }
2154
2155 if (MCID.mayLoad() || MCID.mayStore()) {
2156 // Check the offset of memory operand, if it is a symbol
2157 // reference or immediate we may have to expand instructions.
2158 if (needsExpandMemInst(Inst)) {
2159 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2160 switch (MCID.OpInfo[MCID.getNumOperands() - 1].OperandType) {
2161 case MipsII::OPERAND_MEM_SIMM9:
2162 expandMem9Inst(Inst, IDLoc, Out, STI, MCID.mayLoad());
2163 break;
2164 default:
2165 expandMem16Inst(Inst, IDLoc, Out, STI, MCID.mayLoad());
2166 break;
2167 }
2168 return getParser().hasPendingError();
2169 }
2170 }
2171
2172 if (inMicroMipsMode()) {
2173 if (MCID.mayLoad() && Opcode != Mips::LWP_MM) {
2174 // Try to create 16-bit GP relative load instruction.
2175 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
2176 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
2177 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2178 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
2179 MCOperand &Op = Inst.getOperand(i);
2180 if (Op.isImm()) {
2181 int MemOffset = Op.getImm();
2182 MCOperand &DstReg = Inst.getOperand(0);
2183 MCOperand &BaseReg = Inst.getOperand(1);
2184 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
2185 getContext().getRegisterInfo()->getRegClass(
2186 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
2187 (BaseReg.getReg() == Mips::GP ||
2188 BaseReg.getReg() == Mips::GP_64)) {
2189
2190 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
2191 IDLoc, STI);
2192 return false;
2193 }
2194 }
2195 }
2196 } // for
2197 } // if load
2198
2199 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
2200
2201 MCOperand Opnd;
2202 int Imm;
2203
2204 switch (Opcode) {
2205 default:
2206 break;
2207 case Mips::ADDIUSP_MM:
2208 Opnd = Inst.getOperand(0);
2209 if (!Opnd.isImm())
2210 return Error(IDLoc, "expected immediate operand kind");
2211 Imm = Opnd.getImm();
2212 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
2213 Imm % 4 != 0)
2214 return Error(IDLoc, "immediate operand value out of range");
2215 break;
2216 case Mips::SLL16_MM:
2217 case Mips::SRL16_MM:
2218 Opnd = Inst.getOperand(2);
2219 if (!Opnd.isImm())
2220 return Error(IDLoc, "expected immediate operand kind");
2221 Imm = Opnd.getImm();
2222 if (Imm < 1 || Imm > 8)
2223 return Error(IDLoc, "immediate operand value out of range");
2224 break;
2225 case Mips::LI16_MM:
2226 Opnd = Inst.getOperand(1);
2227 if (!Opnd.isImm())
2228 return Error(IDLoc, "expected immediate operand kind");
2229 Imm = Opnd.getImm();
2230 if (Imm < -1 || Imm > 126)
2231 return Error(IDLoc, "immediate operand value out of range");
2232 break;
2233 case Mips::ADDIUR2_MM:
2234 Opnd = Inst.getOperand(2);
2235 if (!Opnd.isImm())
2236 return Error(IDLoc, "expected immediate operand kind");
2237 Imm = Opnd.getImm();
2238 if (!(Imm == 1 || Imm == -1 ||
2239 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
2240 return Error(IDLoc, "immediate operand value out of range");
2241 break;
2242 case Mips::ANDI16_MM:
2243 Opnd = Inst.getOperand(2);
2244 if (!Opnd.isImm())
2245 return Error(IDLoc, "expected immediate operand kind");
2246 Imm = Opnd.getImm();
2247 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
2248 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
2249 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
2250 return Error(IDLoc, "immediate operand value out of range");
2251 break;
2252 case Mips::LBU16_MM:
2253 Opnd = Inst.getOperand(2);
2254 if (!Opnd.isImm())
2255 return Error(IDLoc, "expected immediate operand kind");
2256 Imm = Opnd.getImm();
2257 if (Imm < -1 || Imm > 14)
2258 return Error(IDLoc, "immediate operand value out of range");
2259 break;
2260 case Mips::SB16_MM:
2261 case Mips::SB16_MMR6:
2262 Opnd = Inst.getOperand(2);
2263 if (!Opnd.isImm())
2264 return Error(IDLoc, "expected immediate operand kind");
2265 Imm = Opnd.getImm();
2266 if (Imm < 0 || Imm > 15)
2267 return Error(IDLoc, "immediate operand value out of range");
2268 break;
2269 case Mips::LHU16_MM:
2270 case Mips::SH16_MM:
2271 case Mips::SH16_MMR6:
2272 Opnd = Inst.getOperand(2);
2273 if (!Opnd.isImm())
2274 return Error(IDLoc, "expected immediate operand kind");
2275 Imm = Opnd.getImm();
2276 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
2277 return Error(IDLoc, "immediate operand value out of range");
2278 break;
2279 case Mips::LW16_MM:
2280 case Mips::SW16_MM:
2281 case Mips::SW16_MMR6:
2282 Opnd = Inst.getOperand(2);
2283 if (!Opnd.isImm())
2284 return Error(IDLoc, "expected immediate operand kind");
2285 Imm = Opnd.getImm();
2286 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
2287 return Error(IDLoc, "immediate operand value out of range");
2288 break;
2289 case Mips::ADDIUPC_MM:
2290 Opnd = Inst.getOperand(1);
2291 if (!Opnd.isImm())
2292 return Error(IDLoc, "expected immediate operand kind");
2293 Imm = Opnd.getImm();
2294 if ((Imm % 4 != 0) || !isInt<25>(Imm))
2295 return Error(IDLoc, "immediate operand value out of range");
2296 break;
2297 case Mips::LWP_MM:
2298 case Mips::SWP_MM:
2299 if (Inst.getOperand(0).getReg() == Mips::RA)
2300 return Error(IDLoc, "invalid operand for instruction");
2301 break;
2302 case Mips::MOVEP_MM:
2303 case Mips::MOVEP_MMR6: {
2304 unsigned R0 = Inst.getOperand(0).getReg();
2305 unsigned R1 = Inst.getOperand(1).getReg();
2306 bool RegPair = ((R0 == Mips::A1 && R1 == Mips::A2) ||
2307 (R0 == Mips::A1 && R1 == Mips::A3) ||
2308 (R0 == Mips::A2 && R1 == Mips::A3) ||
2309 (R0 == Mips::A0 && R1 == Mips::S5) ||
2310 (R0 == Mips::A0 && R1 == Mips::S6) ||
2311 (R0 == Mips::A0 && R1 == Mips::A1) ||
2312 (R0 == Mips::A0 && R1 == Mips::A2) ||
2313 (R0 == Mips::A0 && R1 == Mips::A3));
2314 if (!RegPair)
2315 return Error(IDLoc, "invalid operand for instruction");
2316 break;
2317 }
2318 }
2319 }
2320
2321 bool FillDelaySlot =
2322 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
2323 if (FillDelaySlot)
2324 TOut.emitDirectiveSetNoReorder();
2325
2326 MacroExpanderResultTy ExpandResult =
2327 tryExpandInstruction(Inst, IDLoc, Out, STI);
2328 switch (ExpandResult) {
2329 case MER_NotAMacro:
2330 Out.emitInstruction(Inst, *STI);
2331 break;
2332 case MER_Success:
2333 break;
2334 case MER_Fail:
2335 return true;
2336 }
2337
2338 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
2339 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
2340 if (inMicroMipsMode()) {
2341 TOut.setUsesMicroMips();
2342 TOut.updateABIInfo(*this);
2343 }
2344
2345 // If this instruction has a delay slot and .set reorder is active,
2346 // emit a NOP after it.
2347 if (FillDelaySlot) {
2348 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst), IDLoc, STI);
2349 TOut.emitDirectiveSetReorder();
2350 }
2351
2352 if ((Opcode == Mips::JalOneReg || Opcode == Mips::JalTwoReg ||
2353 ExpandedJalSym) &&
2354 isPicAndNotNxxAbi()) {
2355 if (IsCpRestoreSet) {
2356 // We need a NOP between the JALR and the LW:
2357 // If .set reorder has been used, we've already emitted a NOP.
2358 // If .set noreorder has been used, we need to emit a NOP at this point.
2359 if (!AssemblerOptions.back()->isReorder())
2360 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst), IDLoc,
2361 STI);
2362
2363 // Load the $gp from the stack.
2364 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
2365 } else
2366 Warning(IDLoc, "no .cprestore used in PIC mode");
2367 }
2368
2369 return false;
2370}
2371
2372MipsAsmParser::MacroExpanderResultTy
2373MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2374 const MCSubtargetInfo *STI) {
2375 switch (Inst.getOpcode()) {
2376 default:
2377 return MER_NotAMacro;
2378 case Mips::LoadImm32:
2379 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2380 case Mips::LoadImm64:
2381 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2382 case Mips::LoadAddrImm32:
2383 case Mips::LoadAddrImm64:
2384 assert(Inst.getOperand(0).isReg() && "expected register operand kind")(static_cast <bool> (Inst.getOperand(0).isReg() &&
"expected register operand kind") ? void (0) : __assert_fail
("Inst.getOperand(0).isReg() && \"expected register operand kind\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 2384, __extension__ __PRETTY_FUNCTION__))
;
2385 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&(static_cast <bool> ((Inst.getOperand(1).isImm() || Inst
.getOperand(1).isExpr()) && "expected immediate operand kind"
) ? void (0) : __assert_fail ("(Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) && \"expected immediate operand kind\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 2386, __extension__ __PRETTY_FUNCTION__))
2386 "expected immediate operand kind")(static_cast <bool> ((Inst.getOperand(1).isImm() || Inst
.getOperand(1).isExpr()) && "expected immediate operand kind"
) ? void (0) : __assert_fail ("(Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) && \"expected immediate operand kind\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 2386, __extension__ __PRETTY_FUNCTION__))
;
2387
2388 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
2389 Inst.getOperand(1),
2390 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
2391 Out, STI)
2392 ? MER_Fail
2393 : MER_Success;
2394 case Mips::LoadAddrReg32:
2395 case Mips::LoadAddrReg64:
2396 assert(Inst.getOperand(0).isReg() && "expected register operand kind")(static_cast <bool> (Inst.getOperand(0).isReg() &&
"expected register operand kind") ? void (0) : __assert_fail
("Inst.getOperand(0).isReg() && \"expected register operand kind\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 2396, __extension__ __PRETTY_FUNCTION__))
;
2397 assert(Inst.getOperand(1).isReg() && "expected register operand kind")(static_cast <bool> (Inst.getOperand(1).isReg() &&
"expected register operand kind") ? void (0) : __assert_fail
("Inst.getOperand(1).isReg() && \"expected register operand kind\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 2397, __extension__ __PRETTY_FUNCTION__))
;
2398 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&(static_cast <bool> ((Inst.getOperand(2).isImm() || Inst
.getOperand(2).isExpr()) && "expected immediate operand kind"
) ? void (0) : __assert_fail ("(Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) && \"expected immediate operand kind\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 2399, __extension__ __PRETTY_FUNCTION__))
2399 "expected immediate operand kind")(static_cast <bool> ((Inst.getOperand(2).isImm() || Inst
.getOperand(2).isExpr()) && "expected immediate operand kind"
) ? void (0) : __assert_fail ("(Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) && \"expected immediate operand kind\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 2399, __extension__ __PRETTY_FUNCTION__))
;
2400
2401 return expandLoadAddress(Inst.getOperand(0).getReg(),
2402 Inst.getOperand(1).getReg(), Inst.getOperand(2),
2403 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
2404 Out, STI)
2405 ? MER_Fail
2406 : MER_Success;
2407 case Mips::B_MM_Pseudo:
2408 case Mips::B_MMR6_Pseudo:
2409 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
2410 : MER_Success;
2411 case Mips::SWM_MM:
2412 case Mips::LWM_MM:
2413 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
2414 : MER_Success;
2415 case Mips::JalOneReg:
2416 case Mips::JalTwoReg:
2417 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2418 case Mips::BneImm:
2419 case Mips::BeqImm:
2420 case Mips::BEQLImmMacro:
2421 case Mips::BNELImmMacro:
2422 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2423 case Mips::BLT:
2424 case Mips::BLE:
2425 case Mips::BGE:
2426 case Mips::BGT:
2427 case Mips::BLTU:
2428 case Mips::BLEU:
2429 case Mips::BGEU:
2430 case Mips::BGTU:
2431 case Mips::BLTL:
2432 case Mips::BLEL:
2433 case Mips::BGEL:
2434 case Mips::BGTL:
2435 case Mips::BLTUL:
2436 case Mips::BLEUL:
2437 case Mips::BGEUL:
2438 case Mips::BGTUL:
2439 case Mips::BLTImmMacro:
2440 case Mips::BLEImmMacro:
2441 case Mips::BGEImmMacro:
2442 case Mips::BGTImmMacro:
2443 case Mips::BLTUImmMacro:
2444 case Mips::BLEUImmMacro:
2445 case Mips::BGEUImmMacro:
2446 case Mips::BGTUImmMacro:
2447 case Mips::BLTLImmMacro:
2448 case Mips::BLELImmMacro:
2449 case Mips::BGELImmMacro:
2450 case Mips::BGTLImmMacro:
2451 case Mips::BLTULImmMacro:
2452 case Mips::BLEULImmMacro:
2453 case Mips::BGEULImmMacro:
2454 case Mips::BGTULImmMacro:
2455 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2456 case Mips::SDivMacro:
2457 case Mips::SDivIMacro:
2458 case Mips::SRemMacro:
2459 case Mips::SRemIMacro:
2460 return expandDivRem(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2461 : MER_Success;
2462 case Mips::DSDivMacro:
2463 case Mips::DSDivIMacro:
2464 case Mips::DSRemMacro:
2465 case Mips::DSRemIMacro:
2466 return expandDivRem(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2467 : MER_Success;
2468 case Mips::UDivMacro:
2469 case Mips::UDivIMacro:
2470 case Mips::URemMacro:
2471 case Mips::URemIMacro:
2472 return expandDivRem(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2473 : MER_Success;
2474 case Mips::DUDivMacro:
2475 case Mips::DUDivIMacro:
2476 case Mips::DURemMacro:
2477 case Mips::DURemIMacro:
2478 return expandDivRem(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2479 : MER_Success;
2480 case Mips::PseudoTRUNC_W_S:
2481 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2482 : MER_Success;
2483 case Mips::PseudoTRUNC_W_D32:
2484 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
2485 : MER_Success;
2486 case Mips::PseudoTRUNC_W_D:
2487 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2488 : MER_Success;
2489
2490 case Mips::LoadImmSingleGPR:
2491 return expandLoadSingleImmToGPR(Inst, IDLoc, Out, STI) ? MER_Fail
2492 : MER_Success;
2493 case Mips::LoadImmSingleFGR:
2494 return expandLoadSingleImmToFPR(Inst, IDLoc, Out, STI) ? MER_Fail
2495 : MER_Success;
2496 case Mips::LoadImmDoubleGPR:
2497 return expandLoadDoubleImmToGPR(Inst, IDLoc, Out, STI) ? MER_Fail
2498 : MER_Success;
2499 case Mips::LoadImmDoubleFGR:
2500 return expandLoadDoubleImmToFPR(Inst, true, IDLoc, Out, STI) ? MER_Fail
2501 : MER_Success;
2502 case Mips::LoadImmDoubleFGR_32:
2503 return expandLoadDoubleImmToFPR(Inst, false, IDLoc, Out, STI) ? MER_Fail
2504 : MER_Success;
2505
2506 case Mips::Ulh:
2507 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2508 case Mips::Ulhu:
2509 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2510 case Mips::Ush:
2511 return expandUsh(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2512 case Mips::Ulw:
2513 case Mips::Usw:
2514 return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2515 case Mips::NORImm:
2516 case Mips::NORImm64:
2517 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2518 case Mips::SGE:
2519 case Mips::SGEU:
2520 return expandSge(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2521 case Mips::SGEImm:
2522 case Mips::SGEUImm:
2523 case Mips::SGEImm64:
2524 case Mips::SGEUImm64:
2525 return expandSgeImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2526 case Mips::SGTImm:
2527 case Mips::SGTUImm:
2528 case Mips::SGTImm64:
2529 case Mips::SGTUImm64:
2530 return expandSgtImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2531 case Mips::SLE:
2532 case Mips::SLEU:
2533 return expandSle(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2534 case Mips::SLEImm:
2535 case Mips::SLEUImm:
2536 case Mips::SLEImm64:
2537 case Mips::SLEUImm64:
2538 return expandSleImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2539 case Mips::SLTImm64:
2540 if (isInt<16>(Inst.getOperand(2).getImm())) {
2541 Inst.setOpcode(Mips::SLTi64);
2542 return MER_NotAMacro;
2543 }
2544 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2545 case Mips::SLTUImm64:
2546 if (isInt<16>(Inst.getOperand(2).getImm())) {
2547 Inst.setOpcode(Mips::SLTiu64);
2548 return MER_NotAMacro;
2549 }
2550 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2551 case Mips::ADDi: case Mips::ADDi_MM:
2552 case Mips::ADDiu: case Mips::ADDiu_MM:
2553 case Mips::SLTi: case Mips::SLTi_MM:
2554 case Mips::SLTiu: case Mips::SLTiu_MM:
2555 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2556 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2557 int64_t ImmValue = Inst.getOperand(2).getImm();
2558 if (isInt<16>(ImmValue))
2559 return MER_NotAMacro;
2560 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2561 : MER_Success;
2562 }
2563 return MER_NotAMacro;
2564 case Mips::ANDi: case Mips::ANDi_MM: case Mips::ANDi64:
2565 case Mips::ORi: case Mips::ORi_MM: case Mips::ORi64:
2566 case Mips::XORi: case Mips::XORi_MM: case Mips::XORi64:
2567 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2568 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2569 int64_t ImmValue = Inst.getOperand(2).getImm();
2570 if (isUInt<16>(ImmValue))
2571 return MER_NotAMacro;
2572 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2573 : MER_Success;
2574 }
2575 return MER_NotAMacro;
2576 case Mips::ROL:
2577 case Mips::ROR:
2578 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2579 case Mips::ROLImm:
2580 case Mips::RORImm:
2581 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2582 case Mips::DROL:
2583 case Mips::DROR:
2584 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2585 case Mips::DROLImm:
2586 case Mips::DRORImm:
2587 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2588 case Mips::ABSMacro:
2589 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2590 case Mips::MULImmMacro:
2591 case Mips::DMULImmMacro:
2592 return expandMulImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2593 case Mips::MULOMacro:
2594 case Mips::DMULOMacro:
2595 return expandMulO(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2596 case Mips::MULOUMacro:
2597 case Mips::DMULOUMacro:
2598 return expandMulOU(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2599 case Mips::DMULMacro:
2600 return expandDMULMacro(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2601 case Mips::LDMacro:
2602 case Mips::SDMacro:
2603 return expandLoadStoreDMacro(Inst, IDLoc, Out, STI,
2604 Inst.getOpcode() == Mips::LDMacro)
2605 ? MER_Fail
2606 : MER_Success;
2607 case Mips::SDC1_M1:
2608 return expandStoreDM1Macro(Inst, IDLoc, Out, STI)
2609 ? MER_Fail
2610 : MER_Success;
2611 case Mips::SEQMacro:
2612 return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2613 case Mips::SEQIMacro:
2614 return expandSeqI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2615 case Mips::SNEMacro:
2616 return expandSne(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2617 case Mips::SNEIMacro:
2618 return expandSneI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2619 case Mips::MFTC0: case Mips::MTTC0:
2620 case Mips::MFTGPR: case Mips::MTTGPR:
2621 case Mips::MFTLO: case Mips::MTTLO:
2622 case Mips::MFTHI: case Mips::MTTHI:
2623 case Mips::MFTACX: case Mips::MTTACX:
2624 case Mips::MFTDSP: case Mips::MTTDSP:
2625 case Mips::MFTC1: case Mips::MTTC1:
2626 case Mips::MFTHC1: case Mips::MTTHC1:
2627 case Mips::CFTC1: case Mips::CTTC1:
2628 return expandMXTRAlias(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2629 case Mips::SaaAddr:
2630 case Mips::SaadAddr:
2631 return expandSaaAddr(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2632 }
2633}
2634
2635bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
2636 MCStreamer &Out,
2637 const MCSubtargetInfo *STI) {
2638 MipsTargetStreamer &TOut = getTargetStreamer();
2639
2640 // Create a JALR instruction which is going to replace the pseudo-JAL.
2641 MCInst JalrInst;
2642 JalrInst.setLoc(IDLoc);
2643 const MCOperand FirstRegOp = Inst.getOperand(0);
2644 const unsigned Opcode = Inst.getOpcode();
2645
2646 if (Opcode == Mips::JalOneReg) {
2647 // jal $rs => jalr $rs
2648 if (IsCpRestoreSet && inMicroMipsMode()) {
2649 JalrInst.setOpcode(Mips::JALRS16_MM);
2650 JalrInst.addOperand(FirstRegOp);
2651 } else if (inMicroMipsMode()) {
2652 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
2653 JalrInst.addOperand(FirstRegOp);
2654 } else {
2655 JalrInst.setOpcode(Mips::JALR);
2656 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
2657 JalrInst.addOperand(FirstRegOp);
2658 }
2659 } else if (Opcode == Mips::JalTwoReg) {
2660 // jal $rd, $rs => jalr $rd, $rs
2661 if (IsCpRestoreSet && inMicroMipsMode())
2662 JalrInst.setOpcode(Mips::JALRS_MM);
2663 else
2664 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
2665 JalrInst.addOperand(FirstRegOp);
2666 const MCOperand SecondRegOp = Inst.getOperand(1);
2667 JalrInst.addOperand(SecondRegOp);
2668 }
2669 Out.emitInstruction(JalrInst, *STI);
2670
2671 // If .set reorder is active and branch instruction has a delay slot,
2672 // emit a NOP after it.
2673 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
2674 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2675 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst), IDLoc,
2676 STI);
2677
2678 return false;
2679}
2680
2681/// Can the value be represented by a unsigned N-bit value and a shift left?
2682template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
2683 unsigned BitNum = findFirstSet(x);
1
Calling 'findFirstSet<unsigned long>'
8
Returning from 'findFirstSet<unsigned long>'
9
'BitNum' initialized to 4294967295
2684
2685 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
10
The result of the right shift is undefined due to shifting by '4294967295', which is greater or equal to the width of type 'uint64_t'
2686}
2687
2688/// Load (or add) an immediate into a register.
2689///
2690/// @param ImmValue The immediate to load.
2691/// @param DstReg The register that will hold the immediate.
2692/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2693/// for a simple initialization.
2694/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2695/// @param IsAddress True if the immediate represents an address. False if it
2696/// is an integer.
2697/// @param IDLoc Location of the immediate in the source file.
2698bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
2699 unsigned SrcReg, bool Is32BitImm,
2700 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2701 const MCSubtargetInfo *STI) {
2702 MipsTargetStreamer &TOut = getTargetStreamer();
2703
2704 if (!Is32BitImm && !isGP64bit()) {
2705 Error(IDLoc, "instruction requires a 64-bit architecture");
2706 return true;
2707 }
2708
2709 if (Is32BitImm) {
2710 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2711 // Sign extend up to 64-bit so that the predicates match the hardware
2712 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2713 // true.
2714 ImmValue = SignExtend64<32>(ImmValue);
2715 } else {
2716 Error(IDLoc, "instruction requires a 32-bit immediate");
2717 return true;
2718 }
2719 }
2720
2721 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2722 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2723
2724 bool UseSrcReg = false;
2725 if (SrcReg != Mips::NoRegister)
2726 UseSrcReg = true;
2727
2728 unsigned TmpReg = DstReg;
2729 if (UseSrcReg &&
2730 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
2731 // At this point we need AT to perform the expansions and we exit if it is
2732 // not available.
2733 unsigned ATReg = getATReg(IDLoc);
2734 if (!ATReg)
2735 return true;
2736 TmpReg = ATReg;
2737 }
2738
2739 if (isInt<16>(ImmValue)) {
2740 if (!UseSrcReg)
2741 SrcReg = ZeroReg;
2742
2743 // This doesn't quite follow the usual ABI expectations for N32 but matches
2744 // traditional assembler behaviour. N32 would normally use addiu for both
2745 // integers and addresses.
2746 if (IsAddress && !Is32BitImm) {
2747 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
2748 return false;
2749 }
2750
2751 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
2752 return false;
2753 }
2754
2755 if (isUInt<16>(ImmValue)) {
2756 unsigned TmpReg = DstReg;
2757 if (SrcReg == DstReg) {
2758 TmpReg = getATReg(IDLoc);
2759 if (!TmpReg)
2760 return true;
2761 }
2762
2763 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
2764 if (UseSrcReg)
2765 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
2766 return false;
2767 }
2768
2769 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2770 warnIfNoMacro(IDLoc);
2771
2772 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2773 uint16_t Bits15To0 = ImmValue & 0xffff;
2774 if (!Is32BitImm && !isInt<32>(ImmValue)) {
2775 // Traditional behaviour seems to special case this particular value. It's
2776 // not clear why other masks are handled differently.
2777 if (ImmValue == 0xffffffff) {
2778 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2779 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
2780 if (UseSrcReg)
2781 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
2782 return false;
2783 }
2784
2785 // Expand to an ORi instead of a LUi to avoid sign-extending into the
2786 // upper 32 bits.
2787 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2788 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
2789 if (Bits15To0)
2790 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
2791 if (UseSrcReg)
2792 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
2793 return false;
2794 }
2795
2796 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
2797 if (Bits15To0)
2798 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
2799 if (UseSrcReg)
2800 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
2801 return false;
2802 }
2803
2804 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2805 if (Is32BitImm) {
2806 Error(IDLoc, "instruction requires a 32-bit immediate");
2807 return true;
2808 }
2809
2810 // Traditionally, these immediates are shifted as little as possible and as
2811 // such we align the most significant bit to bit 15 of our temporary.
2812 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2813 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2814 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2815 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
2816 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2817 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
2818
2819 if (UseSrcReg)
2820 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
2821
2822 return false;
2823 }
2824
2825 warnIfNoMacro(IDLoc);
2826
2827 // The remaining case is packed with a sequence of dsll and ori with zeros
2828 // being omitted and any neighbouring dsll's being coalesced.
2829 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2830
2831 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2832 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
2833 IDLoc, Out, STI))
2834 return false;
2835
2836 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2837 // skip it and defer the shift to the next chunk.
2838 unsigned ShiftCarriedForwards = 16;
2839 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2840 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2841
2842 if (ImmChunk != 0) {
2843 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2844 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
2845 ShiftCarriedForwards = 0;
2846 }
2847
2848 ShiftCarriedForwards += 16;
2849 }
2850 ShiftCarriedForwards -= 16;
2851
2852 // Finish any remaining shifts left by trailing zeros.
2853 if (ShiftCarriedForwards)
2854 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2855
2856 if (UseSrcReg)
2857 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
2858
2859 return false;
2860}
2861
2862bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
2863 MCStreamer &Out, const MCSubtargetInfo *STI) {
2864 const MCOperand &ImmOp = Inst.getOperand(1);
2865 assert(ImmOp.isImm() && "expected immediate operand kind")(static_cast <bool> (ImmOp.isImm() && "expected immediate operand kind"
) ? void (0) : __assert_fail ("ImmOp.isImm() && \"expected immediate operand kind\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 2865, __extension__ __PRETTY_FUNCTION__))
;
2866 const MCOperand &DstRegOp = Inst.getOperand(0);
2867 assert(DstRegOp.isReg() && "expected register operand kind")(static_cast <bool> (DstRegOp.isReg() && "expected register operand kind"
) ? void (0) : __assert_fail ("DstRegOp.isReg() && \"expected register operand kind\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 2867, __extension__ __PRETTY_FUNCTION__))
;
2868
2869 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
2870 Is32BitImm, false, IDLoc, Out, STI))
2871 return true;
2872
2873 return false;
2874}
2875
2876bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2877 const MCOperand &Offset,
2878 bool Is32BitAddress, SMLoc IDLoc,
2879 MCStreamer &Out,
2880 const MCSubtargetInfo *STI) {
2881 // la can't produce a usable address when addresses are 64-bit.
2882 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2883 Warning(IDLoc, "la used to load 64-bit address");
2884 // Continue as if we had 'dla' instead.
2885 Is32BitAddress = false;
2886 }
2887
2888 // dla requires 64-bit addresses.
2889 if (!Is32BitAddress && !hasMips3()) {
2890 Error(IDLoc, "instruction requires a 64-bit architecture");
2891 return true;
2892 }
2893
2894 if (!Offset.isImm())
2895 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
2896 Is32BitAddress, IDLoc, Out, STI);
2897
2898 if (!ABI.ArePtrs64bit()) {
2899 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2900 Is32BitAddress = true;
2901 }
2902
2903 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
2904 IDLoc, Out, STI);
2905}
2906
2907bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2908 unsigned DstReg, unsigned SrcReg,
2909 bool Is32BitSym, SMLoc IDLoc,
2910 MCStreamer &Out,
2911 const MCSubtargetInfo *STI) {
2912 MipsTargetStreamer &TOut = getTargetStreamer();
2913 bool UseSrcReg = SrcReg != Mips::NoRegister && SrcReg != Mips::ZERO &&
2914 SrcReg != Mips::ZERO_64;
2915 warnIfNoMacro(IDLoc);
2916
2917 if (inPicMode()) {
2918 MCValue Res;
2919 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2920 Error(IDLoc, "expected relocatable expression");
2921 return true;
2922 }
2923 if (Res.getSymB() != nullptr) {
2924 Error(IDLoc, "expected relocatable expression with only one symbol");
2925 return true;
2926 }
2927
2928 bool IsPtr64 = ABI.ArePtrs64bit();
2929 bool IsLocalSym =
2930 Res.getSymA()->getSymbol().isInSection() ||
2931 Res.getSymA()->getSymbol().isTemporary() ||
2932 (Res.getSymA()->getSymbol().isELF() &&
2933 cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
2934 ELF::STB_LOCAL);
2935 bool UseXGOT = STI->getFeatureBits()[Mips::FeatureXGOT] && !IsLocalSym;
2936
2937 // The case where the result register is $25 is somewhat special. If the
2938 // symbol in the final relocation is external and not modified with a
2939 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16
2940 // or R_MIPS_CALL16 instead of R_MIPS_GOT_DISP in 64-bit case.
2941 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
2942 Res.getConstant() == 0 && !IsLocalSym) {
2943 if (UseXGOT) {
2944 const MCExpr *CallHiExpr = MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16,
2945 SymExpr, getContext());
2946 const MCExpr *CallLoExpr = MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16,
2947 SymExpr, getContext());
2948 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(CallHiExpr), IDLoc,
2949 STI);
2950 TOut.emitRRR(IsPtr64 ? Mips::DADDu : Mips::ADDu, DstReg, DstReg, GPReg,
2951 IDLoc, STI);
2952 TOut.emitRRX(IsPtr64 ? Mips::LD : Mips::LW, DstReg, DstReg,
2953 MCOperand::createExpr(CallLoExpr), IDLoc, STI);
2954 } else {
2955 const MCExpr *CallExpr =
2956 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2957 TOut.emitRRX(IsPtr64 ? Mips::LD : Mips::LW, DstReg, GPReg,
2958 MCOperand::createExpr(CallExpr), IDLoc, STI);
2959 }
2960 return false;
2961 }
2962
2963 unsigned TmpReg = DstReg;
2964 if (UseSrcReg &&
2965 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2966 SrcReg)) {
2967 // If $rs is the same as $rd, we need to use AT.
2968 // If it is not available we exit.
2969 unsigned ATReg = getATReg(IDLoc);
2970 if (!ATReg)
2971 return true;
2972 TmpReg = ATReg;
2973 }
2974
2975 // FIXME: In case of N32 / N64 ABI and emabled XGOT, local addresses
2976 // loaded using R_MIPS_GOT_PAGE / R_MIPS_GOT_OFST pair of relocations.
2977 // FIXME: Implement XGOT for microMIPS.
2978 if (UseXGOT) {
2979 // Loading address from XGOT
2980 // External GOT: lui $tmp, %got_hi(symbol)($gp)
2981 // addu $tmp, $tmp, $gp
2982 // lw $tmp, %got_lo(symbol)($tmp)
2983 // >addiu $tmp, $tmp, offset
2984 // >addiu $rd, $tmp, $rs
2985 // The addiu's marked with a '>' may be omitted if they are redundant. If
2986 // this happens then the last instruction must use $rd as the result
2987 // register.
2988 const MCExpr *CallHiExpr =
2989 MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, SymExpr, getContext());
2990 const MCExpr *CallLoExpr = MipsMCExpr::create(
2991 MipsMCExpr::MEK_GOT_LO16, Res.getSymA(), getContext());
2992
2993 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(CallHiExpr), IDLoc,
2994 STI);
2995 TOut.emitRRR(IsPtr64 ? Mips::DADDu : Mips::ADDu, TmpReg, TmpReg, GPReg,
2996 IDLoc, STI);
2997 TOut.emitRRX(IsPtr64 ? Mips::LD : Mips::LW, TmpReg, TmpReg,
2998 MCOperand::createExpr(CallLoExpr), IDLoc, STI);
2999
3000 if (Res.getConstant() != 0)
3001 TOut.emitRRX(IsPtr64 ? Mips::DADDiu : Mips::ADDiu, TmpReg, TmpReg,
3002 MCOperand::createExpr(MCConstantExpr::create(
3003 Res.getConstant(), getContext())),
3004 IDLoc, STI);
3005
3006 if (UseSrcReg)
3007 TOut.emitRRR(IsPtr64 ? Mips::DADDu : Mips::ADDu, DstReg, TmpReg, SrcReg,
3008 IDLoc, STI);
3009 return false;
3010 }
3011
3012 const MipsMCExpr *GotExpr = nullptr;
3013 const MCExpr *LoExpr = nullptr;
3014 if (ABI.IsN32() || ABI.IsN64()) {
3015 // The remaining cases are:
3016 // Small offset: ld $tmp, %got_disp(symbol)($gp)
3017 // >daddiu $tmp, $tmp, offset
3018 // >daddu $rd, $tmp, $rs
3019 // The daddiu's marked with a '>' may be omitted if they are redundant. If
3020 // this happens then the last instruction must use $rd as the result
3021 // register.
3022 GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, Res.getSymA(),
3023 getContext());
3024 if (Res.getConstant() != 0) {
3025 // Symbols fully resolve with just the %got_disp(symbol) but we
3026 // must still account for any offset to the symbol for
3027 // expressions like symbol+8.
3028 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
3029
3030 // FIXME: Offsets greater than 16 bits are not yet implemented.
3031 // FIXME: The correct range is a 32-bit sign-extended number.
3032 if (Res.getConstant() < -0x8000 || Res.getConstant() > 0x7fff) {
3033 Error(IDLoc, "macro instruction uses large offset, which is not "
3034 "currently supported");
3035 return true;
3036 }
3037 }
3038 } else {
3039 // The remaining cases are:
3040 // External GOT: lw $tmp, %got(symbol)($gp)
3041 // >addiu $tmp, $tmp, offset
3042 // >addiu $rd, $tmp, $rs
3043 // Local GOT: lw $tmp, %got(symbol+offset)($gp)
3044 // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
3045 // >addiu $rd, $tmp, $rs
3046 // The addiu's marked with a '>' may be omitted if they are redundant. If
3047 // this happens then the last instruction must use $rd as the result
3048 // register.
3049 if (IsLocalSym) {
3050 GotExpr =
3051 MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
3052 LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
3053 } else {
3054 // External symbols fully resolve the symbol with just the %got(symbol)
3055 // but we must still account for any offset to the symbol for
3056 // expressions like symbol+8.
3057 GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT, Res.getSymA(),
3058 getContext());
3059 if (Res.getConstant() != 0)
3060 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
3061 }
3062 }
3063
3064 TOut.emitRRX(IsPtr64 ? Mips::LD : Mips::LW, TmpReg, GPReg,
3065 MCOperand::createExpr(GotExpr), IDLoc, STI);
3066
3067 if (LoExpr)
3068 TOut.emitRRX(IsPtr64 ? Mips::DADDiu : Mips::ADDiu, TmpReg, TmpReg,
3069 MCOperand::createExpr(LoExpr), IDLoc, STI);
3070
3071 if (UseSrcReg)
3072 TOut.emitRRR(IsPtr64 ? Mips::DADDu : Mips::ADDu, DstReg, TmpReg, SrcReg,
3073 IDLoc, STI);
3074
3075 return false;
3076 }
3077
3078 const MipsMCExpr *HiExpr =
3079 MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
3080 const MipsMCExpr *LoExpr =
3081 MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
3082
3083 // This is the 64-bit symbol address expansion.
3084 if (ABI.ArePtrs64bit() && isGP64bit()) {
3085 // We need AT for the 64-bit expansion in the cases where the optional
3086 // source register is the destination register and for the superscalar
3087 // scheduled form.
3088 //
3089 // If it is not available we exit if the destination is the same as the
3090 // source register.
3091
3092 const MipsMCExpr *HighestExpr =
3093 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
3094 const MipsMCExpr *HigherExpr =
3095 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
3096
3097 bool RdRegIsRsReg =
3098 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg);
3099
3100 if (canUseATReg() && UseSrcReg && RdRegIsRsReg) {
3101 unsigned ATReg = getATReg(IDLoc);
3102
3103 // If $rs is the same as $rd:
3104 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
3105 // daddiu $at, $at, %higher(sym)
3106 // dsll $at, $at, 16
3107 // daddiu $at, $at, %hi(sym)
3108 // dsll $at, $at, 16
3109 // daddiu $at, $at, %lo(sym)
3110 // daddu $rd, $at, $rd
3111 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
3112 STI);
3113 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3114 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3115 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3116 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3117 IDLoc, STI);
3118 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3119 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
3120 IDLoc, STI);
3121 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
3122
3123 return false;
3124 } else if (canUseATReg() && !RdRegIsRsReg && DstReg != getATReg(IDLoc)) {
3125 unsigned ATReg = getATReg(IDLoc);
3126
3127 // If the $rs is different from $rd or if $rs isn't specified and we
3128 // have $at available:
3129 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3130 // lui $at, %hi(sym)
3131 // daddiu $rd, $rd, %higher(sym)
3132 // daddiu $at, $at, %lo(sym)
3133 // dsll32 $rd, $rd, 0
3134 // daddu $rd, $rd, $at
3135 // (daddu $rd, $rd, $rs)
3136 //
3137 // Which is preferred for superscalar issue.
3138 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3139 STI);
3140 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3141 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3142 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3143 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
3144 IDLoc, STI);
3145 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
3146 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
3147 if (UseSrcReg)
3148 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3149
3150 return false;
3151 } else if ((!canUseATReg() && !RdRegIsRsReg) ||
3152 (canUseATReg() && DstReg == getATReg(IDLoc))) {
3153 // Otherwise, synthesize the address in the destination register
3154 // serially:
3155 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3156 // daddiu $rd, $rd, %higher(sym)
3157 // dsll $rd, $rd, 16
3158 // daddiu $rd, $rd, %hi(sym)
3159 // dsll $rd, $rd, 16
3160 // daddiu $rd, $rd, %lo(sym)
3161 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3162 STI);
3163 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3164 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3165 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3166 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3167 MCOperand::createExpr(HiExpr), IDLoc, STI);
3168 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3169 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3170 MCOperand::createExpr(LoExpr), IDLoc, STI);
3171 if (UseSrcReg)
3172 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3173
3174 return false;
3175 } else {
3176 // We have a case where SrcReg == DstReg and we don't have $at
3177 // available. We can't expand this case, so error out appropriately.
3178 assert(SrcReg == DstReg && !canUseATReg() &&(static_cast <bool> (SrcReg == DstReg && !canUseATReg
() && "Could have expanded dla but didn't?") ? void (
0) : __assert_fail ("SrcReg == DstReg && !canUseATReg() && \"Could have expanded dla but didn't?\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3179, __extension__ __PRETTY_FUNCTION__))
3179 "Could have expanded dla but didn't?")(static_cast <bool> (SrcReg == DstReg && !canUseATReg
() && "Could have expanded dla but didn't?") ? void (
0) : __assert_fail ("SrcReg == DstReg && !canUseATReg() && \"Could have expanded dla but didn't?\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3179, __extension__ __PRETTY_FUNCTION__))
;
3180 reportParseError(IDLoc,
3181 "pseudo-instruction requires $at, which is not available");
3182 return true;
3183 }
3184 }
3185
3186 // And now, the 32-bit symbol address expansion:
3187 // If $rs is the same as $rd:
3188 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
3189 // ori $at, $at, %lo(sym)
3190 // addu $rd, $at, $rd
3191 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
3192 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
3193 // ori $rd, $rd, %lo(sym)
3194 // (addu $rd, $rd, $rs)
3195 unsigned TmpReg = DstReg;
3196 if (UseSrcReg &&
3197 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
3198 // If $rs is the same as $rd, we need to use AT.
3199 // If it is not available we exit.
3200 unsigned ATReg = getATReg(IDLoc);
3201 if (!ATReg)
3202 return true;
3203 TmpReg = ATReg;
3204 }
3205
3206 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3207 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
3208 IDLoc, STI);
3209
3210 if (UseSrcReg)
3211 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
3212 else
3213 assert((static_cast <bool> (getContext().getRegisterInfo()->
isSuperOrSubRegisterEq(DstReg, TmpReg)) ? void (0) : __assert_fail
("getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg)"
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3214, __extension__ __PRETTY_FUNCTION__))
3214 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg))(static_cast <bool> (getContext().getRegisterInfo()->
isSuperOrSubRegisterEq(DstReg, TmpReg)) ? void (0) : __assert_fail
("getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg)"
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3214, __extension__ __PRETTY_FUNCTION__))
;
3215
3216 return false;
3217}
3218
3219// Each double-precision register DO-D15 overlaps with two of the single
3220// precision registers F0-F31. As an example, all of the following hold true:
3221// D0 + 1 == F1, F1 + 1 == D1, F1 + 1 == F2, depending on the context.
3222static unsigned nextReg(unsigned Reg) {
3223 if (MipsMCRegisterClasses[Mips::FGR32RegClassID].contains(Reg))
3224 return Reg == (unsigned)Mips::F31 ? (unsigned)Mips::F0 : Reg + 1;
3225 switch (Reg) {
3226 default: llvm_unreachable("Unknown register in assembly macro expansion!")::llvm::llvm_unreachable_internal("Unknown register in assembly macro expansion!"
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3226)
;
3227 case Mips::ZERO: return Mips::AT;
3228 case Mips::AT: return Mips::V0;
3229 case Mips::V0: return Mips::V1;
3230 case Mips::V1: return Mips::A0;
3231 case Mips::A0: return Mips::A1;
3232 case Mips::A1: return Mips::A2;
3233 case Mips::A2: return Mips::A3;
3234 case Mips::A3: return Mips::T0;
3235 case Mips::T0: return Mips::T1;
3236 case Mips::T1: return Mips::T2;
3237 case Mips::T2: return Mips::T3;
3238 case Mips::T3: return Mips::T4;
3239 case Mips::T4: return Mips::T5;
3240 case Mips::T5: return Mips::T6;
3241 case Mips::T6: return Mips::T7;
3242 case Mips::T7: return Mips::S0;
3243 case Mips::S0: return Mips::S1;
3244 case Mips::S1: return Mips::S2;
3245 case Mips::S2: return Mips::S3;
3246 case Mips::S3: return Mips::S4;
3247 case Mips::S4: return Mips::S5;
3248 case Mips::S5: return Mips::S6;
3249 case Mips::S6: return Mips::S7;
3250 case Mips::S7: return Mips::T8;
3251 case Mips::T8: return Mips::T9;
3252 case Mips::T9: return Mips::K0;
3253 case Mips::K0: return Mips::K1;
3254 case Mips::K1: return Mips::GP;
3255 case Mips::GP: return Mips::SP;
3256 case Mips::SP: return Mips::FP;
3257 case Mips::FP: return Mips::RA;
3258 case Mips::RA: return Mips::ZERO;
3259 case Mips::D0: return Mips::F1;
3260 case Mips::D1: return Mips::F3;
3261 case Mips::D2: return Mips::F5;
3262 case Mips::D3: return Mips::F7;
3263 case Mips::D4: return Mips::F9;
3264 case Mips::D5: return Mips::F11;
3265 case Mips::D6: return Mips::F13;
3266 case Mips::D7: return Mips::F15;
3267 case Mips::D8: return Mips::F17;
3268 case Mips::D9: return Mips::F19;
3269 case Mips::D10: return Mips::F21;
3270 case Mips::D11: return Mips::F23;
3271 case Mips::D12: return Mips::F25;
3272 case Mips::D13: return Mips::F27;
3273 case Mips::D14: return Mips::F29;
3274 case Mips::D15: return Mips::F31;
3275 }
3276}
3277
3278// FIXME: This method is too general. In principle we should compute the number
3279// of instructions required to synthesize the immediate inline compared to
3280// synthesizing the address inline and relying on non .text sections.
3281// For static O32 and N32 this may yield a small benefit, for static N64 this is
3282// likely to yield a much larger benefit as we have to synthesize a 64bit
3283// address to load a 64 bit value.
3284bool MipsAsmParser::emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc,
3285 MCSymbol *Sym) {
3286 unsigned ATReg = getATReg(IDLoc);
3287 if (!ATReg)
3288 return true;
3289
3290 if(IsPicEnabled) {
3291 const MCExpr *GotSym =
3292 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3293 const MipsMCExpr *GotExpr =
3294 MipsMCExpr::create(MipsMCExpr::MEK_GOT, GotSym, getContext());
3295
3296 if(isABI_O32() || isABI_N32()) {
3297 TOut.emitRRX(Mips::LW, ATReg, GPReg, MCOperand::createExpr(GotExpr),
3298 IDLoc, STI);
3299 } else { //isABI_N64()
3300 TOut.emitRRX(Mips::LD, ATReg, GPReg, MCOperand::createExpr(GotExpr),
3301 IDLoc, STI);
3302 }
3303 } else { //!IsPicEnabled
3304 const MCExpr *HiSym =
3305 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3306 const MipsMCExpr *HiExpr =
3307 MipsMCExpr::create(MipsMCExpr::MEK_HI, HiSym, getContext());
3308
3309 // FIXME: This is technically correct but gives a different result to gas,
3310 // but gas is incomplete there (it has a fixme noting it doesn't work with
3311 // 64-bit addresses).
3312 // FIXME: With -msym32 option, the address expansion for N64 should probably
3313 // use the O32 / N32 case. It's safe to use the 64 address expansion as the
3314 // symbol's value is considered sign extended.
3315 if(isABI_O32() || isABI_N32()) {
3316 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3317 } else { //isABI_N64()
3318 const MCExpr *HighestSym =
3319 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3320 const MipsMCExpr *HighestExpr =
3321 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, HighestSym, getContext());
3322 const MCExpr *HigherSym =
3323 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3324 const MipsMCExpr *HigherExpr =
3325 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, HigherSym, getContext());
3326
3327 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
3328 STI);
3329 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3330 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3331 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3332 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3333 IDLoc, STI);
3334 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3335 }
3336 }
3337 return false;
3338}
3339
3340static uint64_t convertIntToDoubleImm(uint64_t ImmOp64) {
3341 // If ImmOp64 is AsmToken::Integer type (all bits set to zero in the
3342 // exponent field), convert it to double (e.g. 1 to 1.0)
3343 if ((Hi_32(ImmOp64) & 0x7ff00000) == 0) {
3344 APFloat RealVal(APFloat::IEEEdouble(), ImmOp64);
3345 ImmOp64 = RealVal.bitcastToAPInt().getZExtValue();
3346 }
3347 return ImmOp64;
3348}
3349
3350static uint32_t covertDoubleImmToSingleImm(uint64_t ImmOp64) {
3351 // Conversion of a double in an uint64_t to a float in a uint32_t,
3352 // retaining the bit pattern of a float.
3353 double DoubleImm = BitsToDouble(ImmOp64);
3354 float TmpFloat = static_cast<float>(DoubleImm);
3355 return FloatToBits(TmpFloat);
3356}
3357
3358bool MipsAsmParser::expandLoadSingleImmToGPR(MCInst &Inst, SMLoc IDLoc,
3359 MCStreamer &Out,
3360 const MCSubtargetInfo *STI) {
3361 assert(Inst.getNumOperands() == 2 && "Invalid operand count")(static_cast <bool> (Inst.getNumOperands() == 2 &&
"Invalid operand count") ? void (0) : __assert_fail ("Inst.getNumOperands() == 2 && \"Invalid operand count\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3361, __extension__ __PRETTY_FUNCTION__))
;
3362 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isImm() && "Invalid instruction operand."
) ? void (0) : __assert_fail ("Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3363, __extension__ __PRETTY_FUNCTION__))
3363 "Invalid instruction operand.")(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isImm() && "Invalid instruction operand."
) ? void (0) : __assert_fail ("Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3363, __extension__ __PRETTY_FUNCTION__))
;
3364
3365 unsigned FirstReg = Inst.getOperand(0).getReg();
3366 uint64_t ImmOp64 = Inst.getOperand(1).getImm();
3367
3368 uint32_t ImmOp32 = covertDoubleImmToSingleImm(convertIntToDoubleImm(ImmOp64));
3369
3370 return loadImmediate(ImmOp32, FirstReg, Mips::NoRegister, true, false, IDLoc,
3371 Out, STI);
3372}
3373
3374bool MipsAsmParser::expandLoadSingleImmToFPR(MCInst &Inst, SMLoc IDLoc,
3375 MCStreamer &Out,
3376 const MCSubtargetInfo *STI) {
3377 MipsTargetStreamer &TOut = getTargetStreamer();
3378 assert(Inst.getNumOperands() == 2 && "Invalid operand count")(static_cast <bool> (Inst.getNumOperands() == 2 &&
"Invalid operand count") ? void (0) : __assert_fail ("Inst.getNumOperands() == 2 && \"Invalid operand count\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3378, __extension__ __PRETTY_FUNCTION__))
;
3379 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isImm() && "Invalid instruction operand."
) ? void (0) : __assert_fail ("Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3380, __extension__ __PRETTY_FUNCTION__))
3380 "Invalid instruction operand.")(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isImm() && "Invalid instruction operand."
) ? void (0) : __assert_fail ("Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3380, __extension__ __PRETTY_FUNCTION__))
;
3381
3382 unsigned FirstReg = Inst.getOperand(0).getReg();
3383 uint64_t ImmOp64 = Inst.getOperand(1).getImm();
3384
3385 ImmOp64 = convertIntToDoubleImm(ImmOp64);
3386
3387 uint32_t ImmOp32 = covertDoubleImmToSingleImm(ImmOp64);
3388
3389 unsigned TmpReg = Mips::ZERO;
3390 if (ImmOp32 != 0) {
3391 TmpReg = getATReg(IDLoc);
3392 if (!TmpReg)
3393 return true;
3394 }
3395
3396 if (Lo_32(ImmOp64) == 0) {
3397 if (TmpReg != Mips::ZERO && loadImmediate(ImmOp32, TmpReg, Mips::NoRegister,
3398 true, false, IDLoc, Out, STI))
3399 return true;
3400 TOut.emitRR(Mips::MTC1, FirstReg, TmpReg, IDLoc, STI);
3401 return false;
3402 }
3403
3404 MCSection *CS = getStreamer().getCurrentSectionOnly();
3405 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3406 // where appropriate.
3407 MCSection *ReadOnlySection =
3408 getContext().getELFSection(".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3409
3410 MCSymbol *Sym = getContext().createTempSymbol();
3411 const MCExpr *LoSym =
3412 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3413 const MipsMCExpr *LoExpr =
3414 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3415
3416 getStreamer().SwitchSection(ReadOnlySection);
3417 getStreamer().emitLabel(Sym, IDLoc);
3418 getStreamer().emitInt32(ImmOp32);
3419 getStreamer().SwitchSection(CS);
3420
3421 if (emitPartialAddress(TOut, IDLoc, Sym))
3422 return true;
3423 TOut.emitRRX(Mips::LWC1, FirstReg, TmpReg, MCOperand::createExpr(LoExpr),
3424 IDLoc, STI);
3425 return false;
3426}
3427
3428bool MipsAsmParser::expandLoadDoubleImmToGPR(MCInst &Inst, SMLoc IDLoc,
3429 MCStreamer &Out,
3430 const MCSubtargetInfo *STI) {
3431 MipsTargetStreamer &TOut = getTargetStreamer();
3432 assert(Inst.getNumOperands() == 2 && "Invalid operand count")(static_cast <bool> (Inst.getNumOperands() == 2 &&
"Invalid operand count") ? void (0) : __assert_fail ("Inst.getNumOperands() == 2 && \"Invalid operand count\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3432, __extension__ __PRETTY_FUNCTION__))
;
3433 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isImm() && "Invalid instruction operand."
) ? void (0) : __assert_fail ("Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3434, __extension__ __PRETTY_FUNCTION__))
3434 "Invalid instruction operand.")(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isImm() && "Invalid instruction operand."
) ? void (0) : __assert_fail ("Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3434, __extension__ __PRETTY_FUNCTION__))
;
3435
3436 unsigned FirstReg = Inst.getOperand(0).getReg();
3437 uint64_t ImmOp64 = Inst.getOperand(1).getImm();
3438
3439 ImmOp64 = convertIntToDoubleImm(ImmOp64);
3440
3441 if (Lo_32(ImmOp64) == 0) {
3442 if (isGP64bit()) {
3443 if (loadImmediate(ImmOp64, FirstReg, Mips::NoRegister, false, false,
3444 IDLoc, Out, STI))
3445 return true;
3446 } else {
3447 if (loadImmediate(Hi_32(ImmOp64), FirstReg, Mips::NoRegister, true, false,
3448 IDLoc, Out, STI))
3449 return true;
3450
3451 if (loadImmediate(0, nextReg(FirstReg), Mips::NoRegister, true, false,
3452 IDLoc, Out, STI))
3453 return true;
3454 }
3455 return false;
3456 }
3457
3458 MCSection *CS = getStreamer().getCurrentSectionOnly();
3459 MCSection *ReadOnlySection =
3460 getContext().getELFSection(".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3461
3462 MCSymbol *Sym = getContext().createTempSymbol();
3463 const MCExpr *LoSym =
3464 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3465 const MipsMCExpr *LoExpr =
3466 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3467
3468 getStreamer().SwitchSection(ReadOnlySection);
3469 getStreamer().emitLabel(Sym, IDLoc);
3470 getStreamer().emitValueToAlignment(8);
3471 getStreamer().emitIntValue(ImmOp64, 8);
3472 getStreamer().SwitchSection(CS);
3473
3474 unsigned TmpReg = getATReg(IDLoc);
3475 if (!TmpReg)
3476 return true;
3477
3478 if (emitPartialAddress(TOut, IDLoc, Sym))
3479 return true;
3480
3481 TOut.emitRRX(isABI_N64() ? Mips::DADDiu : Mips::ADDiu, TmpReg, TmpReg,
3482 MCOperand::createExpr(LoExpr), IDLoc, STI);
3483
3484 if (isGP64bit())
3485 TOut.emitRRI(Mips::LD, FirstReg, TmpReg, 0, IDLoc, STI);
3486 else {
3487 TOut.emitRRI(Mips::LW, FirstReg, TmpReg, 0, IDLoc, STI);
3488 TOut.emitRRI(Mips::LW, nextReg(FirstReg), TmpReg, 4, IDLoc, STI);
3489 }
3490 return false;
3491}
3492
3493bool MipsAsmParser::expandLoadDoubleImmToFPR(MCInst &Inst, bool Is64FPU,
3494 SMLoc IDLoc, MCStreamer &Out,
3495 const MCSubtargetInfo *STI) {
3496 MipsTargetStreamer &TOut = getTargetStreamer();
3497 assert(Inst.getNumOperands() == 2 && "Invalid operand count")(static_cast <bool> (Inst.getNumOperands() == 2 &&
"Invalid operand count") ? void (0) : __assert_fail ("Inst.getNumOperands() == 2 && \"Invalid operand count\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3497, __extension__ __PRETTY_FUNCTION__))
;
3498 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isImm() && "Invalid instruction operand."
) ? void (0) : __assert_fail ("Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3499, __extension__ __PRETTY_FUNCTION__))
3499 "Invalid instruction operand.")(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isImm() && "Invalid instruction operand."
) ? void (0) : __assert_fail ("Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3499, __extension__ __PRETTY_FUNCTION__))
;
3500
3501 unsigned FirstReg = Inst.getOperand(0).getReg();
3502 uint64_t ImmOp64 = Inst.getOperand(1).getImm();
3503
3504 ImmOp64 = convertIntToDoubleImm(ImmOp64);
3505
3506 unsigned TmpReg = Mips::ZERO;
3507 if (ImmOp64 != 0) {
3508 TmpReg = getATReg(IDLoc);
3509 if (!TmpReg)
3510 return true;
3511 }
3512
3513 if ((Lo_32(ImmOp64) == 0) &&
3514 !((Hi_32(ImmOp64) & 0xffff0000) && (Hi_32(ImmOp64) & 0x0000ffff))) {
3515 if (isGP64bit()) {
3516 if (TmpReg != Mips::ZERO &&
3517 loadImmediate(ImmOp64, TmpReg, Mips::NoRegister, false, false, IDLoc,
3518 Out, STI))
3519 return true;
3520 TOut.emitRR(Mips::DMTC1, FirstReg, TmpReg, IDLoc, STI);
3521 return false;
3522 }
3523
3524 if (TmpReg != Mips::ZERO &&
3525 loadImmediate(Hi_32(ImmOp64), TmpReg, Mips::NoRegister, true, false,
3526 IDLoc, Out, STI))
3527 return true;
3528
3529 if (hasMips32r2()) {
3530 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3531 TOut.emitRRR(Mips::MTHC1_D32, FirstReg, FirstReg, TmpReg, IDLoc, STI);
3532 } else {
3533 TOut.emitRR(Mips::MTC1, nextReg(FirstReg), TmpReg, IDLoc, STI);
3534 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3535 }
3536 return false;
3537 }
3538
3539 MCSection *CS = getStreamer().getCurrentSectionOnly();
3540 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3541 // where appropriate.
3542 MCSection *ReadOnlySection =
3543 getContext().getELFSection(".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3544
3545 MCSymbol *Sym = getContext().createTempSymbol();
3546 const MCExpr *LoSym =
3547 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3548 const MipsMCExpr *LoExpr =
3549 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3550
3551 getStreamer().SwitchSection(ReadOnlySection);
3552 getStreamer().emitLabel(Sym, IDLoc);
3553 getStreamer().emitValueToAlignment(8);
3554 getStreamer().emitIntValue(ImmOp64, 8);
3555 getStreamer().SwitchSection(CS);
3556
3557 if (emitPartialAddress(TOut, IDLoc, Sym))
3558 return true;
3559
3560 TOut.emitRRX(Is64FPU ? Mips::LDC164 : Mips::LDC1, FirstReg, TmpReg,
3561 MCOperand::createExpr(LoExpr), IDLoc, STI);
3562
3563 return false;
3564}
3565
3566bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
3567 MCStreamer &Out,
3568 const MCSubtargetInfo *STI) {
3569 MipsTargetStreamer &TOut = getTargetStreamer();
3570
3571 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&(static_cast <bool> (getInstDesc(Inst.getOpcode()).getNumOperands
() == 1 && "unexpected number of operands") ? void (0
) : __assert_fail ("getInstDesc(Inst.getOpcode()).getNumOperands() == 1 && \"unexpected number of operands\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3572, __extension__ __PRETTY_FUNCTION__))
3572 "unexpected number of operands")(static_cast <bool> (getInstDesc(Inst.getOpcode()).getNumOperands
() == 1 && "unexpected number of operands") ? void (0
) : __assert_fail ("getInstDesc(Inst.getOpcode()).getNumOperands() == 1 && \"unexpected number of operands\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3572, __extension__ __PRETTY_FUNCTION__))
;
3573
3574 MCOperand Offset = Inst.getOperand(0);
3575 if (Offset.isExpr()) {
3576 Inst.clear();
3577 Inst.setOpcode(Mips::BEQ_MM);
3578 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3579 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3580 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
3581 } else {
3582 assert(Offset.isImm() && "expected immediate operand kind")(static_cast <bool> (Offset.isImm() && "expected immediate operand kind"
) ? void (0) : __assert_fail ("Offset.isImm() && \"expected immediate operand kind\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3582, __extension__ __PRETTY_FUNCTION__))
;
3583 if (isInt<11>(Offset.getImm())) {
3584 // If offset fits into 11 bits then this instruction becomes microMIPS
3585 // 16-bit unconditional branch instruction.
3586 if (inMicroMipsMode())
3587 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
3588 } else {
3589 if (!isInt<17>(Offset.getImm()))
3590 return Error(IDLoc, "branch target out of range");
3591 if (offsetToAlignment(Offset.getImm(), Align(2)))
3592 return Error(IDLoc, "branch to misaligned address");
3593 Inst.clear();
3594 Inst.setOpcode(Mips::BEQ_MM);
3595 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3596 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3597 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
3598 }
3599 }
3600 Out.emitInstruction(Inst, *STI);
3601
3602 // If .set reorder is active and branch instruction has a delay slot,
3603 // emit a NOP after it.
3604 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
3605 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
3606 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
3607
3608 return false;
3609}
3610
3611bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3612 const MCSubtargetInfo *STI) {
3613 MipsTargetStreamer &TOut = getTargetStreamer();
3614 const MCOperand &DstRegOp = Inst.getOperand(0);
3615 assert(DstRegOp.isReg() && "expected register operand kind")(static_cast <bool> (DstRegOp.isReg() && "expected register operand kind"
) ? void (0) : __assert_fail ("DstRegOp.isReg() && \"expected register operand kind\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3615, __extension__ __PRETTY_FUNCTION__))
;
3616
3617 const MCOperand &ImmOp = Inst.getOperand(1);
3618 assert(ImmOp.isImm() && "expected immediate operand kind")(static_cast <bool> (ImmOp.isImm() && "expected immediate operand kind"
) ? void (0) : __assert_fail ("ImmOp.isImm() && \"expected immediate operand kind\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3618, __extension__ __PRETTY_FUNCTION__))
;
3619
3620 const MCOperand &MemOffsetOp = Inst.getOperand(2);
3621 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&(static_cast <bool> ((MemOffsetOp.isImm() || MemOffsetOp
.isExpr()) && "expected immediate or expression operand"
) ? void (0) : __assert_fail ("(MemOffsetOp.isImm() || MemOffsetOp.isExpr()) && \"expected immediate or expression operand\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3622, __extension__ __PRETTY_FUNCTION__))
3622 "expected immediate or expression operand")(static_cast <bool> ((MemOffsetOp.isImm() || MemOffsetOp
.isExpr()) && "expected immediate or expression operand"
) ? void (0) : __assert_fail ("(MemOffsetOp.isImm() || MemOffsetOp.isExpr()) && \"expected immediate or expression operand\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3622, __extension__ __PRETTY_FUNCTION__))
;
3623
3624 bool IsLikely = false;
3625
3626 unsigned OpCode = 0;
3627 switch(Inst.getOpcode()) {
3628 case Mips::BneImm:
3629 OpCode = Mips::BNE;
3630 break;
3631 case Mips::BeqImm:
3632 OpCode = Mips::BEQ;
3633 break;
3634 case Mips::BEQLImmMacro:
3635 OpCode = Mips::BEQL;
3636 IsLikely = true;
3637 break;
3638 case Mips::BNELImmMacro:
3639 OpCode = Mips::BNEL;
3640 IsLikely = true;
3641 break;
3642 default:
3643 llvm_unreachable("Unknown immediate branch pseudo-instruction.")::llvm::llvm_unreachable_internal("Unknown immediate branch pseudo-instruction."
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3643)
;
3644 break;
3645 }
3646
3647 int64_t ImmValue = ImmOp.getImm();
3648 if (ImmValue == 0) {
3649 if (IsLikely) {
3650 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO,
3651 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3652 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3653 } else
3654 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
3655 STI);
3656 } else {
3657 warnIfNoMacro(IDLoc);
3658
3659 unsigned ATReg = getATReg(IDLoc);
3660 if (!ATReg)
3661 return true;
3662
3663 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
3664 IDLoc, Out, STI))
3665 return true;
3666
3667 if (IsLikely) {
3668 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg,
3669 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3670 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3671 } else
3672 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
3673 }
3674 return false;
3675}
3676
3677void MipsAsmParser::expandMem16Inst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3678 const MCSubtargetInfo *STI, bool IsLoad) {
3679 unsigned NumOp = Inst.getNumOperands();
3680 assert((NumOp == 3 || NumOp == 4) && "unexpected operands number")(static_cast <bool> ((NumOp == 3 || NumOp == 4) &&
"unexpected operands number") ? void (0) : __assert_fail ("(NumOp == 3 || NumOp == 4) && \"unexpected operands number\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3680, __extension__ __PRETTY_FUNCTION__))
;
3681 unsigned StartOp = NumOp == 3 ? 0 : 1;
3682
3683 const MCOperand &DstRegOp = Inst.getOperand(StartOp);
3684 assert(DstRegOp.isReg() && "expected register operand kind")(static_cast <bool> (DstRegOp.isReg() && "expected register operand kind"
) ? void (0) : __assert_fail ("DstRegOp.isReg() && \"expected register operand kind\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3684, __extension__ __PRETTY_FUNCTION__))
;
3685 const MCOperand &BaseRegOp = Inst.getOperand(StartOp + 1);
3686 assert(BaseRegOp.isReg() && "expected register operand kind")(static_cast <bool> (BaseRegOp.isReg() && "expected register operand kind"
) ? void (0) : __assert_fail ("BaseRegOp.isReg() && \"expected register operand kind\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3686, __extension__ __PRETTY_FUNCTION__))
;
3687 const MCOperand &OffsetOp = Inst.getOperand(StartOp + 2);
3688
3689 MipsTargetStreamer &TOut = getTargetStreamer();
3690 unsigned OpCode = Inst.getOpcode();
3691 unsigned DstReg = DstRegOp.getReg();
3692 unsigned BaseReg = BaseRegOp.getReg();
3693 unsigned TmpReg = DstReg;
3694
3695 const MCInstrDesc &Desc = getInstDesc(OpCode);
3696 int16_t DstRegClass = Desc.OpInfo[StartOp].RegClass;
3697 unsigned DstRegClassID =
3698 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
3699 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
3700 (DstRegClassID == Mips::GPR64RegClassID);
3701
3702 if (!IsLoad || !IsGPR || (BaseReg == DstReg)) {
3703 // At this point we need AT to perform the expansions
3704 // and we exit if it is not available.
3705 TmpReg = getATReg(IDLoc);
3706 if (!TmpReg)
3707 return;
3708 }
3709
3710 auto emitInstWithOffset = [&](const MCOperand &Off) {
3711 if (NumOp == 3)
3712 TOut.emitRRX(OpCode, DstReg, TmpReg, Off, IDLoc, STI);
3713 else
3714 TOut.emitRRRX(OpCode, DstReg, DstReg, TmpReg, Off, IDLoc, STI);
3715 };
3716
3717 if (OffsetOp.isImm()) {
3718 int64_t LoOffset = OffsetOp.getImm() & 0xffff;
3719 int64_t HiOffset = OffsetOp.getImm() & ~0xffff;
3720
3721 // If msb of LoOffset is 1(negative number) we must increment
3722 // HiOffset to account for the sign-extension of the low part.
3723 if (LoOffset & 0x8000)
3724 HiOffset += 0x10000;
3725
3726 bool IsLargeOffset = HiOffset != 0;
3727
3728 if (IsLargeOffset) {
3729 bool Is32BitImm = isInt<32>(OffsetOp.getImm());
3730 if (loadImmediate(HiOffset, TmpReg, Mips::NoRegister, Is32BitImm, true,
3731 IDLoc, Out, STI))
3732 return;
3733 }
3734
3735 if (BaseReg != Mips::ZERO && BaseReg != Mips::ZERO_64)
3736 TOut.emitRRR(ABI.ArePtrs64bit() ? Mips::DADDu : Mips::ADDu, TmpReg,
3737 TmpReg, BaseReg, IDLoc, STI);
3738 emitInstWithOffset(MCOperand::createImm(int16_t(LoOffset)));
3739 return;
3740 }
3741
3742 if (OffsetOp.isExpr()) {
3743 if (inPicMode()) {
3744 // FIXME:
3745 // c) Check that immediates of R_MIPS_GOT16/R_MIPS_LO16 relocations
3746 // do not exceed 16-bit.
3747 // d) Use R_MIPS_GOT_PAGE/R_MIPS_GOT_OFST relocations instead
3748 // of R_MIPS_GOT_DISP in appropriate cases to reduce number
3749 // of GOT entries.
3750 MCValue Res;
3751 if (!OffsetOp.getExpr()->evaluateAsRelocatable(Res, nullptr, nullptr)) {
3752 Error(IDLoc, "expected relocatable expression");
3753 return;
3754 }
3755 if (Res.getSymB() != nullptr) {
3756 Error(IDLoc, "expected relocatable expression with only one symbol");
3757 return;
3758 }
3759
3760 loadAndAddSymbolAddress(Res.getSymA(), TmpReg, BaseReg,
3761 !ABI.ArePtrs64bit(), IDLoc, Out, STI);
3762 emitInstWithOffset(MCOperand::createImm(int16_t(Res.getConstant())));
3763 } else {
3764 // FIXME: Implement 64-bit case.
3765 // 1) lw $8, sym => lui $8, %hi(sym)
3766 // lw $8, %lo(sym)($8)
3767 // 2) sw $8, sym => lui $at, %hi(sym)
3768 // sw $8, %lo(sym)($at)
3769 const MCExpr *OffExpr = OffsetOp.getExpr();
3770 MCOperand LoOperand = MCOperand::createExpr(
3771 MipsMCExpr::create(MipsMCExpr::MEK_LO, OffExpr, getContext()));
3772 MCOperand HiOperand = MCOperand::createExpr(
3773 MipsMCExpr::create(MipsMCExpr::MEK_HI, OffExpr, getContext()));
3774
3775 if (ABI.IsN64()) {
3776 MCOperand HighestOperand = MCOperand::createExpr(
3777 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, OffExpr, getContext()));
3778 MCOperand HigherOperand = MCOperand::createExpr(
3779 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, OffExpr, getContext()));
3780
3781 TOut.emitRX(Mips::LUi, TmpReg, HighestOperand, IDLoc, STI);
3782 TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, HigherOperand, IDLoc, STI);
3783 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
3784 TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, HiOperand, IDLoc, STI);
3785 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
3786 if (BaseReg != Mips::ZERO && BaseReg != Mips::ZERO_64)
3787 TOut.emitRRR(Mips::DADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI);
3788 emitInstWithOffset(LoOperand);
3789 } else {
3790 // Generate the base address in TmpReg.
3791 TOut.emitRX(Mips::LUi, TmpReg, HiOperand, IDLoc, STI);
3792 if (BaseReg != Mips::ZERO)
3793 TOut.emitRRR(Mips::ADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI);
3794 // Emit the load or store with the adjusted base and offset.
3795 emitInstWithOffset(LoOperand);
3796 }
3797 }
3798 return;
3799 }
3800
3801 llvm_unreachable("unexpected operand type")::llvm::llvm_unreachable_internal("unexpected operand type", "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3801)
;
3802}
3803
3804void MipsAsmParser::expandMem9Inst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3805 const MCSubtargetInfo *STI, bool IsLoad) {
3806 unsigned NumOp = Inst.getNumOperands();
3807 assert((NumOp == 3 || NumOp == 4) && "unexpected operands number")(static_cast <bool> ((NumOp == 3 || NumOp == 4) &&
"unexpected operands number") ? void (0) : __assert_fail ("(NumOp == 3 || NumOp == 4) && \"unexpected operands number\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3807, __extension__ __PRETTY_FUNCTION__))
;
3808 unsigned StartOp = NumOp == 3 ? 0 : 1;
3809
3810 const MCOperand &DstRegOp = Inst.getOperand(StartOp);
3811 assert(DstRegOp.isReg() && "expected register operand kind")(static_cast <bool> (DstRegOp.isReg() && "expected register operand kind"
) ? void (0) : __assert_fail ("DstRegOp.isReg() && \"expected register operand kind\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3811, __extension__ __PRETTY_FUNCTION__))
;
3812 const MCOperand &BaseRegOp = Inst.getOperand(StartOp + 1);
3813 assert(BaseRegOp.isReg() && "expected register operand kind")(static_cast <bool> (BaseRegOp.isReg() && "expected register operand kind"
) ? void (0) : __assert_fail ("BaseRegOp.isReg() && \"expected register operand kind\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3813, __extension__ __PRETTY_FUNCTION__))
;
3814 const MCOperand &OffsetOp = Inst.getOperand(StartOp + 2);
3815
3816 MipsTargetStreamer &TOut = getTargetStreamer();
3817 unsigned OpCode = Inst.getOpcode();
3818 unsigned DstReg = DstRegOp.getReg();
3819 unsigned BaseReg = BaseRegOp.getReg();
3820 unsigned TmpReg = DstReg;
3821
3822 const MCInstrDesc &Desc = getInstDesc(OpCode);
3823 int16_t DstRegClass = Desc.OpInfo[StartOp].RegClass;
3824 unsigned DstRegClassID =
3825 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
3826 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
3827 (DstRegClassID == Mips::GPR64RegClassID);
3828
3829 if (!IsLoad || !IsGPR || (BaseReg == DstReg)) {
3830 // At this point we need AT to perform the expansions
3831 // and we exit if it is not available.
3832 TmpReg = getATReg(IDLoc);
3833 if (!TmpReg)
3834 return;
3835 }
3836
3837 auto emitInst = [&]() {
3838 if (NumOp == 3)
3839 TOut.emitRRX(OpCode, DstReg, TmpReg, MCOperand::createImm(0), IDLoc, STI);
3840 else
3841 TOut.emitRRRX(OpCode, DstReg, DstReg, TmpReg, MCOperand::createImm(0),
3842 IDLoc, STI);
3843 };
3844
3845 if (OffsetOp.isImm()) {
3846 loadImmediate(OffsetOp.getImm(), TmpReg, BaseReg, !ABI.ArePtrs64bit(), true,
3847 IDLoc, Out, STI);
3848 emitInst();
3849 return;
3850 }
3851
3852 if (OffsetOp.isExpr()) {
3853 loadAndAddSymbolAddress(OffsetOp.getExpr(), TmpReg, BaseReg,
3854 !ABI.ArePtrs64bit(), IDLoc, Out, STI);
3855 emitInst();
3856 return;
3857 }
3858
3859 llvm_unreachable("unexpected operand type")::llvm::llvm_unreachable_internal("unexpected operand type", "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3859)
;
3860}
3861
3862bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
3863 MCStreamer &Out,
3864 const MCSubtargetInfo *STI) {
3865 unsigned OpNum = Inst.getNumOperands();
3866 unsigned Opcode = Inst.getOpcode();
3867 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
3868
3869 assert(Inst.getOperand(OpNum - 1).isImm() &&(static_cast <bool> (Inst.getOperand(OpNum - 1).isImm()
&& Inst.getOperand(OpNum - 2).isReg() && Inst
.getOperand(OpNum - 3).isReg() && "Invalid instruction operand."
) ? void (0) : __assert_fail ("Inst.getOperand(OpNum - 1).isImm() && Inst.getOperand(OpNum - 2).isReg() && Inst.getOperand(OpNum - 3).isReg() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3871, __extension__ __PRETTY_FUNCTION__))
3870 Inst.getOperand(OpNum - 2).isReg() &&(static_cast <bool> (Inst.getOperand(OpNum - 1).isImm()
&& Inst.getOperand(OpNum - 2).isReg() && Inst
.getOperand(OpNum - 3).isReg() && "Invalid instruction operand."
) ? void (0) : __assert_fail ("Inst.getOperand(OpNum - 1).isImm() && Inst.getOperand(OpNum - 2).isReg() && Inst.getOperand(OpNum - 3).isReg() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3871, __extension__ __PRETTY_FUNCTION__))
3871 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.")(static_cast <bool> (Inst.getOperand(OpNum - 1).isImm()
&& Inst.getOperand(OpNum - 2).isReg() && Inst
.getOperand(OpNum - 3).isReg() && "Invalid instruction operand."
) ? void (0) : __assert_fail ("Inst.getOperand(OpNum - 1).isImm() && Inst.getOperand(OpNum - 2).isReg() && Inst.getOperand(OpNum - 3).isReg() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3871, __extension__ __PRETTY_FUNCTION__))
;
3872
3873 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
3874 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
3875 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
3876 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
3877 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
3878 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
3879 // It can be implemented as SWM16 or LWM16 instruction.
3880 if (inMicroMipsMode() && hasMips32r6())
3881 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
3882 else
3883 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
3884 }
3885
3886 Inst.setOpcode(NewOpcode);
3887 Out.emitInstruction(Inst, *STI);
3888 return false;
3889}
3890
3891bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
3892 MCStreamer &Out,
3893 const MCSubtargetInfo *STI) {
3894 MipsTargetStreamer &TOut = getTargetStreamer();
3895 bool EmittedNoMacroWarning = false;
3896 unsigned PseudoOpcode = Inst.getOpcode();
3897 unsigned SrcReg = Inst.getOperand(0).getReg();
3898 const MCOperand &TrgOp = Inst.getOperand(1);
3899 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
3900
3901 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
3902 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
3903
3904 unsigned TrgReg;
3905 if (TrgOp.isReg())
3906 TrgReg = TrgOp.getReg();
3907 else if (TrgOp.isImm()) {
3908 warnIfNoMacro(IDLoc);
3909 EmittedNoMacroWarning = true;
3910
3911 TrgReg = getATReg(IDLoc);
3912 if (!TrgReg)
3913 return true;
3914
3915 switch(PseudoOpcode) {
3916 default:
3917 llvm_unreachable("unknown opcode for branch pseudo-instruction")::llvm::llvm_unreachable_internal("unknown opcode for branch pseudo-instruction"
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 3917)
;
3918 case Mips::BLTImmMacro:
3919 PseudoOpcode = Mips::BLT;
3920 break;
3921 case Mips::BLEImmMacro:
3922 PseudoOpcode = Mips::BLE;
3923 break;
3924 case Mips::BGEImmMacro:
3925 PseudoOpcode = Mips::BGE;
3926 break;
3927 case Mips::BGTImmMacro:
3928 PseudoOpcode = Mips::BGT;
3929 break;
3930 case Mips::BLTUImmMacro:
3931 PseudoOpcode = Mips::BLTU;
3932 break;
3933 case Mips::BLEUImmMacro:
3934 PseudoOpcode = Mips::BLEU;
3935 break;
3936 case Mips::BGEUImmMacro:
3937 PseudoOpcode = Mips::BGEU;
3938 break;
3939 case Mips::BGTUImmMacro:
3940 PseudoOpcode = Mips::BGTU;
3941 break;
3942 case Mips::BLTLImmMacro:
3943 PseudoOpcode = Mips::BLTL;
3944 break;
3945 case Mips::BLELImmMacro:
3946 PseudoOpcode = Mips::BLEL;
3947 break;
3948 case Mips::BGELImmMacro:
3949 PseudoOpcode = Mips::BGEL;
3950 break;
3951 case Mips::BGTLImmMacro:
3952 PseudoOpcode = Mips::BGTL;
3953 break;
3954 case Mips::BLTULImmMacro:
3955 PseudoOpcode = Mips::BLTUL;
3956 break;
3957 case Mips::BLEULImmMacro:
3958 PseudoOpcode = Mips::BLEUL;
3959 break;
3960 case Mips::BGEULImmMacro:
3961 PseudoOpcode = Mips::BGEUL;
3962 break;
3963 case Mips::BGTULImmMacro:
3964 PseudoOpcode = Mips::BGTUL;
3965 break;
3966 }
3967
3968 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
3969 false, IDLoc, Out, STI))
3970 return true;
3971 }
3972
3973 switch (PseudoOpcode) {
3974 case Mips::BLT:
3975 case Mips::BLTU:
3976 case Mips::BLTL:
3977 case Mips::BLTUL:
3978 AcceptsEquality = false;
3979 ReverseOrderSLT = false;
3980 IsUnsigned =
3981 ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
3982 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
3983 ZeroSrcOpcode = Mips::BGTZ;
3984 ZeroTrgOpcode = Mips::BLTZ;
3985 break;
3986 case Mips::BLE:
3987 case Mips::BLEU:
3988 case Mips::BLEL:
3989 case Mips::BLEUL:
3990 AcceptsEquality = true;
3991 ReverseOrderSLT = true;
3992 IsUnsigned =
3993 ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
3994 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
3995 ZeroSrcOpcode = Mips::BGEZ;
3996 ZeroTrgOpcode = Mips::BLEZ;
3997 break;
3998 case Mips::BGE:
3999 case Mips::BGEU:
4000 case Mips::BGEL:
4001 case Mips::BGEUL:
4002 AcceptsEquality = true;
4003 ReverseOrderSLT = false;
4004 IsUnsigned =
4005 ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
4006 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
4007 ZeroSrcOpcode = Mips::BLEZ;
4008 ZeroTrgOpcode = Mips::BGEZ;
4009 break;
4010 case Mips::BGT:
4011 case Mips::BGTU:
4012 case Mips::BGTL:
4013 case Mips::BGTUL:
4014 AcceptsEquality = false;
4015 ReverseOrderSLT = true;
4016 IsUnsigned =
4017 ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
4018 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
4019 ZeroSrcOpcode = Mips::BLTZ;
4020 ZeroTrgOpcode = Mips::BGTZ;
4021 break;
4022 default:
4023 llvm_unreachable("unknown opcode for branch pseudo-instruction")::llvm::llvm_unreachable_internal("unknown opcode for branch pseudo-instruction"
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4023)
;
4024 }
4025
4026 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
4027 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
4028 if (IsSrcRegZero && IsTrgRegZero) {
4029 // FIXME: All of these Opcode-specific if's are needed for compatibility
4030 // with GAS' behaviour. However, they may not generate the most efficient
4031 // code in some circumstances.
4032 if (PseudoOpcode == Mips::BLT) {
4033 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
4034 IDLoc, STI);
4035 return false;
4036 }
4037 if (PseudoOpcode == Mips::BLE) {
4038 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
4039 IDLoc, STI);
4040 Warning(IDLoc, "branch is always taken");
4041 return false;
4042 }
4043 if (PseudoOpcode == Mips::BGE) {
4044 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
4045 IDLoc, STI);
4046 Warning(IDLoc, "branch is always taken");
4047 return false;
4048 }
4049 if (PseudoOpcode == Mips::BGT) {
4050 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
4051 IDLoc, STI);
4052 return false;
4053 }
4054 if (PseudoOpcode == Mips::BGTU) {
4055 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
4056 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
4057 return false;
4058 }
4059 if (AcceptsEquality) {
4060 // If both registers are $0 and the pseudo-branch accepts equality, it
4061 // will always be taken, so we emit an unconditional branch.
4062 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
4063 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
4064 Warning(IDLoc, "branch is always taken");
4065 return false;
4066 }
4067 // If both registers are $0 and the pseudo-branch does not accept
4068 // equality, it will never be taken, so we don't have to emit anything.
4069 return false;
4070 }
4071 if (IsSrcRegZero || IsTrgRegZero) {
4072 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
4073 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
4074 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
4075 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
4076 // the pseudo-branch will never be taken, so we don't emit anything.
4077 // This only applies to unsigned pseudo-branches.
4078 return false;
4079 }
4080 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
4081 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
4082 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
4083 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
4084 // the pseudo-branch will always be taken, so we emit an unconditional
4085 // branch.
4086 // This only applies to unsigned pseudo-branches.
4087 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
4088 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
4089 Warning(IDLoc, "branch is always taken");
4090 return false;
4091 }
4092 if (IsUnsigned) {
4093 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
4094 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
4095 // the pseudo-branch will be taken only when the non-zero register is
4096 // different from 0, so we emit a BNEZ.
4097 //
4098 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
4099 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
4100 // the pseudo-branch will be taken only when the non-zero register is
4101 // equal to 0, so we emit a BEQZ.
4102 //
4103 // Because only BLEU and BGEU branch on equality, we can use the
4104 // AcceptsEquality variable to decide when to emit the BEQZ.
4105 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
4106 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
4107 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
4108 return false;
4109 }
4110 // If we have a signed pseudo-branch and one of the registers is $0,
4111 // we can use an appropriate compare-to-zero branch. We select which one
4112 // to use in the switch statement above.
4113 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
4114 IsSrcRegZero ? TrgReg : SrcReg,
4115 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
4116 return false;
4117 }
4118
4119 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
4120 // expansions. If it is not available, we return.
4121 unsigned ATRegNum = getATReg(IDLoc);
4122 if (!ATRegNum)
4123 return true;
4124
4125 if (!EmittedNoMacroWarning)
4126 warnIfNoMacro(IDLoc);
4127
4128 // SLT fits well with 2 of our 4 pseudo-branches:
4129 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
4130 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
4131 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
4132 // This is accomplished by using a BNEZ with the result of the SLT.
4133 //
4134 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
4135 // and BLE with BGT), so we change the BNEZ into a BEQZ.
4136 // Because only BGE and BLE branch on equality, we can use the
4137 // AcceptsEquality variable to decide when to emit the BEQZ.
4138 // Note that the order of the SLT arguments doesn't change between
4139 // opposites.
4140 //
4141 // The same applies to the unsigned variants, except that SLTu is used
4142 // instead of SLT.
4143 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
4144 ReverseOrderSLT ? TrgReg : SrcReg,
4145 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
4146
4147 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
4148 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
4149 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
4150 STI);
4151 return false;
4152}
4153
4154// Expand a integer division macro.
4155//
4156// Notably we don't have to emit a warning when encountering $rt as the $zero
4157// register, or 0 as an immediate. processInstruction() has already done that.
4158//
4159// The destination register can only be $zero when expanding (S)DivIMacro or
4160// D(S)DivMacro.
4161
4162bool MipsAsmParser::expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4163 const MCSubtargetInfo *STI,
4164 const bool IsMips64, const bool Signed) {
4165 MipsTargetStreamer &TOut = getTargetStreamer();
4166
4167 warnIfNoMacro(IDLoc);
4168
4169 const MCOperand &RdRegOp = Inst.getOperand(0);
4170 assert(RdRegOp.isReg() && "expected register operand kind")(static_cast <bool> (RdRegOp.isReg() && "expected register operand kind"
) ? void (0) : __assert_fail ("RdRegOp.isReg() && \"expected register operand kind\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4170, __extension__ __PRETTY_FUNCTION__))
;
4171 unsigned RdReg = RdRegOp.getReg();
4172
4173 const MCOperand &RsRegOp = Inst.getOperand(1);
4174 assert(RsRegOp.isReg() && "expected register operand kind")(static_cast <bool> (RsRegOp.isReg() && "expected register operand kind"
) ? void (0) : __assert_fail ("RsRegOp.isReg() && \"expected register operand kind\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4174, __extension__ __PRETTY_FUNCTION__))
;
4175 unsigned RsReg = RsRegOp.getReg();
4176
4177 unsigned RtReg;
4178 int64_t ImmValue;
4179
4180 const MCOperand &RtOp = Inst.getOperand(2);
4181 assert((RtOp.isReg() || RtOp.isImm()) &&(static_cast <bool> ((RtOp.isReg() || RtOp.isImm()) &&
"expected register or immediate operand kind") ? void (0) : __assert_fail
("(RtOp.isReg() || RtOp.isImm()) && \"expected register or immediate operand kind\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4182, __extension__ __PRETTY_FUNCTION__))
4182 "expected register or immediate operand kind")(static_cast <bool> ((RtOp.isReg() || RtOp.isImm()) &&
"expected register or immediate operand kind") ? void (0) : __assert_fail
("(RtOp.isReg() || RtOp.isImm()) && \"expected register or immediate operand kind\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4182, __extension__ __PRETTY_FUNCTION__))
;
4183 if (RtOp.isReg())
4184 RtReg = RtOp.getReg();
4185 else
4186 ImmValue = RtOp.getImm();
4187
4188 unsigned DivOp;
4189 unsigned ZeroReg;
4190 unsigned SubOp;
4191
4192 if (IsMips64) {
4193 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
4194 ZeroReg = Mips::ZERO_64;
4195 SubOp = Mips::DSUB;
4196 } else {
4197 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
4198 ZeroReg = Mips::ZERO;
4199 SubOp = Mips::SUB;
4200 }
4201
4202 bool UseTraps = useTraps();
4203
4204 unsigned Opcode = Inst.getOpcode();
4205 bool isDiv = Opcode == Mips::SDivMacro || Opcode == Mips::SDivIMacro ||
4206 Opcode == Mips::UDivMacro || Opcode == Mips::UDivIMacro ||
4207 Opcode == Mips::DSDivMacro || Opcode == Mips::DSDivIMacro ||
4208 Opcode == Mips::DUDivMacro || Opcode == Mips::DUDivIMacro;
4209
4210 bool isRem = Opcode == Mips::SRemMacro || Opcode == Mips::SRemIMacro ||
4211 Opcode == Mips::URemMacro || Opcode == Mips::URemIMacro ||
4212 Opcode == Mips::DSRemMacro || Opcode == Mips::DSRemIMacro ||
4213 Opcode == Mips::DURemMacro || Opcode == Mips::DURemIMacro;
4214
4215 if (RtOp.isImm()) {
4216 unsigned ATReg = getATReg(IDLoc);
4217 if (!ATReg)
4218 return true;
4219
4220 if (ImmValue == 0) {
4221 if (UseTraps)
4222 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
4223 else
4224 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
4225 return false;
4226 }
4227
4228 if (isRem && (ImmValue == 1 || (Signed && (ImmValue == -1)))) {
4229 TOut.emitRRR(Mips::OR, RdReg, ZeroReg, ZeroReg, IDLoc, STI);
4230 return false;
4231 } else if (isDiv && ImmValue == 1) {
4232 TOut.emitRRR(Mips::OR, RdReg, RsReg, Mips::ZERO, IDLoc, STI);
4233 return false;
4234 } else if (isDiv && Signed && ImmValue == -1) {
4235 TOut.emitRRR(SubOp, RdReg, ZeroReg, RsReg, IDLoc, STI);
4236 return false;
4237 } else {
4238 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue),
4239 false, Inst.getLoc(), Out, STI))
4240 return true;
4241 TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI);
4242 TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
4243 return false;
4244 }
4245 return true;
4246 }
4247
4248 // If the macro expansion of (d)div(u) or (d)rem(u) would always trap or
4249 // break, insert the trap/break and exit. This gives a different result to
4250 // GAS. GAS has an inconsistency/missed optimization in that not all cases
4251 // are handled equivalently. As the observed behaviour is the same, we're ok.
4252 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
4253 if (UseTraps) {
4254 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
4255 return false;
4256 }
4257 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
4258 return false;
4259 }
4260
4261 // (d)rem(u) $0, $X, $Y is a special case. Like div $zero, $X, $Y, it does
4262 // not expand to macro sequence.
4263 if (isRem && (RdReg == Mips::ZERO || RdReg == Mips::ZERO_64)) {
4264 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
4265 return false;
4266 }
4267
4268 // Temporary label for first branch traget
4269 MCContext &Context = TOut.getStreamer().getContext();
4270 MCSymbol *BrTarget;
4271 MCOperand LabelOp;
4272
4273 if (UseTraps) {
4274 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
4275 } else {
4276 // Branch to the li instruction.
4277 BrTarget = Context.createTempSymbol();
4278 LabelOp = MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4279 TOut.emitRRX(Mips::BNE, RtReg, ZeroReg, LabelOp, IDLoc, STI);
4280 }
4281
4282 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
4283
4284 if (!UseTraps)
4285 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
4286
4287 if (!Signed) {
4288 if (!UseTraps)
4289 TOut.getStreamer().emitLabel(BrTarget);
4290
4291 TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
4292 return false;
4293 }
4294
4295 unsigned ATReg = getATReg(IDLoc);
4296 if (!ATReg)
4297 return true;
4298
4299 if (!UseTraps)
4300 TOut.getStreamer().emitLabel(BrTarget);
4301
4302 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
4303
4304 // Temporary label for the second branch target.
4305 MCSymbol *BrTargetEnd = Context.createTempSymbol();
4306 MCOperand LabelOpEnd =
4307 MCOperand::createExpr(MCSymbolRefExpr::create(BrTargetEnd, Context));
4308
4309 // Branch to the mflo instruction.
4310 TOut.emitRRX(Mips::BNE, RtReg, ATReg, LabelOpEnd, IDLoc, STI);
4311
4312 if (IsMips64) {
4313 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
4314 TOut.emitDSLL(ATReg, ATReg, 63, IDLoc, STI);
4315 } else {
4316 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
4317 }
4318
4319 if (UseTraps)
4320 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
4321 else {
4322 // Branch to the mflo instruction.
4323 TOut.emitRRX(Mips::BNE, RsReg, ATReg, LabelOpEnd, IDLoc, STI);
4324 TOut.emitNop(IDLoc, STI);
4325 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
4326 }
4327
4328 TOut.getStreamer().emitLabel(BrTargetEnd);
4329 TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
4330 return false;
4331}
4332
4333bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
4334 SMLoc IDLoc, MCStreamer &Out,
4335 const MCSubtargetInfo *STI) {
4336 MipsTargetStreamer &TOut = getTargetStreamer();
4337
4338 assert(Inst.getNumOperands() == 3 && "Invalid operand count")(static_cast <bool> (Inst.getNumOperands() == 3 &&
"Invalid operand count") ? void (0) : __assert_fail ("Inst.getNumOperands() == 3 && \"Invalid operand count\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4338, __extension__ __PRETTY_FUNCTION__))
;
4339 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isReg
() && "Invalid instruction operand.") ? void (0) : __assert_fail
("Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isReg() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4340, __extension__ __PRETTY_FUNCTION__))
4340 Inst.getOperand(2).isReg() && "Invalid instruction operand.")(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isReg
() && "Invalid instruction operand.") ? void (0) : __assert_fail
("Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isReg() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4340, __extension__ __PRETTY_FUNCTION__))
;
4341
4342 unsigned FirstReg = Inst.getOperand(0).getReg();
4343 unsigned SecondReg = Inst.getOperand(1).getReg();
4344 unsigned ThirdReg = Inst.getOperand(2).getReg();
4345
4346 if (hasMips1() && !hasMips2()) {
4347 unsigned ATReg = getATReg(IDLoc);
4348 if (!ATReg)
4349 return true;
4350 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4351 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4352 TOut.emitNop(IDLoc, STI);
4353 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
4354 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
4355 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
4356 TOut.emitNop(IDLoc, STI);
4357 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
4358 : Mips::CVT_W_S,
4359 FirstReg, SecondReg, IDLoc, STI);
4360 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
4361 TOut.emitNop(IDLoc, STI);
4362 return false;
4363 }
4364
4365 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
4366 : Mips::TRUNC_W_S,
4367 FirstReg, SecondReg, IDLoc, STI);
4368
4369 return false;
4370}
4371
4372bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
4373 MCStreamer &Out, const MCSubtargetInfo *STI) {
4374 if (hasMips32r6() || hasMips64r6()) {
4375 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
4376 }
4377
4378 const MCOperand &DstRegOp = Inst.getOperand(0);
4379 assert(DstRegOp.isReg() && "expected register operand kind")(static_cast <bool> (DstRegOp.isReg() && "expected register operand kind"
) ? void (0) : __assert_fail ("DstRegOp.isReg() && \"expected register operand kind\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4379, __extension__ __PRETTY_FUNCTION__))
;
4380 const MCOperand &SrcRegOp = Inst.getOperand(1);
4381 assert(SrcRegOp.isReg() && "expected register operand kind")(static_cast <bool> (SrcRegOp.isReg() && "expected register operand kind"
) ? void (0) : __assert_fail ("SrcRegOp.isReg() && \"expected register operand kind\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4381, __extension__ __PRETTY_FUNCTION__))
;
4382 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4383 assert(OffsetImmOp.isImm() && "expected immediate operand kind")(static_cast <bool> (OffsetImmOp.isImm() && "expected immediate operand kind"
) ? void (0) : __assert_fail ("OffsetImmOp.isImm() && \"expected immediate operand kind\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4383, __extension__ __PRETTY_FUNCTION__))
;
4384
4385 MipsTargetStreamer &TOut = getTargetStreamer();
4386 unsigned DstReg = DstRegOp.getReg();
4387 unsigned SrcReg = SrcRegOp.getReg();
4388 int64_t OffsetValue = OffsetImmOp.getImm();
4389
4390 // NOTE: We always need AT for ULHU, as it is always used as the source
4391 // register for one of the LBu's.
4392 warnIfNoMacro(IDLoc);
4393 unsigned ATReg = getATReg(IDLoc);
4394 if (!ATReg)
4395 return true;
4396
4397 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4398 if (IsLargeOffset) {
4399 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4400 IDLoc, Out, STI))
4401 return true;
4402 }
4403
4404 int64_t FirstOffset = IsLargeOffset ? 0 : OffsetValue;
4405 int64_t SecondOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4406 if (isLittle())
4407 std::swap(FirstOffset, SecondOffset);
4408
4409 unsigned FirstLbuDstReg = IsLargeOffset ? DstReg : ATReg;
4410 unsigned SecondLbuDstReg = IsLargeOffset ? ATReg : DstReg;
4411
4412 unsigned LbuSrcReg = IsLargeOffset ? ATReg : SrcReg;
4413 unsigned SllReg = IsLargeOffset ? DstReg : ATReg;
4414
4415 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
4416 FirstOffset, IDLoc, STI);
4417 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondOffset, IDLoc, STI);
4418 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
4419 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
4420
4421 return false;
4422}
4423
4424bool MipsAsmParser::expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4425 const MCSubtargetInfo *STI) {
4426 if (hasMips32r6() || hasMips64r6()) {
4427 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
4428 }
4429
4430 const MCOperand &DstRegOp = Inst.getOperand(0);
4431 assert(DstRegOp.isReg() && "expected register operand kind")(static_cast <bool> (DstRegOp.isReg() && "expected register operand kind"
) ? void (0) : __assert_fail ("DstRegOp.isReg() && \"expected register operand kind\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4431, __extension__ __PRETTY_FUNCTION__))
;
4432 const MCOperand &SrcRegOp = Inst.getOperand(1);
4433 assert(SrcRegOp.isReg() && "expected register operand kind")(static_cast <bool> (SrcRegOp.isReg() && "expected register operand kind"
) ? void (0) : __assert_fail ("SrcRegOp.isReg() && \"expected register operand kind\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4433, __extension__ __PRETTY_FUNCTION__))
;
4434 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4435 assert(OffsetImmOp.isImm() && "expected immediate operand kind")(static_cast <bool> (OffsetImmOp.isImm() && "expected immediate operand kind"
) ? void (0) : __assert_fail ("OffsetImmOp.isImm() && \"expected immediate operand kind\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4435, __extension__ __PRETTY_FUNCTION__))
;
4436
4437 MipsTargetStreamer &TOut = getTargetStreamer();
4438 unsigned DstReg = DstRegOp.getReg();
4439 unsigned SrcReg = SrcRegOp.getReg();
4440 int64_t OffsetValue = OffsetImmOp.getImm();
4441
4442 warnIfNoMacro(IDLoc);
4443 unsigned ATReg = getATReg(IDLoc);
4444 if (!ATReg)
4445 return true;
4446
4447 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4448 if (IsLargeOffset) {
4449 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4450 IDLoc, Out, STI))
4451 return true;
4452 }
4453
4454 int64_t FirstOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4455 int64_t SecondOffset = IsLargeOffset ? 0 : OffsetValue;
4456 if (isLittle())
4457 std::swap(FirstOffset, SecondOffset);
4458
4459 if (IsLargeOffset) {
4460 TOut.emitRRI(Mips::SB, DstReg, ATReg, FirstOffset, IDLoc, STI);
4461 TOut.emitRRI(Mips::SRL, DstReg, DstReg, 8, IDLoc, STI);
4462 TOut.emitRRI(Mips::SB, DstReg, ATReg, SecondOffset, IDLoc, STI);
4463 TOut.emitRRI(Mips::LBu, ATReg, ATReg, 0, IDLoc, STI);
4464 TOut.emitRRI(Mips::SLL, DstReg, DstReg, 8, IDLoc, STI);
4465 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
4466 } else {
4467 TOut.emitRRI(Mips::SB, DstReg, SrcReg, FirstOffset, IDLoc, STI);
4468 TOut.emitRRI(Mips::SRL, ATReg, DstReg, 8, IDLoc, STI);
4469 TOut.emitRRI(Mips::SB, ATReg, SrcReg, SecondOffset, IDLoc, STI);
4470 }
4471
4472 return false;
4473}
4474
4475bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4476 const MCSubtargetInfo *STI) {
4477 if (hasMips32r6() || hasMips64r6()) {
4478 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
4479 }
4480
4481 const MCOperand &DstRegOp = Inst.getOperand(0);
4482 assert(DstRegOp.isReg() && "expected register operand kind")(static_cast <bool> (DstRegOp.isReg() && "expected register operand kind"
) ? void (0) : __assert_fail ("DstRegOp.isReg() && \"expected register operand kind\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4482, __extension__ __PRETTY_FUNCTION__))
;
4483 const MCOperand &SrcRegOp = Inst.getOperand(1);
4484 assert(SrcRegOp.isReg() && "expected register operand kind")(static_cast <bool> (SrcRegOp.isReg() && "expected register operand kind"
) ? void (0) : __assert_fail ("SrcRegOp.isReg() && \"expected register operand kind\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4484, __extension__ __PRETTY_FUNCTION__))
;
4485 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4486 assert(OffsetImmOp.isImm() && "expected immediate operand kind")(static_cast <bool> (OffsetImmOp.isImm() && "expected immediate operand kind"
) ? void (0) : __assert_fail ("OffsetImmOp.isImm() && \"expected immediate operand kind\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4486, __extension__ __PRETTY_FUNCTION__))
;
4487
4488 MipsTargetStreamer &TOut = getTargetStreamer();
4489 unsigned DstReg = DstRegOp.getReg();
4490 unsigned SrcReg = SrcRegOp.getReg();
4491 int64_t OffsetValue = OffsetImmOp.getImm();
4492
4493 // Compute left/right load/store offsets.
4494 bool IsLargeOffset = !(isInt<16>(OffsetValue + 3) && isInt<16>(OffsetValue));
4495 int64_t LxlOffset = IsLargeOffset ? 0 : OffsetValue;
4496 int64_t LxrOffset = IsLargeOffset ? 3 : (OffsetValue + 3);
4497 if (isLittle())
4498 std::swap(LxlOffset, LxrOffset);
4499
4500 bool IsLoadInst = (Inst.getOpcode() == Mips::Ulw);
4501 bool DoMove = IsLoadInst && (SrcReg == DstReg) && !IsLargeOffset;
4502 unsigned TmpReg = SrcReg;
4503 if (IsLargeOffset || DoMove) {
4504 warnIfNoMacro(IDLoc);
4505 TmpReg = getATReg(IDLoc);
4506 if (!TmpReg)
4507 return true;
4508 }
4509
4510 if (IsLargeOffset) {
4511 if (loadImmediate(OffsetValue, TmpReg, SrcReg, !ABI.ArePtrs64bit(), true,
4512 IDLoc, Out, STI))
4513 return true;
4514 }
4515
4516 if (DoMove)
4517 std::swap(DstReg, TmpReg);
4518
4519 unsigned XWL = IsLoadInst ? Mips::LWL : Mips::SWL;
4520 unsigned XWR = IsLoadInst ? Mips::LWR : Mips::SWR;
4521 TOut.emitRRI(XWL, DstReg, TmpReg, LxlOffset, IDLoc, STI);
4522 TOut.emitRRI(XWR, DstReg, TmpReg, LxrOffset, IDLoc, STI);
4523
4524 if (DoMove)
4525 TOut.emitRRR(Mips::OR, TmpReg, DstReg, Mips::ZERO, IDLoc, STI);
4526
4527 return false;
4528}
4529
4530bool MipsAsmParser::expandSge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4531 const MCSubtargetInfo *STI) {
4532 MipsTargetStreamer &TOut = getTargetStreamer();
4533
4534 assert(Inst.getNumOperands() == 3 && "Invalid operand count")(static_cast <bool> (Inst.getNumOperands() == 3 &&
"Invalid operand count") ? void (0) : __assert_fail ("Inst.getNumOperands() == 3 && \"Invalid operand count\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4534, __extension__ __PRETTY_FUNCTION__))
;
4535 assert(Inst.getOperand(0).isReg() &&(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isReg
() && "Invalid instruction operand.") ? void (0) : __assert_fail
("Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isReg() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4537, __extension__ __PRETTY_FUNCTION__))
4536 Inst.getOperand(1).isReg() &&(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isReg
() && "Invalid instruction operand.") ? void (0) : __assert_fail
("Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isReg() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4537, __extension__ __PRETTY_FUNCTION__))
4537 Inst.getOperand(2).isReg() && "Invalid instruction operand.")(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isReg
() && "Invalid instruction operand.") ? void (0) : __assert_fail
("Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isReg() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4537, __extension__ __PRETTY_FUNCTION__))
;
4538
4539 unsigned DstReg = Inst.getOperand(0).getReg();
4540 unsigned SrcReg = Inst.getOperand(1).getReg();
4541 unsigned OpReg = Inst.getOperand(2).getReg();
4542 unsigned OpCode;
4543
4544 warnIfNoMacro(IDLoc);
4545
4546 switch (Inst.getOpcode()) {
4547 case Mips::SGE:
4548 OpCode = Mips::SLT;
4549 break;
4550 case Mips::SGEU:
4551 OpCode = Mips::SLTu;
4552 break;
4553 default:
4554 llvm_unreachable("unexpected 'sge' opcode")::llvm::llvm_unreachable_internal("unexpected 'sge' opcode", "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4554)
;
4555 }
4556
4557 // $SrcReg >= $OpReg is equal to (not ($SrcReg < $OpReg))
4558 TOut.emitRRR(OpCode, DstReg, SrcReg, OpReg, IDLoc, STI);
4559 TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI);
4560
4561 return false;
4562}
4563
4564bool MipsAsmParser::expandSgeImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4565 const MCSubtargetInfo *STI) {
4566 MipsTargetStreamer &TOut = getTargetStreamer();
4567
4568 assert(Inst.getNumOperands() == 3 && "Invalid operand count")(static_cast <bool> (Inst.getNumOperands() == 3 &&
"Invalid operand count") ? void (0) : __assert_fail ("Inst.getNumOperands() == 3 && \"Invalid operand count\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4568, __extension__ __PRETTY_FUNCTION__))
;
4569 assert(Inst.getOperand(0).isReg() &&(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm
() && "Invalid instruction operand.") ? void (0) : __assert_fail
("Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4571, __extension__ __PRETTY_FUNCTION__))
4570 Inst.getOperand(1).isReg() &&(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm
() && "Invalid instruction operand.") ? void (0) : __assert_fail
("Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4571, __extension__ __PRETTY_FUNCTION__))
4571 Inst.getOperand(2).isImm() && "Invalid instruction operand.")(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm
() && "Invalid instruction operand.") ? void (0) : __assert_fail
("Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4571, __extension__ __PRETTY_FUNCTION__))
;
4572
4573 unsigned DstReg = Inst.getOperand(0).getReg();
4574 unsigned SrcReg = Inst.getOperand(1).getReg();
4575 int64_t ImmValue = Inst.getOperand(2).getImm();
4576 unsigned OpRegCode, OpImmCode;
4577
4578 warnIfNoMacro(IDLoc);
4579
4580 switch (Inst.getOpcode()) {
4581 case Mips::SGEImm:
4582 case Mips::SGEImm64:
4583 OpRegCode = Mips::SLT;
4584 OpImmCode = Mips::SLTi;
4585 break;
4586 case Mips::SGEUImm:
4587 case Mips::SGEUImm64:
4588 OpRegCode = Mips::SLTu;
4589 OpImmCode = Mips::SLTiu;
4590 break;
4591 default:
4592 llvm_unreachable("unexpected 'sge' opcode with immediate")::llvm::llvm_unreachable_internal("unexpected 'sge' opcode with immediate"
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4592)
;
4593 }
4594
4595 // $SrcReg >= Imm is equal to (not ($SrcReg < Imm))
4596 if (isInt<16>(ImmValue)) {
4597 // Use immediate version of STL.
4598 TOut.emitRRI(OpImmCode, DstReg, SrcReg, ImmValue, IDLoc, STI);
4599 TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI);
4600 } else {
4601 unsigned ImmReg = DstReg;
4602 if (DstReg == SrcReg) {
4603 unsigned ATReg = getATReg(Inst.getLoc());
4604 if (!ATReg)
4605 return true;
4606 ImmReg = ATReg;
4607 }
4608
4609 if (loadImmediate(ImmValue, ImmReg, Mips::NoRegister, isInt<32>(ImmValue),
4610 false, IDLoc, Out, STI))
4611 return true;
4612
4613 TOut.emitRRR(OpRegCode, DstReg, SrcReg, ImmReg, IDLoc, STI);
4614 TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI);
4615 }
4616
4617 return false;
4618}
4619
4620bool MipsAsmParser::expandSgtImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4621 const MCSubtargetInfo *STI) {
4622 MipsTargetStreamer &TOut = getTargetStreamer();
4623
4624 assert(Inst.getNumOperands() == 3 && "Invalid operand count")(static_cast <bool> (Inst.getNumOperands() == 3 &&
"Invalid operand count") ? void (0) : __assert_fail ("Inst.getNumOperands() == 3 && \"Invalid operand count\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4624, __extension__ __PRETTY_FUNCTION__))
;
4625 assert(Inst.getOperand(0).isReg() &&(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm
() && "Invalid instruction operand.") ? void (0) : __assert_fail
("Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4627, __extension__ __PRETTY_FUNCTION__))
4626 Inst.getOperand(1).isReg() &&(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm
() && "Invalid instruction operand.") ? void (0) : __assert_fail
("Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4627, __extension__ __PRETTY_FUNCTION__))
4627 Inst.getOperand(2).isImm() && "Invalid instruction operand.")(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm
() && "Invalid instruction operand.") ? void (0) : __assert_fail
("Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4627, __extension__ __PRETTY_FUNCTION__))
;
4628
4629 unsigned DstReg = Inst.getOperand(0).getReg();
4630 unsigned SrcReg = Inst.getOperand(1).getReg();
4631 unsigned ImmReg = DstReg;
4632 int64_t ImmValue = Inst.getOperand(2).getImm();
4633 unsigned OpCode;
4634
4635 warnIfNoMacro(IDLoc);
4636
4637 switch (Inst.getOpcode()) {
4638 case Mips::SGTImm:
4639 case Mips::SGTImm64:
4640 OpCode = Mips::SLT;
4641 break;
4642 case Mips::SGTUImm:
4643 case Mips::SGTUImm64:
4644 OpCode = Mips::SLTu;
4645 break;
4646 default:
4647 llvm_unreachable("unexpected 'sgt' opcode with immediate")::llvm::llvm_unreachable_internal("unexpected 'sgt' opcode with immediate"
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4647)
;
4648 }
4649
4650 if (DstReg == SrcReg) {
4651 unsigned ATReg = getATReg(Inst.getLoc());
4652 if (!ATReg)
4653 return true;
4654 ImmReg = ATReg;
4655 }
4656
4657 if (loadImmediate(ImmValue, ImmReg, Mips::NoRegister, isInt<32>(ImmValue),
4658 false, IDLoc, Out, STI))
4659 return true;
4660
4661 // $SrcReg > $ImmReg is equal to $ImmReg < $SrcReg
4662 TOut.emitRRR(OpCode, DstReg, ImmReg, SrcReg, IDLoc, STI);
4663
4664 return false;
4665}
4666
4667bool MipsAsmParser::expandSle(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4668 const MCSubtargetInfo *STI) {
4669 MipsTargetStreamer &TOut = getTargetStreamer();
4670
4671 assert(Inst.getNumOperands() == 3 && "Invalid operand count")(static_cast <bool> (Inst.getNumOperands() == 3 &&
"Invalid operand count") ? void (0) : __assert_fail ("Inst.getNumOperands() == 3 && \"Invalid operand count\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4671, __extension__ __PRETTY_FUNCTION__))
;
4672 assert(Inst.getOperand(0).isReg() &&(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isReg
() && "Invalid instruction operand.") ? void (0) : __assert_fail
("Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isReg() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4674, __extension__ __PRETTY_FUNCTION__))
4673 Inst.getOperand(1).isReg() &&(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isReg
() && "Invalid instruction operand.") ? void (0) : __assert_fail
("Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isReg() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4674, __extension__ __PRETTY_FUNCTION__))
4674 Inst.getOperand(2).isReg() && "Invalid instruction operand.")(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isReg
() && "Invalid instruction operand.") ? void (0) : __assert_fail
("Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isReg() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4674, __extension__ __PRETTY_FUNCTION__))
;
4675
4676 unsigned DstReg = Inst.getOperand(0).getReg();
4677 unsigned SrcReg = Inst.getOperand(1).getReg();
4678 unsigned OpReg = Inst.getOperand(2).getReg();
4679 unsigned OpCode;
4680
4681 warnIfNoMacro(IDLoc);
4682
4683 switch (Inst.getOpcode()) {
4684 case Mips::SLE:
4685 OpCode = Mips::SLT;
4686 break;
4687 case Mips::SLEU:
4688 OpCode = Mips::SLTu;
4689 break;
4690 default:
4691 llvm_unreachable("unexpected 'sge' opcode")::llvm::llvm_unreachable_internal("unexpected 'sge' opcode", "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4691)
;
4692 }
4693
4694 // $SrcReg <= $OpReg is equal to (not ($OpReg < $SrcReg))
4695 TOut.emitRRR(OpCode, DstReg, OpReg, SrcReg, IDLoc, STI);
4696 TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI);
4697
4698 return false;
4699}
4700
4701bool MipsAsmParser::expandSleImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4702 const MCSubtargetInfo *STI) {
4703 MipsTargetStreamer &TOut = getTargetStreamer();
4704
4705 assert(Inst.getNumOperands() == 3 && "Invalid operand count")(static_cast <bool> (Inst.getNumOperands() == 3 &&
"Invalid operand count") ? void (0) : __assert_fail ("Inst.getNumOperands() == 3 && \"Invalid operand count\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4705, __extension__ __PRETTY_FUNCTION__))
;
4706 assert(Inst.getOperand(0).isReg() &&(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm
() && "Invalid instruction operand.") ? void (0) : __assert_fail
("Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4708, __extension__ __PRETTY_FUNCTION__))
4707 Inst.getOperand(1).isReg() &&(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm
() && "Invalid instruction operand.") ? void (0) : __assert_fail
("Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4708, __extension__ __PRETTY_FUNCTION__))
4708 Inst.getOperand(2).isImm() && "Invalid instruction operand.")(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm
() && "Invalid instruction operand.") ? void (0) : __assert_fail
("Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4708, __extension__ __PRETTY_FUNCTION__))
;
4709
4710 unsigned DstReg = Inst.getOperand(0).getReg();
4711 unsigned SrcReg = Inst.getOperand(1).getReg();
4712 int64_t ImmValue = Inst.getOperand(2).getImm();
4713 unsigned OpRegCode;
4714
4715 warnIfNoMacro(IDLoc);
4716
4717 switch (Inst.getOpcode()) {
4718 case Mips::SLEImm:
4719 case Mips::SLEImm64:
4720 OpRegCode = Mips::SLT;
4721 break;
4722 case Mips::SLEUImm:
4723 case Mips::SLEUImm64:
4724 OpRegCode = Mips::SLTu;
4725 break;
4726 default:
4727 llvm_unreachable("unexpected 'sge' opcode with immediate")::llvm::llvm_unreachable_internal("unexpected 'sge' opcode with immediate"
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4727)
;
4728 }
4729
4730 // $SrcReg <= Imm is equal to (not (Imm < $SrcReg))
4731 unsigned ImmReg = DstReg;
4732 if (DstReg == SrcReg) {
4733 unsigned ATReg = getATReg(Inst.getLoc());
4734 if (!ATReg)
4735 return true;
4736 ImmReg = ATReg;
4737 }
4738
4739 if (loadImmediate(ImmValue, ImmReg, Mips::NoRegister, isInt<32>(ImmValue),
4740 false, IDLoc, Out, STI))
4741 return true;
4742
4743 TOut.emitRRR(OpRegCode, DstReg, ImmReg, SrcReg, IDLoc, STI);
4744 TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI);
4745
4746 return false;
4747}
4748
4749bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
4750 MCStreamer &Out,
4751 const MCSubtargetInfo *STI) {
4752 MipsTargetStreamer &TOut = getTargetStreamer();
4753
4754 assert(Inst.getNumOperands() == 3 && "Invalid operand count")(static_cast <bool> (Inst.getNumOperands() == 3 &&
"Invalid operand count") ? void (0) : __assert_fail ("Inst.getNumOperands() == 3 && \"Invalid operand count\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4754, __extension__ __PRETTY_FUNCTION__))
;
4755 assert(Inst.getOperand(0).isReg() &&(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm
() && "Invalid instruction operand.") ? void (0) : __assert_fail
("Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4757, __extension__ __PRETTY_FUNCTION__))
4756 Inst.getOperand(1).isReg() &&(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm
() && "Invalid instruction operand.") ? void (0) : __assert_fail
("Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4757, __extension__ __PRETTY_FUNCTION__))
4757 Inst.getOperand(2).isImm() && "Invalid instruction operand.")(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm
() && "Invalid instruction operand.") ? void (0) : __assert_fail
("Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4757, __extension__ __PRETTY_FUNCTION__))
;
4758
4759 unsigned ATReg = Mips::NoRegister;
4760 unsigned FinalDstReg = Mips::NoRegister;
4761 unsigned DstReg = Inst.getOperand(0).getReg();
4762 unsigned SrcReg = Inst.getOperand(1).getReg();
4763 int64_t ImmValue = Inst.getOperand(2).getImm();
4764
4765 bool Is32Bit = isInt<32>(ImmValue) || (!isGP64bit() && isUInt<32>(ImmValue));
4766
4767 unsigned FinalOpcode = Inst.getOpcode();
4768
4769 if (DstReg == SrcReg) {
4770 ATReg = getATReg(Inst.getLoc());
4771 if (!ATReg)
4772 return true;
4773 FinalDstReg = DstReg;
4774 DstReg = ATReg;
4775 }
4776
4777 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false,
4778 Inst.getLoc(), Out, STI)) {
4779 switch (FinalOpcode) {
4780 default:
4781 llvm_unreachable("unimplemented expansion")::llvm::llvm_unreachable_internal("unimplemented expansion", "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4781)
;
4782 case Mips::ADDi:
4783 FinalOpcode = Mips::ADD;
4784 break;
4785 case Mips::ADDiu:
4786 FinalOpcode = Mips::ADDu;
4787 break;
4788 case Mips::ANDi:
4789 FinalOpcode = Mips::AND;
4790 break;
4791 case Mips::NORImm:
4792 FinalOpcode = Mips::NOR;
4793 break;
4794 case Mips::ORi:
4795 FinalOpcode = Mips::OR;
4796 break;
4797 case Mips::SLTi:
4798 FinalOpcode = Mips::SLT;
4799 break;
4800 case Mips::SLTiu:
4801 FinalOpcode = Mips::SLTu;
4802 break;
4803 case Mips::XORi:
4804 FinalOpcode = Mips::XOR;
4805 break;
4806 case Mips::ADDi_MM:
4807 FinalOpcode = Mips::ADD_MM;
4808 break;
4809 case Mips::ADDiu_MM:
4810 FinalOpcode = Mips::ADDu_MM;
4811 break;
4812 case Mips::ANDi_MM:
4813 FinalOpcode = Mips::AND_MM;
4814 break;
4815 case Mips::ORi_MM:
4816 FinalOpcode = Mips::OR_MM;
4817 break;
4818 case Mips::SLTi_MM:
4819 FinalOpcode = Mips::SLT_MM;
4820 break;
4821 case Mips::SLTiu_MM:
4822 FinalOpcode = Mips::SLTu_MM;
4823 break;
4824 case Mips::XORi_MM:
4825 FinalOpcode = Mips::XOR_MM;
4826 break;
4827 case Mips::ANDi64:
4828 FinalOpcode = Mips::AND64;
4829 break;
4830 case Mips::NORImm64:
4831 FinalOpcode = Mips::NOR64;
4832 break;
4833 case Mips::ORi64:
4834 FinalOpcode = Mips::OR64;
4835 break;
4836 case Mips::SLTImm64:
4837 FinalOpcode = Mips::SLT64;
4838 break;
4839 case Mips::SLTUImm64:
4840 FinalOpcode = Mips::SLTu64;
4841 break;
4842 case Mips::XORi64:
4843 FinalOpcode = Mips::XOR64;
4844 break;
4845 }
4846
4847 if (FinalDstReg == Mips::NoRegister)
4848 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
4849 else
4850 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
4851 return false;
4852 }
4853 return true;
4854}
4855
4856bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4857 const MCSubtargetInfo *STI) {
4858 MipsTargetStreamer &TOut = getTargetStreamer();
4859 unsigned ATReg = Mips::NoRegister;
4860 unsigned DReg = Inst.getOperand(0).getReg();
4861 unsigned SReg = Inst.getOperand(1).getReg();
4862 unsigned TReg = Inst.getOperand(2).getReg();
4863 unsigned TmpReg = DReg;
4864
4865 unsigned FirstShift = Mips::NOP;
4866 unsigned SecondShift = Mips::NOP;
4867
4868 if (hasMips32r2()) {
4869 if (DReg == SReg) {
4870 TmpReg = getATReg(Inst.getLoc());
4871 if (!TmpReg)
4872 return true;
4873 }
4874
4875 if (Inst.getOpcode() == Mips::ROL) {
4876 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4877 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
4878 return false;
4879 }
4880
4881 if (Inst.getOpcode() == Mips::ROR) {
4882 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
4883 return false;
4884 }
4885
4886 return true;
4887 }
4888
4889 if (hasMips32()) {
4890 switch (Inst.getOpcode()) {
4891 default:
4892 llvm_unreachable("unexpected instruction opcode")::llvm::llvm_unreachable_internal("unexpected instruction opcode"
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4892)
;
4893 case Mips::ROL:
4894 FirstShift = Mips::SRLV;
4895 SecondShift = Mips::SLLV;
4896 break;
4897 case Mips::ROR:
4898 FirstShift = Mips::SLLV;
4899 SecondShift = Mips::SRLV;
4900 break;
4901 }
4902
4903 ATReg = getATReg(Inst.getLoc());
4904 if (!ATReg)
4905 return true;
4906
4907 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4908 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4909 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4910 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
4911
4912 return false;
4913 }
4914
4915 return true;
4916}
4917
4918bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
4919 MCStreamer &Out,
4920 const MCSubtargetInfo *STI) {
4921 MipsTargetStreamer &TOut = getTargetStreamer();
4922 unsigned ATReg = Mips::NoRegister;
4923 unsigned DReg = Inst.getOperand(0).getReg();
4924 unsigned SReg = Inst.getOperand(1).getReg();
4925 int64_t ImmValue = Inst.getOperand(2).getImm();
4926
4927 unsigned FirstShift = Mips::NOP;
4928 unsigned SecondShift = Mips::NOP;
4929
4930 if (hasMips32r2()) {
4931 if (Inst.getOpcode() == Mips::ROLImm) {
4932 uint64_t MaxShift = 32;
4933 uint64_t ShiftValue = ImmValue;
4934 if (ImmValue != 0)
4935 ShiftValue = MaxShift - ImmValue;
4936 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
4937 return false;
4938 }
4939
4940 if (Inst.getOpcode() == Mips::RORImm) {
4941 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
4942 return false;
4943 }
4944
4945 return true;
4946 }
4947
4948 if (hasMips32()) {
4949 if (ImmValue == 0) {
4950 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
4951 return false;
4952 }
4953
4954 switch (Inst.getOpcode()) {
4955 default:
4956 llvm_unreachable("unexpected instruction opcode")::llvm::llvm_unreachable_internal("unexpected instruction opcode"
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 4956)
;
4957 case Mips::ROLImm:
4958 FirstShift = Mips::SLL;
4959 SecondShift = Mips::SRL;
4960 break;
4961 case Mips::RORImm:
4962 FirstShift = Mips::SRL;
4963 SecondShift = Mips::SLL;
4964 break;
4965 }
4966
4967 ATReg = getATReg(Inst.getLoc());
4968 if (!ATReg)
4969 return true;
4970
4971 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
4972 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
4973 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
4974
4975 return false;
4976 }
4977
4978 return true;
4979}
4980
4981bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4982 const MCSubtargetInfo *STI) {
4983 MipsTargetStreamer &TOut = getTargetStreamer();
4984 unsigned ATReg = Mips::NoRegister;
4985 unsigned DReg = Inst.getOperand(0).getReg();
4986 unsigned SReg = Inst.getOperand(1).getReg();
4987 unsigned TReg = Inst.getOperand(2).getReg();
4988 unsigned TmpReg = DReg;
4989
4990 unsigned FirstShift = Mips::NOP;
4991 unsigned SecondShift = Mips::NOP;
4992
4993 if (hasMips64r2()) {
4994 if (TmpReg == SReg) {
4995 TmpReg = getATReg(Inst.getLoc());
4996 if (!TmpReg)
4997 return true;
4998 }
4999
5000 if (Inst.getOpcode() == Mips::DROL) {
5001 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
5002 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
5003 return false;
5004 }
5005
5006 if (Inst.getOpcode() == Mips::DROR) {
5007 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
5008 return false;
5009 }
5010
5011 return true;
5012 }
5013
5014 if (hasMips64()) {
5015 switch (Inst.getOpcode()) {
5016 default:
5017 llvm_unreachable("unexpected instruction opcode")::llvm::llvm_unreachable_internal("unexpected instruction opcode"
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 5017)
;
5018 case Mips::DROL:
5019 FirstShift = Mips::DSRLV;
5020 SecondShift = Mips::DSLLV;
5021 break;
5022 case Mips::DROR:
5023 FirstShift = Mips::DSLLV;
5024 SecondShift = Mips::DSRLV;
5025 break;
5026 }
5027
5028 ATReg = getATReg(Inst.getLoc());
5029 if (!ATReg)
5030 return true;
5031
5032 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
5033 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
5034 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
5035 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
5036
5037 return false;
5038 }
5039
5040 return true;
5041}
5042
5043bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
5044 MCStreamer &Out,
5045 const MCSubtargetInfo *STI) {
5046 MipsTargetStreamer &TOut = getTargetStreamer();
5047 unsigned ATReg = Mips::NoRegister;
5048 unsigned DReg = Inst.getOperand(0).getReg();
5049 unsigned SReg = Inst.getOperand(1).getReg();
5050 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
5051
5052 unsigned FirstShift = Mips::NOP;
5053 unsigned SecondShift = Mips::NOP;
5054
5055 MCInst TmpInst;
5056
5057 if (hasMips64r2()) {
5058 unsigned FinalOpcode = Mips::NOP;
5059 if (ImmValue == 0)
5060 FinalOpcode = Mips::DROTR;
5061 else if (ImmValue % 32 == 0)
5062 FinalOpcode = Mips::DROTR32;
5063 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
5064 if (Inst.getOpcode() == Mips::DROLImm)
5065 FinalOpcode = Mips::DROTR32;
5066 else
5067 FinalOpcode = Mips::DROTR;
5068 } else if (ImmValue >= 33) {
5069 if (Inst.getOpcode() == Mips::DROLImm)
5070 FinalOpcode = Mips::DROTR;
5071 else
5072 FinalOpcode = Mips::DROTR32;
5073 }
5074
5075 uint64_t ShiftValue = ImmValue % 32;
5076 if (Inst.getOpcode() == Mips::DROLImm)
5077 ShiftValue = (32 - ImmValue % 32) % 32;
5078
5079 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
5080
5081 return false;
5082 }
5083
5084 if (hasMips64()) {
5085 if (ImmValue == 0) {
5086 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
5087 return false;
5088 }
5089
5090 switch (Inst.getOpcode()) {
5091 default:
5092 llvm_unreachable("unexpected instruction opcode")::llvm::llvm_unreachable_internal("unexpected instruction opcode"
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 5092)
;
5093 case Mips::DROLImm:
5094 if ((ImmValue >= 1) && (ImmValue <= 31)) {
5095 FirstShift = Mips::DSLL;
5096 SecondShift = Mips::DSRL32;
5097 }
5098 if (ImmValue == 32) {
5099 FirstShift = Mips::DSLL32;
5100 SecondShift = Mips::DSRL32;
5101 }
5102 if ((ImmValue >= 33) && (ImmValue <= 63)) {
5103 FirstShift = Mips::DSLL32;
5104 SecondShift = Mips::DSRL;
5105 }
5106 break;
5107 case Mips::DRORImm:
5108 if ((ImmValue >= 1) && (ImmValue <= 31)) {
5109 FirstShift = Mips::DSRL;
5110 SecondShift = Mips::DSLL32;
5111 }
5112 if (ImmValue == 32) {
5113 FirstShift = Mips::DSRL32;
5114 SecondShift = Mips::DSLL32;
5115 }
5116 if ((ImmValue >= 33) && (ImmValue <= 63)) {
5117 FirstShift = Mips::DSRL32;
5118 SecondShift = Mips::DSLL;
5119 }
5120 break;
5121 }
5122
5123 ATReg = getATReg(Inst.getLoc());
5124 if (!ATReg)
5125 return true;
5126
5127 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
5128 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
5129 Inst.getLoc(), STI);
5130 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
5131
5132 return false;
5133 }
5134
5135 return true;
5136}
5137
5138bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5139 const MCSubtargetInfo *STI) {
5140 MipsTargetStreamer &TOut = getTargetStreamer();
5141 unsigned FirstRegOp = Inst.getOperand(0).getReg();
5142 unsigned SecondRegOp = Inst.getOperand(1).getReg();
5143
5144 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
5145 if (FirstRegOp != SecondRegOp)
5146 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
5147 else
5148 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
5149 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
5150
5151 return false;
5152}
5153
5154bool MipsAsmParser::expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5155 const MCSubtargetInfo *STI) {
5156 MipsTargetStreamer &TOut = getTargetStreamer();
5157 unsigned ATReg = Mips::NoRegister;
5158 unsigned DstReg = Inst.getOperand(0).getReg();
5159 unsigned SrcReg = Inst.getOperand(1).getReg();
5160 int32_t ImmValue = Inst.getOperand(2).getImm();
5161
5162 ATReg = getATReg(IDLoc);
5163 if (!ATReg)
5164 return true;
5165
5166 loadImmediate(ImmValue, ATReg, Mips::NoRegister, true, false, IDLoc, Out,
5167 STI);
5168
5169 TOut.emitRR(Inst.getOpcode() == Mips::MULImmMacro ? Mips::MULT : Mips::DMULT,
5170 SrcReg, ATReg, IDLoc, STI);
5171
5172 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
5173
5174 return false;
5175}
5176
5177bool MipsAsmParser::expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5178 const MCSubtargetInfo *STI) {
5179 MipsTargetStreamer &TOut = getTargetStreamer();
5180 unsigned ATReg = Mips::NoRegister;
5181 unsigned DstReg = Inst.getOperand(0).getReg();
5182 unsigned SrcReg = Inst.getOperand(1).getReg();
5183 unsigned TmpReg = Inst.getOperand(2).getReg();
5184
5185 ATReg = getATReg(Inst.getLoc());
5186 if (!ATReg)
5187 return true;
5188
5189 TOut.emitRR(Inst.getOpcode() == Mips::MULOMacro ? Mips::MULT : Mips::DMULT,
5190 SrcReg, TmpReg, IDLoc, STI);
5191
5192 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
5193
5194 TOut.emitRRI(Inst.getOpcode() == Mips::MULOMacro ? Mips::SRA : Mips::DSRA32,
5195 DstReg, DstReg, 0x1F, IDLoc, STI);
5196
5197 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
5198
5199 if (useTraps()) {
5200 TOut.emitRRI(Mips::TNE, DstReg, ATReg, 6, IDLoc, STI);
5201 } else {
5202 MCContext & Context = TOut.getStreamer().getContext();
5203 MCSymbol * BrTarget = Context.createTempSymbol();
5204 MCOperand LabelOp =
5205 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
5206
5207 TOut.emitRRX(Mips::BEQ, DstReg, ATReg, LabelOp, IDLoc, STI);
5208 if (AssemblerOptions.back()->isReorder())
5209 TOut.emitNop(IDLoc, STI);
5210 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
5211
5212 TOut.getStreamer().emitLabel(BrTarget);
5213 }
5214 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
5215
5216 return false;
5217}
5218
5219bool MipsAsmParser::expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5220 const MCSubtargetInfo *STI) {
5221 MipsTargetStreamer &TOut = getTargetStreamer();
5222 unsigned ATReg = Mips::NoRegister;
5223 unsigned DstReg = Inst.getOperand(0).getReg();
5224 unsigned SrcReg = Inst.getOperand(1).getReg();
5225 unsigned TmpReg = Inst.getOperand(2).getReg();
5226
5227 ATReg = getATReg(IDLoc);
5228 if (!ATReg)
5229 return true;
5230
5231 TOut.emitRR(Inst.getOpcode() == Mips::MULOUMacro ? Mips::MULTu : Mips::DMULTu,
5232 SrcReg, TmpReg, IDLoc, STI);
5233
5234 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
5235 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
5236 if (useTraps()) {
5237 TOut.emitRRI(Mips::TNE, ATReg, Mips::ZERO, 6, IDLoc, STI);
5238 } else {
5239 MCContext & Context = TOut.getStreamer().getContext();
5240 MCSymbol * BrTarget = Context.createTempSymbol();
5241 MCOperand LabelOp =
5242 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
5243
5244 TOut.emitRRX(Mips::BEQ, ATReg, Mips::ZERO, LabelOp, IDLoc, STI);
5245 if (AssemblerOptions.back()->isReorder())
5246 TOut.emitNop(IDLoc, STI);
5247 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
5248
5249 TOut.getStreamer().emitLabel(BrTarget);
5250 }
5251
5252 return false;
5253}
5254
5255bool MipsAsmParser::expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5256 const MCSubtargetInfo *STI) {
5257 MipsTargetStreamer &TOut = getTargetStreamer();
5258 unsigned DstReg = Inst.getOperand(0).getReg();
5259 unsigned SrcReg = Inst.getOperand(1).getReg();
5260 unsigned TmpReg = Inst.getOperand(2).getReg();
5261
5262 TOut.emitRR(Mips::DMULTu, SrcReg, TmpReg, IDLoc, STI);
5263 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
5264
5265 return false;
5266}
5267
5268// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
5269// lw $<reg+1>>, offset+4($reg2)'
5270// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);
5271// sw $<reg+1>>, offset+4($reg2)'
5272// for O32.
5273bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc,
5274 MCStreamer &Out,
5275 const MCSubtargetInfo *STI,
5276 bool IsLoad) {
5277 if (!isABI_O32())
5278 return true;
5279
5280 warnIfNoMacro(IDLoc);
5281
5282 MipsTargetStreamer &TOut = getTargetStreamer();
5283 unsigned Opcode = IsLoad ? Mips::LW : Mips::SW;
5284 unsigned FirstReg = Inst.getOperand(0).getReg();
5285 unsigned SecondReg = nextReg(FirstReg);
5286 unsigned BaseReg = Inst.getOperand(1).getReg();
5287 if (!SecondReg)
5288 return true;
5289
5290 warnIfRegIndexIsAT(FirstReg, IDLoc);
5291
5292 assert(Inst.getOperand(2).isImm() &&(static_cast <bool> (Inst.getOperand(2).isImm() &&
"Offset for load macro is not immediate!") ? void (0) : __assert_fail
("Inst.getOperand(2).isImm() && \"Offset for load macro is not immediate!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 5293, __extension__ __PRETTY_FUNCTION__))
5293 "Offset for load macro is not immediate!")(static_cast <bool> (Inst.getOperand(2).isImm() &&
"Offset for load macro is not immediate!") ? void (0) : __assert_fail
("Inst.getOperand(2).isImm() && \"Offset for load macro is not immediate!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 5293, __extension__ __PRETTY_FUNCTION__))
;
5294
5295 MCOperand &FirstOffset = Inst.getOperand(2);
5296 signed NextOffset = FirstOffset.getImm() + 4;
5297 MCOperand SecondOffset = MCOperand::createImm(NextOffset);
5298
5299 if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
5300 return true;
5301
5302 // For loads, clobber the base register with the second load instead of the
5303 // first if the BaseReg == FirstReg.
5304 if (FirstReg != BaseReg || !IsLoad) {
5305 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
5306 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
5307 } else {
5308 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
5309 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
5310 }
5311
5312 return false;
5313}
5314
5315
5316// Expand 's.d $<reg> offset($reg2)' to 'swc1 $<reg+1>, offset($reg2);
5317// swc1 $<reg>, offset+4($reg2)'
5318// or if little endian to 'swc1 $<reg>, offset($reg2);
5319// swc1 $<reg+1>, offset+4($reg2)'
5320// for Mips1.
5321bool MipsAsmParser::expandStoreDM1Macro(MCInst &Inst, SMLoc IDLoc,
5322 MCStreamer &Out,
5323 const MCSubtargetInfo *STI) {
5324 if (!isABI_O32())
5325 return true;
5326
5327 warnIfNoMacro(IDLoc);
5328
5329 MipsTargetStreamer &TOut = getTargetStreamer();
5330 unsigned Opcode = Mips::SWC1;
5331 unsigned FirstReg = Inst.getOperand(0).getReg();
5332 unsigned SecondReg = nextReg(FirstReg);
5333 unsigned BaseReg = Inst.getOperand(1).getReg();
5334 if (!SecondReg)
5335 return true;
5336
5337 warnIfRegIndexIsAT(FirstReg, IDLoc);
5338
5339 assert(Inst.getOperand(2).isImm() &&(static_cast <bool> (Inst.getOperand(2).isImm() &&
"Offset for macro is not immediate!") ? void (0) : __assert_fail
("Inst.getOperand(2).isImm() && \"Offset for macro is not immediate!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 5340, __extension__ __PRETTY_FUNCTION__))
5340 "Offset for macro is not immediate!")(static_cast <bool> (Inst.getOperand(2).isImm() &&
"Offset for macro is not immediate!") ? void (0) : __assert_fail
("Inst.getOperand(2).isImm() && \"Offset for macro is not immediate!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 5340, __extension__ __PRETTY_FUNCTION__))
;
5341
5342 MCOperand &FirstOffset = Inst.getOperand(2);
5343 signed NextOffset = FirstOffset.getImm() + 4;
5344 MCOperand SecondOffset = MCOperand::createImm(NextOffset);
5345
5346 if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
5347 return true;
5348
5349 if (!IsLittleEndian)
5350 std::swap(FirstReg, SecondReg);
5351
5352 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
5353 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
5354
5355 return false;
5356}
5357
5358bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5359 const MCSubtargetInfo *STI) {
5360 MipsTargetStreamer &TOut = getTargetStreamer();
5361
5362 assert(Inst.getNumOperands() == 3 && "Invalid operand count")(static_cast <bool> (Inst.getNumOperands() == 3 &&
"Invalid operand count") ? void (0) : __assert_fail ("Inst.getNumOperands() == 3 && \"Invalid operand count\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 5362, __extension__ __PRETTY_FUNCTION__))
;
5363 assert(Inst.getOperand(0).isReg() &&(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isReg
() && "Invalid instruction operand.") ? void (0) : __assert_fail
("Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isReg() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 5365, __extension__ __PRETTY_FUNCTION__))
5364 Inst.getOperand(1).isReg() &&(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isReg
() && "Invalid instruction operand.") ? void (0) : __assert_fail
("Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isReg() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 5365, __extension__ __PRETTY_FUNCTION__))
5365 Inst.getOperand(2).isReg() && "Invalid instruction operand.")(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isReg
() && "Invalid instruction operand.") ? void (0) : __assert_fail
("Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isReg() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 5365, __extension__ __PRETTY_FUNCTION__))
;
5366
5367 unsigned DstReg = Inst.getOperand(0).getReg();
5368 unsigned SrcReg = Inst.getOperand(1).getReg();
5369 unsigned OpReg = Inst.getOperand(2).getReg();
5370
5371 warnIfNoMacro(IDLoc);
5372
5373 if (SrcReg != Mips::ZERO && OpReg != Mips::ZERO) {
5374 TOut.emitRRR(Mips::XOR, DstReg, SrcReg, OpReg, IDLoc, STI);
5375 TOut.emitRRI(Mips::SLTiu, DstReg, DstReg, 1, IDLoc, STI);
5376 return false;
5377 }
5378
5379 unsigned Reg = SrcReg == Mips::ZERO ? OpReg : SrcReg;
5380 TOut.emitRRI(Mips::SLTiu, DstReg, Reg, 1, IDLoc, STI);
5381 return false;
5382}
5383
5384bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5385 const MCSubtargetInfo *STI) {
5386 MipsTargetStreamer &TOut = getTargetStreamer();
5387
5388 assert(Inst.getNumOperands() == 3 && "Invalid operand count")(static_cast <bool> (Inst.getNumOperands() == 3 &&
"Invalid operand count") ? void (0) : __assert_fail ("Inst.getNumOperands() == 3 && \"Invalid operand count\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 5388, __extension__ __PRETTY_FUNCTION__))
;
5389 assert(Inst.getOperand(0).isReg() &&(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm
() && "Invalid instruction operand.") ? void (0) : __assert_fail
("Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 5391, __extension__ __PRETTY_FUNCTION__))
5390 Inst.getOperand(1).isReg() &&(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm
() && "Invalid instruction operand.") ? void (0) : __assert_fail
("Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 5391, __extension__ __PRETTY_FUNCTION__))
5391 Inst.getOperand(2).isImm() && "Invalid instruction operand.")(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm
() && "Invalid instruction operand.") ? void (0) : __assert_fail
("Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 5391, __extension__ __PRETTY_FUNCTION__))
;
5392
5393 unsigned DstReg = Inst.getOperand(0).getReg();
5394 unsigned SrcReg = Inst.getOperand(1).getReg();
5395 int64_t Imm = Inst.getOperand(2).getImm();
5396
5397 warnIfNoMacro(IDLoc);
5398
5399 if (Imm == 0) {
5400 TOut.emitRRI(Mips::SLTiu, DstReg, SrcReg, 1, IDLoc, STI);
5401 return false;
5402 }
5403
5404 if (SrcReg == Mips::ZERO) {
5405 Warning(IDLoc, "comparison is always false");
5406 TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu,
5407 DstReg, SrcReg, SrcReg, IDLoc, STI);
5408 return false;
5409 }
5410
5411 unsigned Opc;
5412 if (Imm > -0x8000 && Imm < 0) {
5413 Imm = -Imm;
5414 Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;
5415 } else {
5416 Opc = Mips::XORi;
5417 }
5418
5419 if (!isUInt<16>(Imm)) {
5420 unsigned ATReg = getATReg(IDLoc);
5421 if (!ATReg)
5422 return true;
5423
5424 if (loadImmediate(Imm, ATReg, Mips::NoRegister, true, isGP64bit(), IDLoc,
5425 Out, STI))
5426 return true;
5427
5428 TOut.emitRRR(Mips::XOR, DstReg, SrcReg, ATReg, IDLoc, STI);
5429 TOut.emitRRI(Mips::SLTiu, DstReg, DstReg, 1, IDLoc, STI);
5430 return false;
5431 }
5432
5433 TOut.emitRRI(Opc, DstReg, SrcReg, Imm, IDLoc, STI);
5434 TOut.emitRRI(Mips::SLTiu, DstReg, DstReg, 1, IDLoc, STI);
5435 return false;
5436}
5437
5438bool MipsAsmParser::expandSne(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5439 const MCSubtargetInfo *STI) {
5440
5441 MipsTargetStreamer &TOut = getTargetStreamer();
5442
5443 assert(Inst.getNumOperands() == 3 && "Invalid operand count")(static_cast <bool> (Inst.getNumOperands() == 3 &&
"Invalid operand count") ? void (0) : __assert_fail ("Inst.getNumOperands() == 3 && \"Invalid operand count\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 5443, __extension__ __PRETTY_FUNCTION__))
;
5444 assert(Inst.getOperand(0).isReg() &&(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isReg
() && "Invalid instruction operand.") ? void (0) : __assert_fail
("Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isReg() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 5446, __extension__ __PRETTY_FUNCTION__))
5445 Inst.getOperand(1).isReg() &&(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isReg
() && "Invalid instruction operand.") ? void (0) : __assert_fail
("Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isReg() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 5446, __extension__ __PRETTY_FUNCTION__))
5446 Inst.getOperand(2).isReg() && "Invalid instruction operand.")(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isReg
() && "Invalid instruction operand.") ? void (0) : __assert_fail
("Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isReg() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 5446, __extension__ __PRETTY_FUNCTION__))
;
5447
5448 unsigned DstReg = Inst.getOperand(0).getReg();
5449 unsigned SrcReg = Inst.getOperand(1).getReg();
5450 unsigned OpReg = Inst.getOperand(2).getReg();
5451
5452 warnIfNoMacro(IDLoc);
5453
5454 if (SrcReg != Mips::ZERO && OpReg != Mips::ZERO) {
5455 TOut.emitRRR(Mips::XOR, DstReg, SrcReg, OpReg, IDLoc, STI);
5456 TOut.emitRRR(Mips::SLTu, DstReg, Mips::ZERO, DstReg, IDLoc, STI);
5457 return false;
5458 }
5459
5460 unsigned Reg = SrcReg == Mips::ZERO ? OpReg : SrcReg;
5461 TOut.emitRRR(Mips::SLTu, DstReg, Mips::ZERO, Reg, IDLoc, STI);
5462 return false;
5463}
5464
5465bool MipsAsmParser::expandSneI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5466 const MCSubtargetInfo *STI) {
5467 MipsTargetStreamer &TOut = getTargetStreamer();
5468
5469 assert(Inst.getNumOperands() == 3 && "Invalid operand count")(static_cast <bool> (Inst.getNumOperands() == 3 &&
"Invalid operand count") ? void (0) : __assert_fail ("Inst.getNumOperands() == 3 && \"Invalid operand count\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 5469, __extension__ __PRETTY_FUNCTION__))
;
5470 assert(Inst.getOperand(0).isReg() &&(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm
() && "Invalid instruction operand.") ? void (0) : __assert_fail
("Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 5472, __extension__ __PRETTY_FUNCTION__))
5471 Inst.getOperand(1).isReg() &&(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm
() && "Invalid instruction operand.") ? void (0) : __assert_fail
("Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 5472, __extension__ __PRETTY_FUNCTION__))
5472 Inst.getOperand(2).isImm() && "Invalid instruction operand.")(static_cast <bool> (Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm
() && "Invalid instruction operand.") ? void (0) : __assert_fail
("Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm() && \"Invalid instruction operand.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 5472, __extension__ __PRETTY_FUNCTION__))
;
5473
5474 unsigned DstReg = Inst.getOperand(0).getReg();
5475 unsigned SrcReg = Inst.getOperand(1).getReg();
5476 int64_t ImmValue = Inst.getOperand(2).getImm();
5477
5478 warnIfNoMacro(IDLoc);
5479
5480 if (ImmValue == 0) {
5481 TOut.emitRRR(Mips::SLTu, DstReg, Mips::ZERO, SrcReg, IDLoc, STI);
5482 return false;
5483 }
5484
5485 if (SrcReg == Mips::ZERO) {
5486 Warning(IDLoc, "comparison is always true");
5487 if (loadImmediate(1, DstReg, Mips::NoRegister, true, false, IDLoc, Out,
5488 STI))
5489 return true;
5490 return false;
5491 }
5492
5493 unsigned Opc;
5494 if (ImmValue > -0x8000 && ImmValue < 0) {
5495 ImmValue = -ImmValue;
5496 Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;
5497 } else {
5498 Opc = Mips::XORi;
5499 }
5500
5501 if (isUInt<16>(ImmValue)) {
5502 TOut.emitRRI(Opc, DstReg, SrcReg, ImmValue, IDLoc, STI);
5503 TOut.emitRRR(Mips::SLTu, DstReg, Mips::ZERO, DstReg, IDLoc, STI);
5504 return false;
5505 }
5506
5507 unsigned ATReg = getATReg(IDLoc);
5508 if (!ATReg)
5509 return true;
5510
5511 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue),
5512 false, IDLoc, Out, STI))
5513 return true;
5514
5515 TOut.emitRRR(Mips::XOR, DstReg, SrcReg, ATReg, IDLoc, STI);
5516 TOut.emitRRR(Mips::SLTu, DstReg, Mips::ZERO, DstReg, IDLoc, STI);
5517 return false;
5518}
5519
5520// Map the DSP accumulator and control register to the corresponding gpr
5521// operand. Unlike the other alias, the m(f|t)t(lo|hi|acx) instructions
5522// do not map the DSP registers contigously to gpr registers.
5523static unsigned getRegisterForMxtrDSP(MCInst &Inst, bool IsMFDSP) {
5524 switch (Inst.getOpcode()) {
5525 case Mips::MFTLO:
5526 case Mips::MTTLO:
5527 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
5528 case Mips::AC0:
5529 return Mips::ZERO;
5530 case Mips::AC1:
5531 return Mips::A0;
5532 case Mips::AC2:
5533 return Mips::T0;
5534 case Mips::AC3:
5535 return Mips::T4;
5536 default:
5537 llvm_unreachable("Unknown register for 'mttr' alias!")::llvm::llvm_unreachable_internal("Unknown register for 'mttr' alias!"
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 5537)
;
5538 }
5539 case Mips::MFTHI:
5540 case Mips::MTTHI:
5541 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
5542 case Mips::AC0:
5543 return Mips::AT;
5544 case Mips::AC1:
5545 return Mips::A1;
5546 case Mips::AC2:
5547 return Mips::T1;
5548 case Mips::AC3:
5549 return Mips::T5;
5550 default:
5551 llvm_unreachable("Unknown register for 'mttr' alias!")::llvm::llvm_unreachable_internal("Unknown register for 'mttr' alias!"
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 5551)
;
5552 }
5553 case Mips::MFTACX:
5554 case Mips::MTTACX:
5555 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
5556 case Mips::AC0:
5557 return Mips::V0;
5558 case Mips::AC1:
5559 return Mips::A2;
5560 case Mips::AC2:
5561 return Mips::T2;
5562 case Mips::AC3:
5563 return Mips::T6;
5564 default:
5565 llvm_unreachable("Unknown register for 'mttr' alias!")::llvm::llvm_unreachable_internal("Unknown register for 'mttr' alias!"
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 5565)
;
5566 }
5567 case Mips::MFTDSP:
5568 case Mips::MTTDSP:
5569 return Mips::S0;
5570 default:
5571 llvm_unreachable("Unknown instruction for 'mttr' dsp alias!")::llvm::llvm_unreachable_internal("Unknown instruction for 'mttr' dsp alias!"
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 5571)
;
5572 }
5573}
5574
5575// Map the floating point register operand to the corresponding register
5576// operand.
5577static unsigned getRegisterForMxtrFP(MCInst &Inst, bool IsMFTC1) {
5578 switch (Inst.getOperand(IsMFTC1 ? 1 : 0).getReg()) {
5579 case Mips::F0: return Mips::ZERO;
5580 case Mips::F1: return Mips::AT;
5581 case Mips::F2: return Mips::V0;
5582 case Mips::F3: return Mips::V1;
5583 case Mips::F4: return Mips::A0;
5584 case Mips::F5: return Mips::A1;
5585 case Mips::F6: return Mips::A2;
5586 case Mips::F7: return Mips::A3;
5587 case Mips::F8: return Mips::T0;
5588 case Mips::F9: return Mips::T1;
5589 case Mips::F10: return Mips::T2;
5590 case Mips::F11: return Mips::T3;
5591 case Mips::F12: return Mips::T4;
5592 case Mips::F13: return Mips::T5;
5593 case Mips::F14: return Mips::T6;
5594 case Mips::F15: return Mips::T7;
5595 case Mips::F16: return Mips::S0;
5596 case Mips::F17: return Mips::S1;
5597 case Mips::F18: return Mips::S2;
5598 case Mips::F19: return Mips::S3;
5599 case Mips::F20: return Mips::S4;
5600 case Mips::F21: return Mips::S5;
5601 case Mips::F22: return Mips::S6;
5602 case Mips::F23: return Mips::S7;
5603 case Mips::F24: return Mips::T8;
5604 case Mips::F25: return Mips::T9;
5605 case Mips::F26: return Mips::K0;
5606 case Mips::F27: return Mips::K1;
5607 case Mips::F28: return Mips::GP;
5608 case Mips::F29: return Mips::SP;
5609 case Mips::F30: return Mips::FP;
5610 case Mips::F31: return Mips::RA;
5611 default: llvm_unreachable("Unknown register for mttc1 alias!")::llvm::llvm_unreachable_internal("Unknown register for mttc1 alias!"
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 5611)
;
5612 }
5613}
5614
5615// Map the coprocessor operand the corresponding gpr register operand.
5616static unsigned getRegisterForMxtrC0(MCInst &Inst, bool IsMFTC0) {
5617 switch (Inst.getOperand(IsMFTC0 ? 1 : 0).getReg()) {
5618 case Mips::COP00: return Mips::ZERO;
5619 case Mips::COP01: return Mips::AT;
5620 case Mips::COP02: return Mips::V0;
5621 case Mips::COP03: return Mips::V1;
5622 case Mips::COP04: return Mips::A0;
5623 case Mips::COP05: return Mips::A1;
5624 case Mips::COP06: return Mips::A2;
5625 case Mips::COP07: return Mips::A3;
5626 case Mips::COP08: return Mips::T0;
5627 case Mips::COP09: return Mips::T1;
5628 case Mips::COP010: return Mips::T2;
5629 case Mips::COP011: return Mips::T3;
5630 case Mips::COP012: return Mips::T4;
5631 case Mips::COP013: return Mips::T5;
5632 case Mips::COP014: return Mips::T6;
5633 case Mips::COP015: return Mips::T7;
5634 case Mips::COP016: return Mips::S0;
5635 case Mips::COP017: return Mips::S1;
5636 case Mips::COP018: return Mips::S2;
5637 case Mips::COP019: return Mips::S3;
5638 case Mips::COP020: return Mips::S4;
5639 case Mips::COP021: return Mips::S5;
5640 case Mips::COP022: return Mips::S6;
5641 case Mips::COP023: return Mips::S7;
5642 case Mips::COP024: return Mips::T8;
5643 case Mips::COP025: return Mips::T9;
5644 case Mips::COP026: return Mips::K0;
5645 case Mips::COP027: return Mips::K1;
5646 case Mips::COP028: return Mips::GP;
5647 case Mips::COP029: return Mips::SP;
5648 case Mips::COP030: return Mips::FP;
5649 case Mips::COP031: return Mips::RA;
5650 default: llvm_unreachable("Unknown register for mttc0 alias!")::llvm::llvm_unreachable_internal("Unknown register for mttc0 alias!"
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp"
, 5650)
;
5651 }
5652}
5653
5654/// Expand an alias of 'mftr' or 'mttr' into the full instruction, by producing
5655/// an mftr or mttr with the correctly mapped gpr register, u, sel and h bits.
5656bool MipsAsmParser::expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5657 const MCSubtargetInfo *STI) {
5658 MipsTargetStreamer &TOut = getTargetStreamer();
5659 unsigned rd = 0;
5660 unsigned u = 1;
5661 unsigned sel = 0;
5662 unsigned h = 0;
5663 bool IsMFTR = false;
5664 switch (Inst.getOpcode()) {
5665 case Mips::MFTC0:
5666 IsMFTR = true;
5667 LLVM_FALLTHROUGH[[gnu::fallthrough]];
5668 case Mips::MTTC0: