Bug Summary

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