Bug Summary

File:build/source/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
Warning:line 6816, column 11
Value stored to 'PrevReg' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

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