/src/keystone/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
Line | Count | Source |
1 | | //===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===// |
2 | | // |
3 | | // The LLVM Compiler Infrastructure |
4 | | // |
5 | | // This file is distributed under the University of Illinois Open Source |
6 | | // License. See LICENSE.TXT for details. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | |
10 | | #include "MCTargetDesc/MipsABIInfo.h" |
11 | | #include "MCTargetDesc/MipsMCExpr.h" |
12 | | #include "MCTargetDesc/MipsMCTargetDesc.h" |
13 | | #include "MipsTargetStreamer.h" |
14 | | #include "llvm/ADT/APInt.h" |
15 | | #include "llvm/ADT/SmallVector.h" |
16 | | #include "llvm/ADT/StringSwitch.h" |
17 | | #include "llvm/ADT/STLExtras.h" |
18 | | #include "llvm/MC/MCContext.h" |
19 | | #include "llvm/MC/MCExpr.h" |
20 | | #include "llvm/MC/MCInst.h" |
21 | | #include "llvm/MC/MCInstBuilder.h" |
22 | | #include "llvm/MC/MCInstrDesc.h" |
23 | | #include "llvm/MC/MCParser/MCAsmLexer.h" |
24 | | #include "llvm/MC/MCParser/MCParsedAsmOperand.h" |
25 | | #include "llvm/MC/MCParser/MCTargetAsmParser.h" |
26 | | #include "llvm/MC/MCStreamer.h" |
27 | | #include "llvm/MC/MCSubtargetInfo.h" |
28 | | #include "llvm/MC/MCSymbol.h" |
29 | | #include "llvm/Support/Debug.h" |
30 | | #include "llvm/Support/MathExtras.h" |
31 | | #include "llvm/Support/SourceMgr.h" |
32 | | #include "llvm/Support/TargetRegistry.h" |
33 | | #include "llvm/Support/raw_ostream.h" |
34 | | #include <memory> |
35 | | |
36 | | #include "keystone/mips.h" |
37 | | |
38 | | using namespace llvm_ks; |
39 | | |
40 | | #define DEBUG_TYPE "mips-asm-parser" |
41 | | |
42 | | namespace llvm_ks { |
43 | | class MCInstrInfo; |
44 | | } |
45 | | |
46 | | namespace { |
47 | | class MipsAssemblerOptions { |
48 | | public: |
49 | | MipsAssemblerOptions(const FeatureBitset &Features_) : |
50 | 13.6k | ATReg(1), Reorder(true), Macro(true), Features(Features_) {} |
51 | | |
52 | 11 | MipsAssemblerOptions(const MipsAssemblerOptions *Opts) { |
53 | 11 | ATReg = Opts->getATRegIndex(); |
54 | 11 | Reorder = Opts->isReorder(); |
55 | 11 | Macro = Opts->isMacro(); |
56 | 11 | Features = Opts->getFeatures(); |
57 | 11 | } |
58 | | |
59 | 6.30k | unsigned getATRegIndex() const { return ATReg; } |
60 | 413 | bool setATRegIndex(unsigned Reg) { |
61 | 413 | if (Reg > 31) |
62 | 132 | return false; |
63 | | |
64 | 281 | ATReg = Reg; |
65 | 281 | return true; |
66 | 413 | } |
67 | | |
68 | 12.1k | bool isReorder() const { return Reorder; } |
69 | 69 | void setReorder() { Reorder = true; } |
70 | 106 | void setNoReorder() { Reorder = false; } |
71 | | |
72 | 838 | bool isMacro() const { return Macro; } |
73 | 31 | void setMacro() { Macro = true; } |
74 | 0 | void setNoMacro() { Macro = false; } |
75 | | |
76 | 1.05k | const FeatureBitset &getFeatures() const { return Features; } |
77 | 9.80k | void setFeatures(const FeatureBitset &Features_) { Features = Features_; } |
78 | | |
79 | | // Set of features that are either architecture features or referenced |
80 | | // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6). |
81 | | // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]). |
82 | | // The reason we need this mask is explained in the selectArch function. |
83 | | // FIXME: Ideally we would like TableGen to generate this information. |
84 | | static const FeatureBitset AllArchRelatedMask; |
85 | | |
86 | | private: |
87 | | unsigned ATReg; |
88 | | bool Reorder; |
89 | | bool Macro; |
90 | | FeatureBitset Features; |
91 | | }; |
92 | | } |
93 | | |
94 | | const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = { |
95 | | Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3, |
96 | | Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4, |
97 | | Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5, |
98 | | Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2, |
99 | | Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6, |
100 | | Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3, |
101 | | Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips, |
102 | | Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008 |
103 | | }; |
104 | | |
105 | | namespace { |
106 | | class MipsAsmParser : public MCTargetAsmParser { |
107 | 0 | MipsTargetStreamer &getTargetStreamer() { |
108 | 0 | MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer(); |
109 | 0 | return static_cast<MipsTargetStreamer &>(TS); |
110 | 0 | } |
111 | | |
112 | | MipsABIInfo ABI; |
113 | | SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions; |
114 | | MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a |
115 | | // nullptr, which indicates that no function is currently |
116 | | // selected. This usually happens after an '.end func' |
117 | | // directive. |
118 | | bool IsLittleEndian; |
119 | | bool IsPicEnabled; |
120 | | bool IsCpRestoreSet; |
121 | | int CpRestoreOffset; |
122 | | unsigned CpSaveLocation; |
123 | | /// If true, then CpSaveLocation is a register, otherwise it's an offset. |
124 | | bool CpSaveLocationIsRegister; |
125 | | |
126 | | // Print a warning along with its fix-it message at the given range. |
127 | | void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg, |
128 | | SMRange Range, bool ShowColors = true); |
129 | | |
130 | | #define GET_ASSEMBLER_HEADER |
131 | | #include "MipsGenAsmMatcher.inc" |
132 | | |
133 | | unsigned checkTargetMatchPredicate(MCInst &Inst) override; |
134 | | |
135 | | bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, |
136 | | OperandVector &Operands, MCStreamer &Out, |
137 | | uint64_t &ErrorInfo, |
138 | | bool MatchingInlineAsm, unsigned int &ErrorCode, uint64_t &Address) override; |
139 | | |
140 | | /// Parse a register as used in CFI directives |
141 | | bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc, unsigned int &ErrorCode) override; |
142 | | |
143 | | bool parseParenSuffix(StringRef Name, OperandVector &Operands, unsigned int &ErrorCode); |
144 | | |
145 | | bool parseBracketSuffix(StringRef Name, OperandVector &Operands, unsigned int &ErrorCode); |
146 | | |
147 | | bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, |
148 | | SMLoc NameLoc, OperandVector &Operands, unsigned int &ErrorCode) override; |
149 | | |
150 | | bool ParseDirective(AsmToken DirectiveID) override; |
151 | | |
152 | | OperandMatchResultTy parseMemOperand(OperandVector &Operands); |
153 | | OperandMatchResultTy |
154 | | matchAnyRegisterNameWithoutDollar(OperandVector &Operands, |
155 | | StringRef Identifier, SMLoc S); |
156 | | OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands, |
157 | | SMLoc S); |
158 | | OperandMatchResultTy parseAnyRegister(OperandVector &Operands); |
159 | | OperandMatchResultTy parseImm(OperandVector &Operands); |
160 | | OperandMatchResultTy parseJumpTarget(OperandVector &Operands); |
161 | | OperandMatchResultTy parseInvNum(OperandVector &Operands); |
162 | | OperandMatchResultTy parseRegisterPair(OperandVector &Operands); |
163 | | OperandMatchResultTy parseMovePRegPair(OperandVector &Operands); |
164 | | OperandMatchResultTy parseRegisterList(OperandVector &Operands); |
165 | | |
166 | | bool searchSymbolAlias(OperandVector &Operands); |
167 | | |
168 | | bool parseOperand(OperandVector &, StringRef Mnemonic, unsigned int &ErrorCode); |
169 | | |
170 | | enum MacroExpanderResultTy { |
171 | | MER_NotAMacro, |
172 | | MER_Success, |
173 | | MER_Fail, |
174 | | }; |
175 | | |
176 | | // Expands assembly pseudo instructions. |
177 | | MacroExpanderResultTy |
178 | | tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, |
179 | | SmallVectorImpl<MCInst> &Instructions); |
180 | | |
181 | | bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, |
182 | | SmallVectorImpl<MCInst> &Instructions); |
183 | | |
184 | | bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg, |
185 | | bool Is32BitImm, bool IsAddress, SMLoc IDLoc, |
186 | | SmallVectorImpl<MCInst> &Instructions); |
187 | | |
188 | | bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg, |
189 | | unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc, |
190 | | SmallVectorImpl<MCInst> &Instructions); |
191 | | |
192 | | bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc, |
193 | | SmallVectorImpl<MCInst> &Instructions); |
194 | | |
195 | | bool expandLoadAddress(unsigned DstReg, unsigned BaseReg, |
196 | | const MCOperand &Offset, bool Is32BitAddress, |
197 | | SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions); |
198 | | |
199 | | bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, |
200 | | SmallVectorImpl<MCInst> &Instructions); |
201 | | |
202 | | void expandMemInst(MCInst &Inst, SMLoc IDLoc, |
203 | | SmallVectorImpl<MCInst> &Instructions, bool isLoad, |
204 | | bool isImmOpnd); |
205 | | |
206 | | bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, |
207 | | SmallVectorImpl<MCInst> &Instructions); |
208 | | |
209 | | bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, |
210 | | SmallVectorImpl<MCInst> &Instructions); |
211 | | |
212 | | bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, |
213 | | SmallVectorImpl<MCInst> &Instructions); |
214 | | |
215 | | bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, |
216 | | SmallVectorImpl<MCInst> &Instructions); |
217 | | |
218 | | bool expandDiv(MCInst &Inst, SMLoc IDLoc, |
219 | | SmallVectorImpl<MCInst> &Instructions, const bool IsMips64, |
220 | | const bool Signed); |
221 | | |
222 | | bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, |
223 | | SmallVectorImpl<MCInst> &Instructions); |
224 | | |
225 | | bool expandUlw(MCInst &Inst, SMLoc IDLoc, |
226 | | SmallVectorImpl<MCInst> &Instructions); |
227 | | |
228 | | bool expandRotation(MCInst &Inst, SMLoc IDLoc, |
229 | | SmallVectorImpl<MCInst> &Instructions); |
230 | | bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, |
231 | | SmallVectorImpl<MCInst> &Instructions); |
232 | | bool expandDRotation(MCInst &Inst, SMLoc IDLoc, |
233 | | SmallVectorImpl<MCInst> &Instructions); |
234 | | bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, |
235 | | SmallVectorImpl<MCInst> &Instructions); |
236 | | |
237 | | bool expandAbs(MCInst &Inst, SMLoc IDLoc, |
238 | | SmallVectorImpl<MCInst> &Instructions); |
239 | | |
240 | | void createNop(bool hasShortDelaySlot, SMLoc IDLoc, |
241 | | SmallVectorImpl<MCInst> &Instructions); |
242 | | |
243 | | void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg, |
244 | | bool Is64Bit, SmallVectorImpl<MCInst> &Instructions); |
245 | | |
246 | | void createCpRestoreMemOp(bool IsLoad, int StackOffset, SMLoc IDLoc, |
247 | | SmallVectorImpl<MCInst> &Instructions); |
248 | | |
249 | | bool reportParseError(Twine ErrorMsg); |
250 | | bool reportParseError(SMLoc Loc, Twine ErrorMsg); |
251 | | |
252 | | bool parseMemOffset(const MCExpr *&Res, bool isParenExpr); |
253 | | bool parseRelocOperand(const MCExpr *&Res); |
254 | | |
255 | | const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr); |
256 | | |
257 | | bool isEvaluated(const MCExpr *Expr); |
258 | | bool parseSetMips0Directive(); |
259 | | bool parseSetArchDirective(); |
260 | | bool parseSetFeature(uint64_t Feature); |
261 | | bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup. |
262 | | bool parseDirectiveCpLoad(SMLoc Loc); |
263 | | bool parseDirectiveCpRestore(SMLoc Loc); |
264 | | bool parseDirectiveCPSetup(); |
265 | | bool parseDirectiveCPReturn(); |
266 | | bool parseDirectiveNaN(); |
267 | | bool parseDirectiveSet(); |
268 | | bool parseDirectiveOption(); |
269 | | bool parseInsnDirective(); |
270 | | |
271 | | bool parseSetAtDirective(); |
272 | | bool parseSetNoAtDirective(); |
273 | | bool parseSetMacroDirective(); |
274 | | bool parseSetNoMacroDirective(); |
275 | | bool parseSetMsaDirective(); |
276 | | bool parseSetNoMsaDirective(); |
277 | | bool parseSetNoDspDirective(); |
278 | | bool parseSetReorderDirective(); |
279 | | bool parseSetNoReorderDirective(); |
280 | | bool parseSetMips16Directive(); |
281 | | bool parseSetNoMips16Directive(); |
282 | | bool parseSetFpDirective(); |
283 | | bool parseSetOddSPRegDirective(); |
284 | | bool parseSetNoOddSPRegDirective(); |
285 | | bool parseSetPopDirective(); |
286 | | bool parseSetPushDirective(); |
287 | | bool parseSetSoftFloatDirective(); |
288 | | bool parseSetHardFloatDirective(); |
289 | | |
290 | | bool parseSetAssignment(); |
291 | | |
292 | | bool parseDataDirective(unsigned Size, SMLoc L); |
293 | | bool parseDirectiveGpWord(); |
294 | | bool parseDirectiveGpDWord(); |
295 | | bool parseDirectiveModule(); |
296 | | bool parseDirectiveModuleFP(); |
297 | | bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI, |
298 | | StringRef Directive); |
299 | | |
300 | | bool parseInternalDirectiveReallowModule(); |
301 | | |
302 | | MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol); |
303 | | |
304 | | bool eatComma(StringRef ErrorStr); |
305 | | |
306 | | int matchCPURegisterName(StringRef Symbol); |
307 | | |
308 | | int matchHWRegsRegisterName(StringRef Symbol); |
309 | | |
310 | | int matchFPURegisterName(StringRef Name); |
311 | | |
312 | | int matchFCCRegisterName(StringRef Name); |
313 | | |
314 | | int matchACRegisterName(StringRef Name); |
315 | | |
316 | | int matchMSA128RegisterName(StringRef Name); |
317 | | |
318 | | int matchMSA128CtrlRegisterName(StringRef Name); |
319 | | |
320 | | unsigned getReg(int RC, int RegNo); |
321 | | |
322 | | /// Returns the internal register number for the current AT. Also checks if |
323 | | /// the current AT is unavailable (set to $0) and gives an error if it is. |
324 | | /// This should be used in pseudo-instruction expansions which need AT. |
325 | | unsigned getATReg(SMLoc Loc); |
326 | | |
327 | | bool processInstruction(MCInst &Inst, SMLoc IDLoc, |
328 | | SmallVectorImpl<MCInst> &Instructions, |
329 | | unsigned int &KsError); |
330 | | |
331 | | // Helper function that checks if the value of a vector index is within the |
332 | | // boundaries of accepted values for each RegisterKind |
333 | | // Example: INSERT.B $w0[n], $1 => 16 > n >= 0 |
334 | | bool validateMSAIndex(int Val, int RegKind); |
335 | | |
336 | | // Selects a new architecture by updating the FeatureBits with the necessary |
337 | | // info including implied dependencies. |
338 | | // Internally, it clears all the feature bits related to *any* architecture |
339 | | // and selects the new one using the ToggleFeature functionality of the |
340 | | // MCSubtargetInfo object that handles implied dependencies. The reason we |
341 | | // clear all the arch related bits manually is because ToggleFeature only |
342 | | // clears the features that imply the feature being cleared and not the |
343 | | // features implied by the feature being cleared. This is easier to see |
344 | | // with an example: |
345 | | // -------------------------------------------------- |
346 | | // | Feature | Implies | |
347 | | // | -------------------------------------------------| |
348 | | // | FeatureMips1 | None | |
349 | | // | FeatureMips2 | FeatureMips1 | |
350 | | // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 | |
351 | | // | FeatureMips4 | FeatureMips3 | |
352 | | // | ... | | |
353 | | // -------------------------------------------------- |
354 | | // |
355 | | // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 | |
356 | | // FeatureMipsGP64 | FeatureMips1) |
357 | | // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4). |
358 | 2.76k | void selectArch(StringRef ArchFeature) { |
359 | 2.76k | MCSubtargetInfo &STI = copySTI(); |
360 | 2.76k | FeatureBitset FeatureBits = STI.getFeatureBits(); |
361 | 2.76k | FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask; |
362 | 2.76k | STI.setFeatureBits(FeatureBits); |
363 | 2.76k | setAvailableFeatures( |
364 | 2.76k | ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature))); |
365 | 2.76k | AssemblerOptions.back()->setFeatures(STI.getFeatureBits()); |
366 | 2.76k | } |
367 | | |
368 | 4.14k | void setFeatureBits(uint64_t Feature, StringRef FeatureString) { |
369 | 4.14k | if (!(getSTI().getFeatureBits()[Feature])) { |
370 | 3.40k | MCSubtargetInfo &STI = copySTI(); |
371 | 3.40k | setAvailableFeatures( |
372 | 3.40k | ComputeAvailableFeatures(STI.ToggleFeature(FeatureString))); |
373 | 3.40k | AssemblerOptions.back()->setFeatures(STI.getFeatureBits()); |
374 | 3.40k | } |
375 | 4.14k | } |
376 | | |
377 | 6.97k | void clearFeatureBits(uint64_t Feature, StringRef FeatureString) { |
378 | 6.97k | if (getSTI().getFeatureBits()[Feature]) { |
379 | 3.28k | MCSubtargetInfo &STI = copySTI(); |
380 | 3.28k | setAvailableFeatures( |
381 | 3.28k | ComputeAvailableFeatures(STI.ToggleFeature(FeatureString))); |
382 | 3.28k | AssemblerOptions.back()->setFeatures(STI.getFeatureBits()); |
383 | 3.28k | } |
384 | 6.97k | } |
385 | | |
386 | 0 | void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) { |
387 | 0 | setFeatureBits(Feature, FeatureString); |
388 | 0 | AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits()); |
389 | 0 | } |
390 | | |
391 | 4 | void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) { |
392 | 4 | clearFeatureBits(Feature, FeatureString); |
393 | 4 | AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits()); |
394 | 4 | } |
395 | | |
396 | | public: |
397 | | enum MipsMatchResultTy { |
398 | | Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY, |
399 | | #define GET_OPERAND_DIAGNOSTIC_TYPES |
400 | | #include "MipsGenAsmMatcher.inc" |
401 | | #undef GET_OPERAND_DIAGNOSTIC_TYPES |
402 | | }; |
403 | | |
404 | | MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser, |
405 | | const MCInstrInfo &MII, const MCTargetOptions &Options) |
406 | 6.81k | : MCTargetAsmParser(Options, sti), |
407 | 6.81k | ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()), |
408 | 6.81k | sti.getCPU(), Options)) { |
409 | 6.81k | MCAsmParserExtension::Initialize(parser); |
410 | | |
411 | 6.81k | parser.addAliasForDirective(".asciiz", ".asciz"); |
412 | | |
413 | | // Initialize the set of available features. |
414 | 6.81k | setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits())); |
415 | | |
416 | | // Remember the initial assembler options. The user can not modify these. |
417 | 6.81k | AssemblerOptions.push_back( |
418 | 6.81k | llvm_ks::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits())); |
419 | | |
420 | | // Create an assembler options environment for the user to modify. |
421 | 6.81k | AssemblerOptions.push_back( |
422 | 6.81k | llvm_ks::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits())); |
423 | | |
424 | | //getTargetStreamer().updateABIInfo(*this); |
425 | | |
426 | | //if (!isABI_O32() && !useOddSPReg() != 0) |
427 | | // report_fatal_error("-mno-odd-spreg requires the O32 ABI"); |
428 | | |
429 | 6.81k | CurrentFn = nullptr; |
430 | | |
431 | | //IsPicEnabled = |
432 | | // (getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_); |
433 | | |
434 | 6.81k | IsCpRestoreSet = false; |
435 | 6.81k | CpRestoreOffset = -1; |
436 | | |
437 | 6.81k | Triple TheTriple(sti.getTargetTriple()); |
438 | 6.81k | if ((TheTriple.getArch() == Triple::mips) || |
439 | 6.05k | (TheTriple.getArch() == Triple::mips64)) |
440 | 919 | IsLittleEndian = false; |
441 | 5.89k | else |
442 | 5.89k | IsLittleEndian = true; |
443 | 6.81k | } |
444 | | |
445 | | /// True if all of $fcc0 - $fcc7 exist for the current ISA. |
446 | 2 | bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); } |
447 | | |
448 | 1.66k | bool isGP64bit() const { |
449 | 1.66k | return getSTI().getFeatureBits()[Mips::FeatureGP64Bit]; |
450 | 1.66k | } |
451 | 0 | bool isFP64bit() const { |
452 | 0 | return getSTI().getFeatureBits()[Mips::FeatureFP64Bit]; |
453 | 0 | } |
454 | 876 | const MipsABIInfo &getABI() const { return ABI; } |
455 | 15.2k | bool isABI_N32() const { return ABI.IsN32(); } |
456 | 15.2k | bool isABI_N64() const { return ABI.IsN64(); } |
457 | 133 | bool isABI_O32() const { return ABI.IsO32(); } |
458 | 0 | bool isABI_FPXX() const { |
459 | 0 | return getSTI().getFeatureBits()[Mips::FeatureFPXX]; |
460 | 0 | } |
461 | | |
462 | 12 | bool useOddSPReg() const { |
463 | 12 | return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]); |
464 | 12 | } |
465 | | |
466 | 14.4k | bool inMicroMipsMode() const { |
467 | 14.4k | return getSTI().getFeatureBits()[Mips::FeatureMicroMips]; |
468 | 14.4k | } |
469 | 0 | bool hasMips1() const { |
470 | 0 | return getSTI().getFeatureBits()[Mips::FeatureMips1]; |
471 | 0 | } |
472 | 0 | bool hasMips2() const { |
473 | 0 | return getSTI().getFeatureBits()[Mips::FeatureMips2]; |
474 | 0 | } |
475 | 33 | bool hasMips3() const { |
476 | 33 | return getSTI().getFeatureBits()[Mips::FeatureMips3]; |
477 | 33 | } |
478 | 2 | bool hasMips4() const { |
479 | 2 | return getSTI().getFeatureBits()[Mips::FeatureMips4]; |
480 | 2 | } |
481 | 0 | bool hasMips5() const { |
482 | 0 | return getSTI().getFeatureBits()[Mips::FeatureMips5]; |
483 | 0 | } |
484 | 17 | bool hasMips32() const { |
485 | 17 | return getSTI().getFeatureBits()[Mips::FeatureMips32]; |
486 | 17 | } |
487 | 2 | bool hasMips64() const { |
488 | 2 | return getSTI().getFeatureBits()[Mips::FeatureMips64]; |
489 | 2 | } |
490 | 18 | bool hasMips32r2() const { |
491 | 18 | return getSTI().getFeatureBits()[Mips::FeatureMips32r2]; |
492 | 18 | } |
493 | 2 | bool hasMips64r2() const { |
494 | 2 | return getSTI().getFeatureBits()[Mips::FeatureMips64r2]; |
495 | 2 | } |
496 | 0 | bool hasMips32r3() const { |
497 | 0 | return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]); |
498 | 0 | } |
499 | 0 | bool hasMips64r3() const { |
500 | 0 | return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]); |
501 | 0 | } |
502 | 0 | bool hasMips32r5() const { |
503 | 0 | return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]); |
504 | 0 | } |
505 | 0 | bool hasMips64r5() const { |
506 | 0 | return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]); |
507 | 0 | } |
508 | 14.8k | bool hasMips32r6() const { |
509 | 14.8k | return getSTI().getFeatureBits()[Mips::FeatureMips32r6]; |
510 | 14.8k | } |
511 | 0 | bool hasMips64r6() const { |
512 | 0 | return getSTI().getFeatureBits()[Mips::FeatureMips64r6]; |
513 | 0 | } |
514 | | |
515 | 0 | bool hasDSP() const { |
516 | 0 | return getSTI().getFeatureBits()[Mips::FeatureDSP]; |
517 | 0 | } |
518 | 0 | bool hasDSPR2() const { |
519 | 0 | return getSTI().getFeatureBits()[Mips::FeatureDSPR2]; |
520 | 0 | } |
521 | 0 | bool hasDSPR3() const { |
522 | 0 | return getSTI().getFeatureBits()[Mips::FeatureDSPR3]; |
523 | 0 | } |
524 | 0 | bool hasMSA() const { |
525 | 0 | return getSTI().getFeatureBits()[Mips::FeatureMSA]; |
526 | 0 | } |
527 | 14.8k | bool hasCnMips() const { |
528 | 14.8k | return (getSTI().getFeatureBits()[Mips::FeatureCnMips]); |
529 | 14.8k | } |
530 | | |
531 | 474 | bool inPicMode() { |
532 | 474 | return IsPicEnabled; |
533 | 474 | } |
534 | | |
535 | 616 | bool inMips16Mode() const { |
536 | 616 | return getSTI().getFeatureBits()[Mips::FeatureMips16]; |
537 | 616 | } |
538 | | |
539 | 0 | bool useTraps() const { |
540 | 0 | return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV]; |
541 | 0 | } |
542 | | |
543 | 0 | bool useSoftFloat() const { |
544 | 0 | return getSTI().getFeatureBits()[Mips::FeatureSoftFloat]; |
545 | 0 | } |
546 | | |
547 | | /// Warn if RegIndex is the same as the current AT. |
548 | | void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc); |
549 | | |
550 | | void warnIfNoMacro(SMLoc Loc); |
551 | | |
552 | 0 | bool isLittle() const { return IsLittleEndian; } |
553 | | }; |
554 | | } |
555 | | |
556 | | namespace { |
557 | | |
558 | | /// MipsOperand - Instances of this class represent a parsed Mips machine |
559 | | /// instruction. |
560 | | class MipsOperand : public MCParsedAsmOperand { |
561 | | public: |
562 | | /// Broad categories of register classes |
563 | | /// The exact class is finalized by the render method. |
564 | | enum RegKind { |
565 | | RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit()) |
566 | | RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and |
567 | | /// isFP64bit()) |
568 | | RegKind_FCC = 4, /// FCC |
569 | | RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which) |
570 | | RegKind_MSACtrl = 16, /// MSA control registers |
571 | | RegKind_COP2 = 32, /// COP2 |
572 | | RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on |
573 | | /// context). |
574 | | RegKind_CCR = 128, /// CCR |
575 | | RegKind_HWRegs = 256, /// HWRegs |
576 | | RegKind_COP3 = 512, /// COP3 |
577 | | RegKind_COP0 = 1024, /// COP0 |
578 | | /// Potentially any (e.g. $1) |
579 | | RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 | |
580 | | RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC | |
581 | | RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0 |
582 | | }; |
583 | | |
584 | | private: |
585 | | enum KindTy { |
586 | | k_Immediate, /// An immediate (possibly involving symbol references) |
587 | | k_Memory, /// Base + Offset Memory Address |
588 | | k_PhysRegister, /// A physical register from the Mips namespace |
589 | | k_RegisterIndex, /// A register index in one or more RegKind. |
590 | | k_Token, /// A simple token |
591 | | k_RegList, /// A physical register list |
592 | | k_RegPair /// A pair of physical register |
593 | | } Kind; |
594 | | |
595 | | public: |
596 | | MipsOperand(KindTy K, MipsAsmParser &Parser) |
597 | 71.8k | : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {} |
598 | | |
599 | | private: |
600 | | /// For diagnostics, and checking the assembler temporary |
601 | | MipsAsmParser &AsmParser; |
602 | | |
603 | | struct Token { |
604 | | const char *Data; |
605 | | unsigned Length; |
606 | | }; |
607 | | |
608 | | struct PhysRegOp { |
609 | | unsigned Num; /// Register Number |
610 | | }; |
611 | | |
612 | | struct RegIdxOp { |
613 | | unsigned Index; /// Index into the register class |
614 | | RegKind Kind; /// Bitfield of the kinds it could possibly be |
615 | | const MCRegisterInfo *RegInfo; |
616 | | }; |
617 | | |
618 | | struct ImmOp { |
619 | | const MCExpr *Val; |
620 | | }; |
621 | | |
622 | | struct MemOp { |
623 | | MipsOperand *Base; |
624 | | const MCExpr *Off; |
625 | | }; |
626 | | |
627 | | struct RegListOp { |
628 | | SmallVector<unsigned, 10> *List; |
629 | | }; |
630 | | |
631 | | union { |
632 | | struct Token Tok; |
633 | | struct PhysRegOp PhysReg; |
634 | | struct RegIdxOp RegIdx; |
635 | | struct ImmOp Imm; |
636 | | struct MemOp Mem; |
637 | | struct RegListOp RegList; |
638 | | }; |
639 | | |
640 | | SMLoc StartLoc, EndLoc; |
641 | | |
642 | | /// Internal constructor for register kinds |
643 | | static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind, |
644 | | const MCRegisterInfo *RegInfo, |
645 | | SMLoc S, SMLoc E, |
646 | 17.8k | MipsAsmParser &Parser) { |
647 | 17.8k | auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser); |
648 | 17.8k | Op->RegIdx.Index = Index; |
649 | 17.8k | Op->RegIdx.RegInfo = RegInfo; |
650 | 17.8k | Op->RegIdx.Kind = RegKind; |
651 | 17.8k | Op->StartLoc = S; |
652 | 17.8k | Op->EndLoc = E; |
653 | 17.8k | return Op; |
654 | 17.8k | } |
655 | | |
656 | | public: |
657 | | /// Coerce the register to GPR32 and return the real register for the current |
658 | | /// target. |
659 | 5.86k | unsigned getGPR32Reg() const { |
660 | 5.86k | assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!"); |
661 | 5.86k | AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc); |
662 | 5.86k | unsigned ClassID = Mips::GPR32RegClassID; |
663 | 5.86k | return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); |
664 | 5.86k | } |
665 | | |
666 | | /// Coerce the register to GPR32 and return the real register for the current |
667 | | /// target. |
668 | 0 | unsigned getGPRMM16Reg() const { |
669 | 0 | assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!"); |
670 | 0 | unsigned ClassID = Mips::GPR32RegClassID; |
671 | 0 | return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); |
672 | 0 | } |
673 | | |
674 | | /// Coerce the register to GPR64 and return the real register for the current |
675 | | /// target. |
676 | 749 | unsigned getGPR64Reg() const { |
677 | 749 | assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!"); |
678 | 749 | unsigned ClassID = Mips::GPR64RegClassID; |
679 | 749 | return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); |
680 | 749 | } |
681 | | |
682 | | private: |
683 | | /// Coerce the register to AFGR64 and return the real register for the current |
684 | | /// target. |
685 | 0 | unsigned getAFGR64Reg() const { |
686 | 0 | assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!"); |
687 | 0 | if (RegIdx.Index % 2 != 0) { |
688 | | // AsmParser.Warning(StartLoc, "Float register should be even."); |
689 | 0 | } |
690 | 0 | return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID) |
691 | 0 | .getRegister(RegIdx.Index / 2); |
692 | 0 | } |
693 | | |
694 | | /// Coerce the register to FGR64 and return the real register for the current |
695 | | /// target. |
696 | 6 | unsigned getFGR64Reg() const { |
697 | 6 | assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!"); |
698 | 6 | return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID) |
699 | 6 | .getRegister(RegIdx.Index); |
700 | 6 | } |
701 | | |
702 | | /// Coerce the register to FGR32 and return the real register for the current |
703 | | /// target. |
704 | 12 | unsigned getFGR32Reg() const { |
705 | 12 | assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!"); |
706 | 12 | return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID) |
707 | 12 | .getRegister(RegIdx.Index); |
708 | 12 | } |
709 | | |
710 | | /// Coerce the register to FGRH32 and return the real register for the current |
711 | | /// target. |
712 | 0 | unsigned getFGRH32Reg() const { |
713 | 0 | assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!"); |
714 | 0 | return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID) |
715 | 0 | .getRegister(RegIdx.Index); |
716 | 0 | } |
717 | | |
718 | | /// Coerce the register to FCC and return the real register for the current |
719 | | /// target. |
720 | 2 | unsigned getFCCReg() const { |
721 | 2 | assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!"); |
722 | 2 | return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID) |
723 | 2 | .getRegister(RegIdx.Index); |
724 | 2 | } |
725 | | |
726 | | /// Coerce the register to MSA128 and return the real register for the current |
727 | | /// target. |
728 | 0 | unsigned getMSA128Reg() const { |
729 | 0 | assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!"); |
730 | | // It doesn't matter which of the MSA128[BHWD] classes we use. They are all |
731 | | // identical |
732 | 0 | unsigned ClassID = Mips::MSA128BRegClassID; |
733 | 0 | return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); |
734 | 0 | } |
735 | | |
736 | | /// Coerce the register to MSACtrl and return the real register for the |
737 | | /// current target. |
738 | 0 | unsigned getMSACtrlReg() const { |
739 | 0 | assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!"); |
740 | 0 | unsigned ClassID = Mips::MSACtrlRegClassID; |
741 | 0 | return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); |
742 | 0 | } |
743 | | |
744 | | /// Coerce the register to COP0 and return the real register for the |
745 | | /// current target. |
746 | 0 | unsigned getCOP0Reg() const { |
747 | 0 | assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!"); |
748 | 0 | unsigned ClassID = Mips::COP0RegClassID; |
749 | 0 | return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); |
750 | 0 | } |
751 | | |
752 | | /// Coerce the register to COP2 and return the real register for the |
753 | | /// current target. |
754 | 167 | unsigned getCOP2Reg() const { |
755 | 167 | assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!"); |
756 | 167 | unsigned ClassID = Mips::COP2RegClassID; |
757 | 167 | return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); |
758 | 167 | } |
759 | | |
760 | | /// Coerce the register to COP3 and return the real register for the |
761 | | /// current target. |
762 | 30 | unsigned getCOP3Reg() const { |
763 | 30 | assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!"); |
764 | 30 | unsigned ClassID = Mips::COP3RegClassID; |
765 | 30 | return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); |
766 | 30 | } |
767 | | |
768 | | /// Coerce the register to ACC64DSP and return the real register for the |
769 | | /// current target. |
770 | 0 | unsigned getACC64DSPReg() const { |
771 | 0 | assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!"); |
772 | 0 | unsigned ClassID = Mips::ACC64DSPRegClassID; |
773 | 0 | return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); |
774 | 0 | } |
775 | | |
776 | | /// Coerce the register to HI32DSP and return the real register for the |
777 | | /// current target. |
778 | 0 | unsigned getHI32DSPReg() const { |
779 | 0 | assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!"); |
780 | 0 | unsigned ClassID = Mips::HI32DSPRegClassID; |
781 | 0 | return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); |
782 | 0 | } |
783 | | |
784 | | /// Coerce the register to LO32DSP and return the real register for the |
785 | | /// current target. |
786 | 0 | unsigned getLO32DSPReg() const { |
787 | 0 | assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!"); |
788 | 0 | unsigned ClassID = Mips::LO32DSPRegClassID; |
789 | 0 | return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); |
790 | 0 | } |
791 | | |
792 | | /// Coerce the register to CCR and return the real register for the |
793 | | /// current target. |
794 | 0 | unsigned getCCRReg() const { |
795 | 0 | assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!"); |
796 | 0 | unsigned ClassID = Mips::CCRRegClassID; |
797 | 0 | return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); |
798 | 0 | } |
799 | | |
800 | | /// Coerce the register to HWRegs and return the real register for the |
801 | | /// current target. |
802 | 0 | unsigned getHWRegsReg() const { |
803 | 0 | assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!"); |
804 | 0 | unsigned ClassID = Mips::HWRegsRegClassID; |
805 | 0 | return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); |
806 | 0 | } |
807 | | |
808 | | public: |
809 | 13.5k | void addExpr(MCInst &Inst, const MCExpr *Expr) const { |
810 | | // Add as immediate when possible. Null MCExpr = 0. |
811 | 13.5k | if (!Expr) |
812 | 0 | Inst.addOperand(MCOperand::createImm(0)); |
813 | 13.5k | else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr)) |
814 | 2.86k | Inst.addOperand(MCOperand::createImm(CE->getValue())); |
815 | 10.6k | else |
816 | 10.6k | Inst.addOperand(MCOperand::createExpr(Expr)); |
817 | 13.5k | } |
818 | | |
819 | 0 | void addRegOperands(MCInst &Inst, unsigned N) const { |
820 | 0 | llvm_unreachable("Use a custom parser instead"); |
821 | 0 | } |
822 | | |
823 | | /// Render the operand to an MCInst as a GPR32 |
824 | | /// Asserts if the wrong number of operands are requested, or the operand |
825 | | /// is not a k_RegisterIndex compatible with RegKind_GPR |
826 | 5.37k | void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const { |
827 | 5.37k | assert(N == 1 && "Invalid number of operands!"); |
828 | 5.37k | Inst.addOperand(MCOperand::createReg(getGPR32Reg())); |
829 | 5.37k | } |
830 | | |
831 | 0 | void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const { |
832 | 0 | assert(N == 1 && "Invalid number of operands!"); |
833 | 0 | Inst.addOperand(MCOperand::createReg(getGPRMM16Reg())); |
834 | 0 | } |
835 | | |
836 | 0 | void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const { |
837 | 0 | assert(N == 1 && "Invalid number of operands!"); |
838 | 0 | Inst.addOperand(MCOperand::createReg(getGPRMM16Reg())); |
839 | 0 | } |
840 | | |
841 | 0 | void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const { |
842 | 0 | assert(N == 1 && "Invalid number of operands!"); |
843 | 0 | Inst.addOperand(MCOperand::createReg(getGPRMM16Reg())); |
844 | 0 | } |
845 | | |
846 | | /// Render the operand to an MCInst as a GPR64 |
847 | | /// Asserts if the wrong number of operands are requested, or the operand |
848 | | /// is not a k_RegisterIndex compatible with RegKind_GPR |
849 | 36 | void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const { |
850 | 36 | assert(N == 1 && "Invalid number of operands!"); |
851 | 36 | Inst.addOperand(MCOperand::createReg(getGPR64Reg())); |
852 | 36 | } |
853 | | |
854 | 0 | void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const { |
855 | 0 | assert(N == 1 && "Invalid number of operands!"); |
856 | 0 | Inst.addOperand(MCOperand::createReg(getAFGR64Reg())); |
857 | 0 | } |
858 | | |
859 | 6 | void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const { |
860 | 6 | assert(N == 1 && "Invalid number of operands!"); |
861 | 6 | Inst.addOperand(MCOperand::createReg(getFGR64Reg())); |
862 | 6 | } |
863 | | |
864 | 12 | void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const { |
865 | 12 | assert(N == 1 && "Invalid number of operands!"); |
866 | 12 | Inst.addOperand(MCOperand::createReg(getFGR32Reg())); |
867 | | // FIXME: We ought to do this for -integrated-as without -via-file-asm too. |
868 | 12 | if (!AsmParser.useOddSPReg() && RegIdx.Index & 1) |
869 | 0 | AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU " |
870 | 0 | "registers"); |
871 | 12 | } |
872 | | |
873 | 0 | void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const { |
874 | 0 | assert(N == 1 && "Invalid number of operands!"); |
875 | 0 | Inst.addOperand(MCOperand::createReg(getFGRH32Reg())); |
876 | 0 | } |
877 | | |
878 | 2 | void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const { |
879 | 2 | assert(N == 1 && "Invalid number of operands!"); |
880 | 2 | Inst.addOperand(MCOperand::createReg(getFCCReg())); |
881 | 2 | } |
882 | | |
883 | 0 | void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const { |
884 | 0 | assert(N == 1 && "Invalid number of operands!"); |
885 | 0 | Inst.addOperand(MCOperand::createReg(getMSA128Reg())); |
886 | 0 | } |
887 | | |
888 | 0 | void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const { |
889 | 0 | assert(N == 1 && "Invalid number of operands!"); |
890 | 0 | Inst.addOperand(MCOperand::createReg(getMSACtrlReg())); |
891 | 0 | } |
892 | | |
893 | 0 | void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const { |
894 | 0 | assert(N == 1 && "Invalid number of operands!"); |
895 | 0 | Inst.addOperand(MCOperand::createReg(getCOP0Reg())); |
896 | 0 | } |
897 | | |
898 | 167 | void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const { |
899 | 167 | assert(N == 1 && "Invalid number of operands!"); |
900 | 167 | Inst.addOperand(MCOperand::createReg(getCOP2Reg())); |
901 | 167 | } |
902 | | |
903 | 30 | void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const { |
904 | 30 | assert(N == 1 && "Invalid number of operands!"); |
905 | 30 | Inst.addOperand(MCOperand::createReg(getCOP3Reg())); |
906 | 30 | } |
907 | | |
908 | 0 | void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const { |
909 | 0 | assert(N == 1 && "Invalid number of operands!"); |
910 | 0 | Inst.addOperand(MCOperand::createReg(getACC64DSPReg())); |
911 | 0 | } |
912 | | |
913 | 0 | void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const { |
914 | 0 | assert(N == 1 && "Invalid number of operands!"); |
915 | 0 | Inst.addOperand(MCOperand::createReg(getHI32DSPReg())); |
916 | 0 | } |
917 | | |
918 | 0 | void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const { |
919 | 0 | assert(N == 1 && "Invalid number of operands!"); |
920 | 0 | Inst.addOperand(MCOperand::createReg(getLO32DSPReg())); |
921 | 0 | } |
922 | | |
923 | 0 | void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const { |
924 | 0 | assert(N == 1 && "Invalid number of operands!"); |
925 | 0 | Inst.addOperand(MCOperand::createReg(getCCRReg())); |
926 | 0 | } |
927 | | |
928 | 0 | void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const { |
929 | 0 | assert(N == 1 && "Invalid number of operands!"); |
930 | 0 | Inst.addOperand(MCOperand::createReg(getHWRegsReg())); |
931 | 0 | } |
932 | | |
933 | | template <unsigned Bits, int Offset = 0, int AdjustOffset = 0> |
934 | 0 | void addConstantUImmOperands(MCInst &Inst, unsigned N) const { |
935 | 0 | assert(N == 1 && "Invalid number of operands!"); |
936 | 0 | uint64_t Imm = getConstantImm() - Offset; |
937 | 0 | Imm &= (1 << Bits) - 1; |
938 | 0 | Imm += Offset; |
939 | 0 | Imm += AdjustOffset; |
940 | 0 | Inst.addOperand(MCOperand::createImm(Imm)); |
941 | 0 | } Unexecuted instantiation: MipsAsmParser.cpp:void (anonymous namespace)::MipsOperand::addConstantUImmOperands<2u, 0, 0>(llvm_ks::MCInst&, unsigned int) const Unexecuted instantiation: MipsAsmParser.cpp:void (anonymous namespace)::MipsOperand::addConstantUImmOperands<16u, 0, 0>(llvm_ks::MCInst&, unsigned int) const Unexecuted instantiation: MipsAsmParser.cpp:void (anonymous namespace)::MipsOperand::addConstantUImmOperands<5u, 0, 0>(llvm_ks::MCInst&, unsigned int) const Unexecuted instantiation: MipsAsmParser.cpp:void (anonymous namespace)::MipsOperand::addConstantUImmOperands<5u, 32, -32>(llvm_ks::MCInst&, unsigned int) const Unexecuted instantiation: MipsAsmParser.cpp:void (anonymous namespace)::MipsOperand::addConstantUImmOperands<10u, 0, 0>(llvm_ks::MCInst&, unsigned int) const Unexecuted instantiation: MipsAsmParser.cpp:void (anonymous namespace)::MipsOperand::addConstantUImmOperands<4u, 0, 0>(llvm_ks::MCInst&, unsigned int) const Unexecuted instantiation: MipsAsmParser.cpp:void (anonymous namespace)::MipsOperand::addConstantUImmOperands<3u, 0, 0>(llvm_ks::MCInst&, unsigned int) const Unexecuted instantiation: MipsAsmParser.cpp:void (anonymous namespace)::MipsOperand::addConstantUImmOperands<5u, 1, 0>(llvm_ks::MCInst&, unsigned int) const Unexecuted instantiation: MipsAsmParser.cpp:void (anonymous namespace)::MipsOperand::addConstantUImmOperands<5u, 33, 0>(llvm_ks::MCInst&, unsigned int) const Unexecuted instantiation: MipsAsmParser.cpp:void (anonymous namespace)::MipsOperand::addConstantUImmOperands<5u, 32, 0>(llvm_ks::MCInst&, unsigned int) const Unexecuted instantiation: MipsAsmParser.cpp:void (anonymous namespace)::MipsOperand::addConstantUImmOperands<6u, 0, 0>(llvm_ks::MCInst&, unsigned int) const Unexecuted instantiation: MipsAsmParser.cpp:void (anonymous namespace)::MipsOperand::addConstantUImmOperands<2u, 1, 0>(llvm_ks::MCInst&, unsigned int) const Unexecuted instantiation: MipsAsmParser.cpp:void (anonymous namespace)::MipsOperand::addConstantUImmOperands<1u, 0, 0>(llvm_ks::MCInst&, unsigned int) const Unexecuted instantiation: MipsAsmParser.cpp:void (anonymous namespace)::MipsOperand::addConstantUImmOperands<7u, 0, 0>(llvm_ks::MCInst&, unsigned int) const Unexecuted instantiation: MipsAsmParser.cpp:void (anonymous namespace)::MipsOperand::addConstantUImmOperands<8u, 0, 0>(llvm_ks::MCInst&, unsigned int) const |
942 | | |
943 | | template <unsigned Bits> |
944 | 0 | void addUImmOperands(MCInst &Inst, unsigned N) const { |
945 | 0 | if (isImm() && !isConstantImm()) { |
946 | 0 | addExpr(Inst, getImm()); |
947 | 0 | return; |
948 | 0 | } |
949 | 0 | addConstantUImmOperands<Bits, 0, 0>(Inst, N); |
950 | 0 | } |
951 | | |
952 | 12.6k | void addImmOperands(MCInst &Inst, unsigned N) const { |
953 | 12.6k | assert(N == 1 && "Invalid number of operands!"); |
954 | 12.6k | const MCExpr *Expr = getImm(); |
955 | 12.6k | addExpr(Inst, Expr); |
956 | 12.6k | } |
957 | | |
958 | 876 | void addMemOperands(MCInst &Inst, unsigned N) const { |
959 | 876 | assert(N == 2 && "Invalid number of operands!"); |
960 | | |
961 | 876 | Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit() |
962 | 876 | ? getMemBase()->getGPR64Reg() |
963 | 876 | : getMemBase()->getGPR32Reg())); |
964 | | |
965 | 876 | const MCExpr *Expr = getMemOff(); |
966 | 876 | addExpr(Inst, Expr); |
967 | 876 | } |
968 | | |
969 | 0 | void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const { |
970 | 0 | assert(N == 2 && "Invalid number of operands!"); |
971 | | |
972 | 0 | Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg())); |
973 | |
|
974 | 0 | const MCExpr *Expr = getMemOff(); |
975 | 0 | addExpr(Inst, Expr); |
976 | 0 | } |
977 | | |
978 | 0 | void addRegListOperands(MCInst &Inst, unsigned N) const { |
979 | 0 | assert(N == 1 && "Invalid number of operands!"); |
980 | | |
981 | 0 | for (auto RegNo : getRegList()) |
982 | 0 | Inst.addOperand(MCOperand::createReg(RegNo)); |
983 | 0 | } |
984 | | |
985 | 0 | void addRegPairOperands(MCInst &Inst, unsigned N) const { |
986 | 0 | assert(N == 2 && "Invalid number of operands!"); |
987 | 0 | unsigned RegNo = getRegPair(); |
988 | 0 | Inst.addOperand(MCOperand::createReg(RegNo++)); |
989 | 0 | Inst.addOperand(MCOperand::createReg(RegNo)); |
990 | 0 | } |
991 | | |
992 | 0 | void addMovePRegPairOperands(MCInst &Inst, unsigned N) const { |
993 | 0 | assert(N == 2 && "Invalid number of operands!"); |
994 | 0 | for (auto RegNo : getRegList()) |
995 | 0 | Inst.addOperand(MCOperand::createReg(RegNo)); |
996 | 0 | } |
997 | | |
998 | 11.9k | bool isReg() const override { |
999 | | // As a special case until we sort out the definition of div/divu, pretend |
1000 | | // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly. |
1001 | 11.9k | if (isGPRAsmReg() && RegIdx.Index == 0) |
1002 | 37 | return true; |
1003 | | |
1004 | 11.9k | return Kind == k_PhysRegister; |
1005 | 11.9k | } |
1006 | 47.9k | bool isRegIdx() const { return Kind == k_RegisterIndex; } |
1007 | 30.8k | bool isImm() const override { return Kind == k_Immediate; } |
1008 | 14 | bool isConstantImm() const { |
1009 | 14 | return isImm() && isa<MCConstantExpr>(getImm()); |
1010 | 14 | } |
1011 | 0 | bool isConstantImmz() const { |
1012 | 0 | return isConstantImm() && getConstantImm() == 0; |
1013 | 0 | } |
1014 | 14 | template <unsigned Bits, int Offset = 0> bool isConstantUImm() const { |
1015 | 14 | return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset); |
1016 | 14 | } Unexecuted instantiation: MipsAsmParser.cpp:bool (anonymous namespace)::MipsOperand::isConstantUImm<1u, 0>() const Unexecuted instantiation: MipsAsmParser.cpp:bool (anonymous namespace)::MipsOperand::isConstantUImm<2u, 0>() const Unexecuted instantiation: MipsAsmParser.cpp:bool (anonymous namespace)::MipsOperand::isConstantUImm<2u, 1>() const Unexecuted instantiation: MipsAsmParser.cpp:bool (anonymous namespace)::MipsOperand::isConstantUImm<3u, 0>() const Unexecuted instantiation: MipsAsmParser.cpp:bool (anonymous namespace)::MipsOperand::isConstantUImm<4u, 0>() const Unexecuted instantiation: MipsAsmParser.cpp:bool (anonymous namespace)::MipsOperand::isConstantUImm<5u, 0>() const Unexecuted instantiation: MipsAsmParser.cpp:bool (anonymous namespace)::MipsOperand::isConstantUImm<5u, 1>() const Unexecuted instantiation: MipsAsmParser.cpp:bool (anonymous namespace)::MipsOperand::isConstantUImm<5u, 32>() const Unexecuted instantiation: MipsAsmParser.cpp:bool (anonymous namespace)::MipsOperand::isConstantUImm<5u, 33>() const MipsAsmParser.cpp:bool (anonymous namespace)::MipsOperand::isConstantUImm<6u, 0>() const Line | Count | Source | 1014 | 2 | template <unsigned Bits, int Offset = 0> bool isConstantUImm() const { | 1015 | 2 | return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset); | 1016 | 2 | } |
Unexecuted instantiation: MipsAsmParser.cpp:bool (anonymous namespace)::MipsOperand::isConstantUImm<7u, 0>() const Unexecuted instantiation: MipsAsmParser.cpp:bool (anonymous namespace)::MipsOperand::isConstantUImm<8u, 0>() const MipsAsmParser.cpp:bool (anonymous namespace)::MipsOperand::isConstantUImm<10u, 0>() const Line | Count | Source | 1014 | 12 | template <unsigned Bits, int Offset = 0> bool isConstantUImm() const { | 1015 | 12 | return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset); | 1016 | 12 | } |
|
1017 | 0 | template <unsigned Bits> bool isUImm() const { |
1018 | 0 | return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm(); |
1019 | 0 | } |
1020 | 0 | template <unsigned Bits> bool isAnyImm() const { |
1021 | 0 | return isConstantImm() ? (isInt<Bits>(getConstantImm()) || |
1022 | 0 | isUInt<Bits>(getConstantImm())) |
1023 | 0 | : isImm(); |
1024 | 0 | } |
1025 | 0 | template <unsigned Bits> bool isConstantSImm() const { |
1026 | 0 | return isConstantImm() && isInt<Bits>(getConstantImm()); |
1027 | 0 | } |
1028 | 56.0k | bool isToken() const override { |
1029 | | // Note: It's not possible to pretend that other operand kinds are tokens. |
1030 | | // The matcher emitter checks tokens first. |
1031 | 56.0k | return Kind == k_Token; |
1032 | 56.0k | } |
1033 | 2.68k | bool isMem() const override { return Kind == k_Memory; } |
1034 | 893 | bool isConstantMemOff() const { |
1035 | 893 | return isMem() && isa<MCConstantExpr>(getMemOff()); |
1036 | 893 | } |
1037 | 494 | template <unsigned Bits> bool isMemWithSimmOffset() const { |
1038 | 494 | return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) |
1039 | 102 | && getMemBase()->isGPRAsmReg(); |
1040 | 494 | } MipsAsmParser.cpp:bool (anonymous namespace)::MipsOperand::isMemWithSimmOffset<11u>() const Line | Count | Source | 1037 | 167 | template <unsigned Bits> bool isMemWithSimmOffset() const { | 1038 | 167 | return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) | 1039 | 34 | && getMemBase()->isGPRAsmReg(); | 1040 | 167 | } |
Unexecuted instantiation: MipsAsmParser.cpp:bool (anonymous namespace)::MipsOperand::isMemWithSimmOffset<16u>() const MipsAsmParser.cpp:bool (anonymous namespace)::MipsOperand::isMemWithSimmOffset<9u>() const Line | Count | Source | 1037 | 327 | template <unsigned Bits> bool isMemWithSimmOffset() const { | 1038 | 327 | return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) | 1039 | 68 | && getMemBase()->isGPRAsmReg(); | 1040 | 327 | } |
|
1041 | 0 | template <unsigned Bits> bool isMemWithSimmOffsetGPR() const { |
1042 | 0 | return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) && |
1043 | 0 | getMemBase()->isGPRAsmReg(); |
1044 | 0 | } |
1045 | 0 | bool isMemWithGRPMM16Base() const { |
1046 | 0 | return isMem() && getMemBase()->isMM16AsmReg(); |
1047 | 0 | } |
1048 | 0 | template <unsigned Bits> bool isMemWithUimmOffsetSP() const { |
1049 | 0 | return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff()) |
1050 | 0 | && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP); |
1051 | 0 | } |
1052 | 399 | template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const { |
1053 | 399 | return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff()) |
1054 | 227 | && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx() |
1055 | 138 | && (getMemBase()->getGPR32Reg() == Mips::SP); |
1056 | 399 | } |
1057 | | template <unsigned Bits, unsigned ShiftLeftAmount> |
1058 | 0 | bool isScaledUImm() const { |
1059 | 0 | return isConstantImm() && |
1060 | 0 | isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm()); |
1061 | 0 | } |
1062 | 0 | bool isRegList16() const { |
1063 | 0 | if (!isRegList()) |
1064 | 0 | return false; |
1065 | | |
1066 | 0 | int Size = RegList.List->size(); |
1067 | 0 | if (Size < 2 || Size > 5) |
1068 | 0 | return false; |
1069 | | |
1070 | 0 | unsigned R0 = RegList.List->front(); |
1071 | 0 | unsigned R1 = RegList.List->back(); |
1072 | 0 | if (!((R0 == Mips::S0 && R1 == Mips::RA) || |
1073 | 0 | (R0 == Mips::S0_64 && R1 == Mips::RA_64))) |
1074 | 0 | return false; |
1075 | | |
1076 | 0 | int PrevReg = *RegList.List->begin(); |
1077 | 0 | for (int i = 1; i < Size - 1; i++) { |
1078 | 0 | int Reg = (*(RegList.List))[i]; |
1079 | 0 | if ( Reg != PrevReg + 1) |
1080 | 0 | return false; |
1081 | 0 | PrevReg = Reg; |
1082 | 0 | } |
1083 | | |
1084 | 0 | return true; |
1085 | 0 | } |
1086 | 0 | bool isInvNum() const { return Kind == k_Immediate; } |
1087 | 0 | bool isLSAImm() const { |
1088 | 0 | if (!isConstantImm()) |
1089 | 0 | return false; |
1090 | 0 | int64_t Val = getConstantImm(); |
1091 | 0 | return 1 <= Val && Val <= 4; |
1092 | 0 | } |
1093 | 0 | bool isRegList() const { return Kind == k_RegList; } |
1094 | 0 | bool isMovePRegPair() const { |
1095 | 0 | if (Kind != k_RegList || RegList.List->size() != 2) |
1096 | 0 | return false; |
1097 | | |
1098 | 0 | unsigned R0 = RegList.List->front(); |
1099 | 0 | unsigned R1 = RegList.List->back(); |
1100 | |
|
1101 | 0 | if ((R0 == Mips::A1 && R1 == Mips::A2) || |
1102 | 0 | (R0 == Mips::A1 && R1 == Mips::A3) || |
1103 | 0 | (R0 == Mips::A2 && R1 == Mips::A3) || |
1104 | 0 | (R0 == Mips::A0 && R1 == Mips::S5) || |
1105 | 0 | (R0 == Mips::A0 && R1 == Mips::S6) || |
1106 | 0 | (R0 == Mips::A0 && R1 == Mips::A1) || |
1107 | 0 | (R0 == Mips::A0 && R1 == Mips::A2) || |
1108 | 0 | (R0 == Mips::A0 && R1 == Mips::A3)) |
1109 | 0 | return true; |
1110 | | |
1111 | 0 | return false; |
1112 | 0 | } |
1113 | | |
1114 | 16.7k | StringRef getToken() const { |
1115 | 16.7k | assert(Kind == k_Token && "Invalid access!"); |
1116 | 16.7k | return StringRef(Tok.Data, Tok.Length); |
1117 | 16.7k | } |
1118 | 0 | bool isRegPair() const { return Kind == k_RegPair; } |
1119 | | |
1120 | 37 | unsigned getReg() const override { |
1121 | | // As a special case until we sort out the definition of div/divu, pretend |
1122 | | // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly. |
1123 | 37 | if (Kind == k_RegisterIndex && RegIdx.Index == 0 && |
1124 | 37 | RegIdx.Kind & RegKind_GPR) |
1125 | 37 | return getGPR32Reg(); // FIXME: GPR64 too |
1126 | | |
1127 | 37 | assert(Kind == k_PhysRegister && "Invalid access!"); |
1128 | 0 | return PhysReg.Num; |
1129 | 0 | } |
1130 | | |
1131 | 12.6k | const MCExpr *getImm() const { |
1132 | 12.6k | assert((Kind == k_Immediate) && "Invalid access!"); |
1133 | 12.6k | return Imm.Val; |
1134 | 12.6k | } |
1135 | | |
1136 | 12 | int64_t getConstantImm() const { |
1137 | 12 | const MCExpr *Val = getImm(); |
1138 | 12 | return static_cast<const MCConstantExpr *>(Val)->getValue(); |
1139 | 12 | } |
1140 | | |
1141 | 1.25k | MipsOperand *getMemBase() const { |
1142 | 1.25k | assert((Kind == k_Memory) && "Invalid access!"); |
1143 | 1.25k | return Mem.Base; |
1144 | 1.25k | } |
1145 | | |
1146 | 2.64k | const MCExpr *getMemOff() const { |
1147 | 2.64k | assert((Kind == k_Memory) && "Invalid access!"); |
1148 | 2.64k | return Mem.Off; |
1149 | 2.64k | } |
1150 | | |
1151 | 875 | int64_t getConstantMemOff() const { |
1152 | 875 | return static_cast<const MCConstantExpr *>(getMemOff())->getValue(); |
1153 | 875 | } |
1154 | | |
1155 | 0 | const SmallVectorImpl<unsigned> &getRegList() const { |
1156 | 0 | assert((Kind == k_RegList) && "Invalid access!"); |
1157 | 0 | return *(RegList.List); |
1158 | 0 | } |
1159 | | |
1160 | 0 | unsigned getRegPair() const { |
1161 | 0 | assert((Kind == k_RegPair) && "Invalid access!"); |
1162 | 0 | return RegIdx.Index; |
1163 | 0 | } |
1164 | | |
1165 | | static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S, |
1166 | 33.5k | MipsAsmParser &Parser) { |
1167 | 33.5k | auto Op = make_unique<MipsOperand>(k_Token, Parser); |
1168 | 33.5k | Op->Tok.Data = Str.data(); |
1169 | 33.5k | Op->Tok.Length = Str.size(); |
1170 | 33.5k | Op->StartLoc = S; |
1171 | 33.5k | Op->EndLoc = S; |
1172 | 33.5k | return Op; |
1173 | 33.5k | } |
1174 | | |
1175 | | /// Create a numeric register (e.g. $1). The exact register remains |
1176 | | /// unresolved until an instruction successfully matches |
1177 | | static std::unique_ptr<MipsOperand> |
1178 | | createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, |
1179 | 10.2k | SMLoc E, MipsAsmParser &Parser) { |
1180 | 10.2k | DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n"); |
1181 | 10.2k | return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser); |
1182 | 10.2k | } |
1183 | | |
1184 | | /// Create a register that is definitely a GPR. |
1185 | | /// This is typically only used for named registers such as $gp. |
1186 | | static std::unique_ptr<MipsOperand> |
1187 | | createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E, |
1188 | 7.11k | MipsAsmParser &Parser) { |
1189 | 7.11k | return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser); |
1190 | 7.11k | } |
1191 | | |
1192 | | /// Create a register that is definitely a FGR. |
1193 | | /// This is typically only used for named registers such as $f0. |
1194 | | static std::unique_ptr<MipsOperand> |
1195 | | createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E, |
1196 | 131 | MipsAsmParser &Parser) { |
1197 | 131 | return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser); |
1198 | 131 | } |
1199 | | |
1200 | | /// Create a register that is definitely a HWReg. |
1201 | | /// This is typically only used for named registers such as $hwr_cpunum. |
1202 | | static std::unique_ptr<MipsOperand> |
1203 | | createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo, |
1204 | 21 | SMLoc S, SMLoc E, MipsAsmParser &Parser) { |
1205 | 21 | return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser); |
1206 | 21 | } |
1207 | | |
1208 | | /// Create a register that is definitely an FCC. |
1209 | | /// This is typically only used for named registers such as $fcc0. |
1210 | | static std::unique_ptr<MipsOperand> |
1211 | | createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E, |
1212 | 71 | MipsAsmParser &Parser) { |
1213 | 71 | return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser); |
1214 | 71 | } |
1215 | | |
1216 | | /// Create a register that is definitely an ACC. |
1217 | | /// This is typically only used for named registers such as $ac0. |
1218 | | static std::unique_ptr<MipsOperand> |
1219 | | createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E, |
1220 | 52 | MipsAsmParser &Parser) { |
1221 | 52 | return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser); |
1222 | 52 | } |
1223 | | |
1224 | | /// Create a register that is definitely an MSA128. |
1225 | | /// This is typically only used for named registers such as $w0. |
1226 | | static std::unique_ptr<MipsOperand> |
1227 | | createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, |
1228 | 1 | SMLoc E, MipsAsmParser &Parser) { |
1229 | 1 | return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser); |
1230 | 1 | } |
1231 | | |
1232 | | /// Create a register that is definitely an MSACtrl. |
1233 | | /// This is typically only used for named registers such as $msaaccess. |
1234 | | static std::unique_ptr<MipsOperand> |
1235 | | createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, |
1236 | 180 | SMLoc E, MipsAsmParser &Parser) { |
1237 | 180 | return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser); |
1238 | 180 | } |
1239 | | |
1240 | | static std::unique_ptr<MipsOperand> |
1241 | 19.6k | CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) { |
1242 | 19.6k | auto Op = make_unique<MipsOperand>(k_Immediate, Parser); |
1243 | 19.6k | Op->Imm.Val = Val; |
1244 | 19.6k | Op->StartLoc = S; |
1245 | 19.6k | Op->EndLoc = E; |
1246 | 19.6k | return Op; |
1247 | 19.6k | } |
1248 | | |
1249 | | static std::unique_ptr<MipsOperand> |
1250 | | CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S, |
1251 | 878 | SMLoc E, MipsAsmParser &Parser) { |
1252 | 878 | auto Op = make_unique<MipsOperand>(k_Memory, Parser); |
1253 | 878 | Op->Mem.Base = Base.release(); |
1254 | 878 | Op->Mem.Off = Off; |
1255 | 878 | Op->StartLoc = S; |
1256 | 878 | Op->EndLoc = E; |
1257 | 878 | return Op; |
1258 | 878 | } |
1259 | | |
1260 | | static std::unique_ptr<MipsOperand> |
1261 | | CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc, |
1262 | 0 | MipsAsmParser &Parser) { |
1263 | 0 | assert (Regs.size() > 0 && "Empty list not allowed"); |
1264 | | |
1265 | 0 | auto Op = make_unique<MipsOperand>(k_RegList, Parser); |
1266 | 0 | Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end()); |
1267 | 0 | Op->StartLoc = StartLoc; |
1268 | 0 | Op->EndLoc = EndLoc; |
1269 | 0 | return Op; |
1270 | 0 | } |
1271 | | |
1272 | | static std::unique_ptr<MipsOperand> |
1273 | 0 | CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) { |
1274 | 0 | auto Op = make_unique<MipsOperand>(k_RegPair, Parser); |
1275 | 0 | Op->RegIdx.Index = RegNo; |
1276 | 0 | Op->StartLoc = S; |
1277 | 0 | Op->EndLoc = E; |
1278 | 0 | return Op; |
1279 | 0 | } |
1280 | | |
1281 | 40.5k | bool isGPRAsmReg() const { |
1282 | 40.5k | return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31; |
1283 | 40.5k | } |
1284 | 4 | bool isMM16AsmReg() const { |
1285 | 4 | if (!(isRegIdx() && RegIdx.Kind)) |
1286 | 4 | return false; |
1287 | 0 | return ((RegIdx.Index >= 2 && RegIdx.Index <= 7) |
1288 | 0 | || RegIdx.Index == 16 || RegIdx.Index == 17); |
1289 | 4 | } |
1290 | 0 | bool isMM16AsmRegZero() const { |
1291 | 0 | if (!(isRegIdx() && RegIdx.Kind)) |
1292 | 0 | return false; |
1293 | 0 | return (RegIdx.Index == 0 || |
1294 | 0 | (RegIdx.Index >= 2 && RegIdx.Index <= 7) || |
1295 | 0 | RegIdx.Index == 17); |
1296 | 0 | } |
1297 | 0 | bool isMM16AsmRegMoveP() const { |
1298 | 0 | if (!(isRegIdx() && RegIdx.Kind)) |
1299 | 0 | return false; |
1300 | 0 | return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) || |
1301 | 0 | (RegIdx.Index >= 16 && RegIdx.Index <= 20)); |
1302 | 0 | } |
1303 | 24 | bool isFGRAsmReg() const { |
1304 | | // AFGR64 is $0-$15 but we handle this in getAFGR64() |
1305 | 24 | return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31; |
1306 | 24 | } |
1307 | 0 | bool isHWRegsAsmReg() const { |
1308 | 0 | return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31; |
1309 | 0 | } |
1310 | 0 | bool isCCRAsmReg() const { |
1311 | 0 | return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31; |
1312 | 0 | } |
1313 | 2 | bool isFCCAsmReg() const { |
1314 | 2 | if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC)) |
1315 | 0 | return false; |
1316 | 2 | if (!AsmParser.hasEightFccRegisters()) |
1317 | 0 | return RegIdx.Index == 0; |
1318 | 2 | return RegIdx.Index <= 7; |
1319 | 2 | } |
1320 | 0 | bool isACCAsmReg() const { |
1321 | 0 | return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3; |
1322 | 0 | } |
1323 | 0 | bool isCOP0AsmReg() const { |
1324 | 0 | return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31; |
1325 | 0 | } |
1326 | 333 | bool isCOP2AsmReg() const { |
1327 | 333 | return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31; |
1328 | 333 | } |
1329 | 31 | bool isCOP3AsmReg() const { |
1330 | 31 | return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31; |
1331 | 31 | } |
1332 | 0 | bool isMSA128AsmReg() const { |
1333 | 0 | return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31; |
1334 | 0 | } |
1335 | 0 | bool isMSACtrlAsmReg() const { |
1336 | 0 | return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7; |
1337 | 0 | } |
1338 | | |
1339 | | /// getStartLoc - Get the location of the first token of this operand. |
1340 | 781 | SMLoc getStartLoc() const override { return StartLoc; } |
1341 | | /// getEndLoc - Get the location of the last token of this operand. |
1342 | 0 | SMLoc getEndLoc() const override { return EndLoc; } |
1343 | | |
1344 | 71.8k | virtual ~MipsOperand() { |
1345 | 71.8k | switch (Kind) { |
1346 | 19.6k | case k_Immediate: |
1347 | 19.6k | break; |
1348 | 878 | case k_Memory: |
1349 | 878 | delete Mem.Base; |
1350 | 878 | break; |
1351 | 0 | case k_RegList: |
1352 | 0 | delete RegList.List; |
1353 | 0 | case k_PhysRegister: |
1354 | 17.8k | case k_RegisterIndex: |
1355 | 51.3k | case k_Token: |
1356 | 51.3k | case k_RegPair: |
1357 | 51.3k | break; |
1358 | 71.8k | } |
1359 | 71.8k | } |
1360 | | |
1361 | 0 | void print(raw_ostream &OS) const override { |
1362 | 0 | switch (Kind) { |
1363 | 0 | case k_Immediate: |
1364 | 0 | OS << "Imm<"; |
1365 | 0 | OS << *Imm.Val; |
1366 | 0 | OS << ">"; |
1367 | 0 | break; |
1368 | 0 | case k_Memory: |
1369 | 0 | OS << "Mem<"; |
1370 | 0 | Mem.Base->print(OS); |
1371 | 0 | OS << ", "; |
1372 | 0 | OS << *Mem.Off; |
1373 | 0 | OS << ">"; |
1374 | 0 | break; |
1375 | 0 | case k_PhysRegister: |
1376 | 0 | OS << "PhysReg<" << PhysReg.Num << ">"; |
1377 | 0 | break; |
1378 | 0 | case k_RegisterIndex: |
1379 | 0 | OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">"; |
1380 | 0 | break; |
1381 | 0 | case k_Token: |
1382 | 0 | OS << Tok.Data; |
1383 | 0 | break; |
1384 | 0 | case k_RegList: |
1385 | 0 | OS << "RegList< "; |
1386 | 0 | for (auto Reg : (*RegList.List)) |
1387 | 0 | OS << Reg << " "; |
1388 | 0 | OS << ">"; |
1389 | 0 | break; |
1390 | 0 | case k_RegPair: |
1391 | 0 | OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">"; |
1392 | 0 | break; |
1393 | 0 | } |
1394 | 0 | } |
1395 | | }; // class MipsOperand |
1396 | | } // namespace |
1397 | | |
1398 | | namespace llvm_ks { |
1399 | | extern const MCInstrDesc MipsInsts[]; |
1400 | | } |
1401 | 15.3k | static const MCInstrDesc &getInstDesc(unsigned Opcode) { |
1402 | 15.3k | return MipsInsts[Opcode]; |
1403 | 15.3k | } |
1404 | | |
1405 | 11.8k | static bool hasShortDelaySlot(unsigned Opcode) { |
1406 | 11.8k | switch (Opcode) { |
1407 | 0 | case Mips::JALS_MM: |
1408 | 0 | case Mips::JALRS_MM: |
1409 | 0 | case Mips::JALRS16_MM: |
1410 | 0 | case Mips::BGEZALS_MM: |
1411 | 0 | case Mips::BLTZALS_MM: |
1412 | 0 | return true; |
1413 | 11.8k | default: |
1414 | 11.8k | return false; |
1415 | 11.8k | } |
1416 | 11.8k | } |
1417 | | |
1418 | 16 | static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) { |
1419 | 16 | if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) { |
1420 | 10 | return &SRExpr->getSymbol(); |
1421 | 10 | } |
1422 | | |
1423 | 6 | if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) { |
1424 | 0 | const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS()); |
1425 | 0 | const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS()); |
1426 | |
|
1427 | 0 | if (LHSSym) |
1428 | 0 | return LHSSym; |
1429 | | |
1430 | 0 | if (RHSSym) |
1431 | 0 | return RHSSym; |
1432 | | |
1433 | 0 | return nullptr; |
1434 | 0 | } |
1435 | | |
1436 | 6 | if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr)) |
1437 | 6 | return getSingleMCSymbol(UExpr->getSubExpr()); |
1438 | | |
1439 | 0 | return nullptr; |
1440 | 6 | } |
1441 | | |
1442 | 16 | static unsigned countMCSymbolRefExpr(const MCExpr *Expr) { |
1443 | 16 | if (isa<MCSymbolRefExpr>(Expr)) |
1444 | 10 | return 1; |
1445 | | |
1446 | 6 | if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) |
1447 | 0 | return countMCSymbolRefExpr(BExpr->getLHS()) + |
1448 | 0 | countMCSymbolRefExpr(BExpr->getRHS()); |
1449 | | |
1450 | 6 | if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr)) |
1451 | 6 | return countMCSymbolRefExpr(UExpr->getSubExpr()); |
1452 | | |
1453 | 0 | return 0; |
1454 | 6 | } |
1455 | | |
1456 | | namespace { |
1457 | | void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc, |
1458 | 906 | SmallVectorImpl<MCInst> &Instructions) { |
1459 | 906 | MCInst tmpInst; |
1460 | 906 | tmpInst.setOpcode(Opcode); |
1461 | 906 | tmpInst.addOperand(MCOperand::createReg(Reg0)); |
1462 | 906 | tmpInst.addOperand(Op1); |
1463 | 906 | tmpInst.setLoc(IDLoc); |
1464 | 906 | Instructions.push_back(tmpInst); |
1465 | 906 | } |
1466 | | |
1467 | | void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc, |
1468 | 322 | SmallVectorImpl<MCInst> &Instructions) { |
1469 | 322 | emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions); |
1470 | 322 | } |
1471 | | |
1472 | | void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc, |
1473 | 0 | SmallVectorImpl<MCInst> &Instructions) { |
1474 | 0 | emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, Instructions); |
1475 | 0 | } |
1476 | | |
1477 | | void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc, |
1478 | 0 | SmallVectorImpl<MCInst> &Instructions) { |
1479 | 0 | MCInst tmpInst; |
1480 | 0 | tmpInst.setOpcode(Opcode); |
1481 | 0 | tmpInst.addOperand(MCOperand::createImm(Imm1)); |
1482 | 0 | tmpInst.addOperand(MCOperand::createImm(Imm2)); |
1483 | 0 | tmpInst.setLoc(IDLoc); |
1484 | 0 | Instructions.push_back(tmpInst); |
1485 | 0 | } |
1486 | | |
1487 | | void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc, |
1488 | 0 | SmallVectorImpl<MCInst> &Instructions) { |
1489 | 0 | MCInst tmpInst; |
1490 | 0 | tmpInst.setOpcode(Opcode); |
1491 | 0 | tmpInst.addOperand(MCOperand::createReg(Reg0)); |
1492 | 0 | tmpInst.setLoc(IDLoc); |
1493 | 0 | Instructions.push_back(tmpInst); |
1494 | 0 | } |
1495 | | |
1496 | | void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2, |
1497 | 17.0k | SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { |
1498 | 17.0k | MCInst tmpInst; |
1499 | 17.0k | tmpInst.setOpcode(Opcode); |
1500 | 17.0k | tmpInst.addOperand(MCOperand::createReg(Reg0)); |
1501 | 17.0k | tmpInst.addOperand(MCOperand::createReg(Reg1)); |
1502 | 17.0k | tmpInst.addOperand(Op2); |
1503 | 17.0k | tmpInst.setLoc(IDLoc); |
1504 | 17.0k | Instructions.push_back(tmpInst); |
1505 | 17.0k | } |
1506 | | |
1507 | | void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2, |
1508 | 1.53k | SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { |
1509 | 1.53k | emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc, |
1510 | 1.53k | Instructions); |
1511 | 1.53k | } |
1512 | | |
1513 | | void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm, |
1514 | 14.8k | SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { |
1515 | 14.8k | emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc, |
1516 | 14.8k | Instructions); |
1517 | 14.8k | } |
1518 | | |
1519 | | void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount, |
1520 | 979 | SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { |
1521 | 979 | if (ShiftAmount >= 32) { |
1522 | 37 | emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc, |
1523 | 37 | Instructions); |
1524 | 37 | return; |
1525 | 37 | } |
1526 | | |
1527 | 942 | emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions); |
1528 | 942 | } |
1529 | | } // end anonymous namespace. |
1530 | | |
1531 | | // return true on error |
1532 | | bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, |
1533 | | SmallVectorImpl<MCInst> &Instructions, |
1534 | | unsigned int &KsError) |
1535 | 14.8k | { |
1536 | 14.8k | const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode()); |
1537 | 14.8k | bool ExpandedJalSym = false; |
1538 | | |
1539 | 14.8k | Inst.setLoc(IDLoc); |
1540 | | |
1541 | 14.8k | if (MCID.isBranch() || MCID.isCall()) { |
1542 | 11.9k | const unsigned Opcode = Inst.getOpcode(); |
1543 | 11.9k | MCOperand Offset; |
1544 | | |
1545 | 11.9k | switch (Opcode) { |
1546 | 4.85k | default: |
1547 | 4.85k | break; |
1548 | 4.85k | case Mips::BBIT0: |
1549 | 0 | case Mips::BBIT032: |
1550 | 0 | case Mips::BBIT1: |
1551 | 0 | case Mips::BBIT132: |
1552 | 0 | assert(hasCnMips() && "instruction only valid for octeon cpus"); |
1553 | | // Fall through |
1554 | | |
1555 | 7.05k | case Mips::BEQ: |
1556 | 7.05k | case Mips::BNE: |
1557 | 7.05k | case Mips::BEQ_MM: |
1558 | 7.05k | case Mips::BNE_MM: |
1559 | 7.05k | assert(MCID.getNumOperands() == 3 && "unexpected number of operands"); |
1560 | 7.05k | Offset = Inst.getOperand(2); |
1561 | 7.05k | if (!Offset.isImm()) |
1562 | 6.97k | break; // We'll deal with this situation later on when applying fixups. |
1563 | 78 | if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm())) { |
1564 | 21 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
1565 | 21 | return true; |
1566 | | //return Error(IDLoc, "branch target out of range"); |
1567 | 21 | } |
1568 | 57 | if (OffsetToAlignment(Offset.getImm(), |
1569 | 57 | 1LL << (inMicroMipsMode() ? 1 : 2))) { |
1570 | 2 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
1571 | 2 | return true; |
1572 | | //return Error(IDLoc, "branch to misaligned address"); |
1573 | 2 | } |
1574 | 55 | break; |
1575 | 55 | case Mips::BGEZ: |
1576 | 0 | case Mips::BGTZ: |
1577 | 0 | case Mips::BLEZ: |
1578 | 0 | case Mips::BLTZ: |
1579 | 84 | case Mips::BGEZAL: |
1580 | 84 | case Mips::BLTZAL: |
1581 | 86 | case Mips::BC1F: |
1582 | 89 | case Mips::BC1T: |
1583 | 89 | case Mips::BGEZ_MM: |
1584 | 89 | case Mips::BGTZ_MM: |
1585 | 89 | case Mips::BLEZ_MM: |
1586 | 89 | case Mips::BLTZ_MM: |
1587 | 89 | case Mips::BGEZAL_MM: |
1588 | 89 | case Mips::BLTZAL_MM: |
1589 | 89 | case Mips::BC1F_MM: |
1590 | 89 | case Mips::BC1T_MM: |
1591 | 89 | assert(MCID.getNumOperands() == 2 && "unexpected number of operands"); |
1592 | 89 | Offset = Inst.getOperand(1); |
1593 | 89 | if (!Offset.isImm()) |
1594 | 70 | break; // We'll deal with this situation later on when applying fixups. |
1595 | 19 | if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm())) { |
1596 | 2 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
1597 | 2 | return true; |
1598 | | //return Error(IDLoc, "branch target out of range"); |
1599 | 2 | } |
1600 | 17 | if (OffsetToAlignment(Offset.getImm(), |
1601 | 17 | 1LL << (inMicroMipsMode() ? 1 : 2))) { |
1602 | 0 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
1603 | 0 | return true; |
1604 | | //return Error(IDLoc, "branch to misaligned address"); |
1605 | 0 | } |
1606 | 17 | break; |
1607 | 17 | case Mips::BEQZ16_MM: |
1608 | 0 | case Mips::BEQZC16_MMR6: |
1609 | 0 | case Mips::BNEZ16_MM: |
1610 | 0 | case Mips::BNEZC16_MMR6: |
1611 | 0 | assert(MCID.getNumOperands() == 2 && "unexpected number of operands"); |
1612 | 0 | Offset = Inst.getOperand(1); |
1613 | 0 | if (!Offset.isImm()) |
1614 | 0 | break; // We'll deal with this situation later on when applying fixups. |
1615 | 0 | if (!isInt<8>(Offset.getImm())) { |
1616 | 0 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
1617 | 0 | return true; |
1618 | | //return Error(IDLoc, "branch target out of range"); |
1619 | 0 | } |
1620 | 0 | if (OffsetToAlignment(Offset.getImm(), 2LL)) { |
1621 | 0 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
1622 | 0 | return true; |
1623 | | //return Error(IDLoc, "branch to misaligned address"); |
1624 | 0 | } |
1625 | 0 | break; |
1626 | 11.9k | } |
1627 | 11.9k | } |
1628 | | |
1629 | | // SSNOP is deprecated on MIPS32r6/MIPS64r6 |
1630 | | // We still accept it but it is a normal nop. |
1631 | 14.8k | if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) { |
1632 | | // std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6"; |
1633 | | // Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a " |
1634 | | // "nop instruction"); |
1635 | 0 | } |
1636 | | |
1637 | 14.8k | if (hasCnMips()) { |
1638 | 0 | const unsigned Opcode = Inst.getOpcode(); |
1639 | 0 | MCOperand Opnd; |
1640 | 0 | int Imm; |
1641 | |
|
1642 | 0 | switch (Opcode) { |
1643 | 0 | default: |
1644 | 0 | break; |
1645 | | |
1646 | 0 | case Mips::BBIT0: |
1647 | 0 | case Mips::BBIT032: |
1648 | 0 | case Mips::BBIT1: |
1649 | 0 | case Mips::BBIT132: |
1650 | 0 | assert(MCID.getNumOperands() == 3 && "unexpected number of operands"); |
1651 | | // The offset is handled above |
1652 | 0 | Opnd = Inst.getOperand(1); |
1653 | 0 | if (!Opnd.isImm()) { |
1654 | 0 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
1655 | 0 | return true; |
1656 | | //return Error(IDLoc, "expected immediate operand kind"); |
1657 | 0 | } |
1658 | 0 | Imm = Opnd.getImm(); |
1659 | 0 | if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 || |
1660 | 0 | Opcode == Mips::BBIT1 ? 63 : 31)) { |
1661 | 0 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
1662 | 0 | return true; |
1663 | | //return Error(IDLoc, "immediate operand value out of range"); |
1664 | 0 | } |
1665 | 0 | if (Imm > 31) { |
1666 | 0 | Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032 |
1667 | 0 | : Mips::BBIT132); |
1668 | 0 | Inst.getOperand(1).setImm(Imm - 32); |
1669 | 0 | } |
1670 | 0 | break; |
1671 | | |
1672 | 0 | case Mips::SEQi: |
1673 | 0 | case Mips::SNEi: |
1674 | 0 | assert(MCID.getNumOperands() == 3 && "unexpected number of operands"); |
1675 | 0 | Opnd = Inst.getOperand(2); |
1676 | 0 | if (!Opnd.isImm()) { |
1677 | 0 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
1678 | 0 | return true; |
1679 | | //return Error(IDLoc, "expected immediate operand kind"); |
1680 | 0 | } |
1681 | 0 | Imm = Opnd.getImm(); |
1682 | 0 | if (!isInt<10>(Imm)) { |
1683 | 0 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
1684 | 0 | return true; |
1685 | | //return Error(IDLoc, "immediate operand value out of range"); |
1686 | 0 | } |
1687 | 0 | break; |
1688 | 0 | } |
1689 | 0 | } |
1690 | | |
1691 | | // This expansion is not in a function called by tryExpandInstruction() |
1692 | | // because the pseudo-instruction doesn't have a distinct opcode. |
1693 | 14.8k | if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) && |
1694 | 453 | inPicMode() && Inst.getOperand(0).isExpr()) { |
1695 | 10 | warnIfNoMacro(IDLoc); |
1696 | | |
1697 | 10 | const MCExpr *JalExpr = Inst.getOperand(0).getExpr(); |
1698 | | |
1699 | | // We can do this expansion if there's only 1 symbol in the argument |
1700 | | // expression. |
1701 | 10 | if (countMCSymbolRefExpr(JalExpr) > 1) { |
1702 | 0 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
1703 | 0 | return true; |
1704 | | //return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode"); |
1705 | 0 | } |
1706 | | |
1707 | | // FIXME: This is checking the expression can be handled by the later stages |
1708 | | // of the assembler. We ought to leave it to those later stages but |
1709 | | // we can't do that until we stop evaluateRelocExpr() rewriting the |
1710 | | // expressions into non-equivalent forms. |
1711 | 10 | const MCSymbol *JalSym = getSingleMCSymbol(JalExpr); |
1712 | | |
1713 | | // FIXME: Add support for label+offset operands (currently causes an error). |
1714 | | // FIXME: Add support for forward-declared local symbols. |
1715 | | // FIXME: Add expansion for when the LargeGOT option is enabled. |
1716 | 10 | if (JalSym->isInSection() || JalSym->isTemporary()) { |
1717 | 8 | if (isABI_O32()) { |
1718 | | // If it's a local symbol and the O32 ABI is being used, we expand to: |
1719 | | // lw $25, 0($gp) |
1720 | | // R_(MICRO)MIPS_GOT16 label |
1721 | | // addiu $25, $25, 0 |
1722 | | // R_(MICRO)MIPS_LO16 label |
1723 | | // jalr $25 |
1724 | 0 | const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got"); |
1725 | 0 | const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo"); |
1726 | |
|
1727 | 0 | emitRRX(Mips::LW, Mips::T9, Mips::GP, |
1728 | 0 | MCOperand::createExpr(Got16RelocExpr), IDLoc, Instructions); |
1729 | 0 | emitRRX(Mips::ADDiu, Mips::T9, Mips::T9, |
1730 | 0 | MCOperand::createExpr(Lo16RelocExpr), IDLoc, Instructions); |
1731 | 8 | } else if (isABI_N32() || isABI_N64()) { |
1732 | | // If it's a local symbol and the N32/N64 ABIs are being used, |
1733 | | // we expand to: |
1734 | | // lw/ld $25, 0($gp) |
1735 | | // R_(MICRO)MIPS_GOT_DISP label |
1736 | | // jalr $25 |
1737 | 8 | const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp"); |
1738 | | |
1739 | 8 | emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP, |
1740 | 8 | MCOperand::createExpr(GotDispRelocExpr), IDLoc, Instructions); |
1741 | 8 | } |
1742 | 8 | } else { |
1743 | | // If it's an external/weak symbol, we expand to: |
1744 | | // lw/ld $25, 0($gp) |
1745 | | // R_(MICRO)MIPS_CALL16 label |
1746 | | // jalr $25 |
1747 | 2 | const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16"); |
1748 | | |
1749 | 2 | emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP, |
1750 | 2 | MCOperand::createExpr(Call16RelocExpr), IDLoc, Instructions); |
1751 | 2 | } |
1752 | | |
1753 | 10 | MCInst JalrInst; |
1754 | 10 | if (IsCpRestoreSet && inMicroMipsMode()) |
1755 | 0 | JalrInst.setOpcode(Mips::JALRS_MM); |
1756 | 10 | else |
1757 | 10 | JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR); |
1758 | 10 | JalrInst.addOperand(MCOperand::createReg(Mips::RA)); |
1759 | 10 | JalrInst.addOperand(MCOperand::createReg(Mips::T9)); |
1760 | | |
1761 | | // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR. |
1762 | | // This relocation is supposed to be an optimization hint for the linker |
1763 | | // and is not necessary for correctness. |
1764 | | |
1765 | 10 | Inst = JalrInst; |
1766 | 10 | ExpandedJalSym = true; |
1767 | 10 | } |
1768 | | |
1769 | 14.8k | if (MCID.mayLoad() || MCID.mayStore()) { |
1770 | | // Check the offset of memory operand, if it is a symbol |
1771 | | // reference or immediate we may have to expand instructions. |
1772 | 2.97k | for (unsigned i = 0; i < MCID.getNumOperands(); i++) { |
1773 | 2.65k | const MCOperandInfo &OpInfo = MCID.OpInfo[i]; |
1774 | 2.65k | if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) || |
1775 | 1.75k | (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) { |
1776 | 1.75k | MCOperand &Op = Inst.getOperand(i); |
1777 | 1.75k | if (Op.isImm()) { |
1778 | 568 | int MemOffset = Op.getImm(); |
1779 | 568 | if (MemOffset < -32768 || MemOffset > 32767) { |
1780 | | // Offset can't exceed 16bit value. |
1781 | 241 | expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true); |
1782 | 241 | return false; |
1783 | 241 | } |
1784 | 1.18k | } else if (Op.isExpr()) { |
1785 | 308 | const MCExpr *Expr = Op.getExpr(); |
1786 | 308 | if (Expr->getKind() == MCExpr::SymbolRef) { |
1787 | 107 | const MCSymbolRefExpr *SR = |
1788 | 107 | static_cast<const MCSymbolRefExpr *>(Expr); |
1789 | 107 | if (SR->getKind() == MCSymbolRefExpr::VK_None) { |
1790 | | // Expand symbol. |
1791 | 107 | expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false); |
1792 | 107 | return false; |
1793 | 107 | } |
1794 | 201 | } else if (!isEvaluated(Expr)) { |
1795 | 201 | expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false); |
1796 | 201 | return false; |
1797 | 201 | } |
1798 | 308 | } |
1799 | 1.75k | } |
1800 | 2.65k | } // for |
1801 | 876 | } // if load/store |
1802 | | |
1803 | 14.2k | if (inMicroMipsMode()) { |
1804 | 0 | if (MCID.mayLoad()) { |
1805 | | // Try to create 16-bit GP relative load instruction. |
1806 | 0 | for (unsigned i = 0; i < MCID.getNumOperands(); i++) { |
1807 | 0 | const MCOperandInfo &OpInfo = MCID.OpInfo[i]; |
1808 | 0 | if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) || |
1809 | 0 | (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) { |
1810 | 0 | MCOperand &Op = Inst.getOperand(i); |
1811 | 0 | if (Op.isImm()) { |
1812 | 0 | int MemOffset = Op.getImm(); |
1813 | 0 | MCOperand &DstReg = Inst.getOperand(0); |
1814 | 0 | MCOperand &BaseReg = Inst.getOperand(1); |
1815 | 0 | if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) && |
1816 | 0 | getContext().getRegisterInfo()->getRegClass( |
1817 | 0 | Mips::GPRMM16RegClassID).contains(DstReg.getReg()) && |
1818 | 0 | (BaseReg.getReg() == Mips::GP || |
1819 | 0 | BaseReg.getReg() == Mips::GP_64)) { |
1820 | |
|
1821 | 0 | emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset, |
1822 | 0 | IDLoc, Instructions); |
1823 | 0 | return false; |
1824 | 0 | } |
1825 | 0 | } |
1826 | 0 | } |
1827 | 0 | } // for |
1828 | 0 | } // if load |
1829 | | |
1830 | | // TODO: Handle this with the AsmOperandClass.PredicateMethod. |
1831 | | |
1832 | 0 | MCOperand Opnd; |
1833 | 0 | int Imm; |
1834 | |
|
1835 | 0 | switch (Inst.getOpcode()) { |
1836 | 0 | default: |
1837 | 0 | break; |
1838 | 0 | case Mips::ADDIUS5_MM: |
1839 | 0 | Opnd = Inst.getOperand(2); |
1840 | 0 | if (!Opnd.isImm()) { |
1841 | 0 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
1842 | 0 | return true; |
1843 | | //return Error(IDLoc, "expected immediate operand kind"); |
1844 | 0 | } |
1845 | 0 | Imm = Opnd.getImm(); |
1846 | 0 | if (Imm < -8 || Imm > 7) { |
1847 | 0 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
1848 | 0 | return true; |
1849 | | //return Error(IDLoc, "immediate operand value out of range"); |
1850 | 0 | } |
1851 | 0 | break; |
1852 | 0 | case Mips::ADDIUSP_MM: |
1853 | 0 | Opnd = Inst.getOperand(0); |
1854 | 0 | if (!Opnd.isImm()) { |
1855 | 0 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
1856 | 0 | return true; |
1857 | | //return Error(IDLoc, "expected immediate operand kind"); |
1858 | 0 | } |
1859 | 0 | Imm = Opnd.getImm(); |
1860 | 0 | if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) || |
1861 | 0 | Imm % 4 != 0) { |
1862 | 0 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
1863 | 0 | return true; |
1864 | | //return Error(IDLoc, "immediate operand value out of range"); |
1865 | 0 | } |
1866 | 0 | break; |
1867 | 0 | case Mips::SLL16_MM: |
1868 | 0 | case Mips::SRL16_MM: |
1869 | 0 | Opnd = Inst.getOperand(2); |
1870 | 0 | if (!Opnd.isImm()) { |
1871 | 0 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
1872 | 0 | return true; |
1873 | | //return Error(IDLoc, "expected immediate operand kind"); |
1874 | 0 | } |
1875 | 0 | Imm = Opnd.getImm(); |
1876 | 0 | if (Imm < 1 || Imm > 8) { |
1877 | 0 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
1878 | 0 | return true; |
1879 | | //return Error(IDLoc, "immediate operand value out of range"); |
1880 | 0 | } |
1881 | 0 | break; |
1882 | 0 | case Mips::LI16_MM: |
1883 | 0 | Opnd = Inst.getOperand(1); |
1884 | 0 | if (!Opnd.isImm()) { |
1885 | 0 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
1886 | 0 | return true; |
1887 | | //return Error(IDLoc, "expected immediate operand kind"); |
1888 | 0 | } |
1889 | 0 | Imm = Opnd.getImm(); |
1890 | 0 | if (Imm < -1 || Imm > 126) { |
1891 | 0 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
1892 | 0 | return true; |
1893 | | //return Error(IDLoc, "immediate operand value out of range"); |
1894 | 0 | } |
1895 | 0 | break; |
1896 | 0 | case Mips::ADDIUR2_MM: |
1897 | 0 | Opnd = Inst.getOperand(2); |
1898 | 0 | if (!Opnd.isImm()) { |
1899 | 0 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
1900 | 0 | return true; |
1901 | | //return Error(IDLoc, "expected immediate operand kind"); |
1902 | 0 | } |
1903 | 0 | Imm = Opnd.getImm(); |
1904 | 0 | if (!(Imm == 1 || Imm == -1 || |
1905 | 0 | ((Imm % 4 == 0) && Imm < 28 && Imm > 0))) { |
1906 | 0 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
1907 | 0 | return true; |
1908 | | //return Error(IDLoc, "immediate operand value out of range"); |
1909 | 0 | } |
1910 | 0 | break; |
1911 | 0 | case Mips::ADDIUR1SP_MM: |
1912 | 0 | Opnd = Inst.getOperand(1); |
1913 | 0 | if (!Opnd.isImm()) { |
1914 | 0 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
1915 | 0 | return true; |
1916 | | //return Error(IDLoc, "expected immediate operand kind"); |
1917 | 0 | } |
1918 | 0 | Imm = Opnd.getImm(); |
1919 | 0 | if (OffsetToAlignment(Imm, 4LL)) { |
1920 | 0 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
1921 | 0 | return true; |
1922 | | //return Error(IDLoc, "misaligned immediate operand value"); |
1923 | 0 | } |
1924 | 0 | if (Imm < 0 || Imm > 255) { |
1925 | 0 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
1926 | 0 | return true; |
1927 | | //return Error(IDLoc, "immediate operand value out of range"); |
1928 | 0 | } |
1929 | 0 | break; |
1930 | 0 | case Mips::ANDI16_MM: |
1931 | 0 | Opnd = Inst.getOperand(2); |
1932 | 0 | if (!Opnd.isImm()) { |
1933 | 0 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
1934 | 0 | return true; |
1935 | | //return Error(IDLoc, "expected immediate operand kind"); |
1936 | 0 | } |
1937 | 0 | Imm = Opnd.getImm(); |
1938 | 0 | if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 || |
1939 | 0 | Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 || |
1940 | 0 | Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535)) { |
1941 | 0 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
1942 | 0 | return true; |
1943 | | //return Error(IDLoc, "immediate operand value out of range"); |
1944 | 0 | } |
1945 | 0 | break; |
1946 | 0 | case Mips::LBU16_MM: |
1947 | 0 | Opnd = Inst.getOperand(2); |
1948 | 0 | if (!Opnd.isImm()) { |
1949 | 0 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
1950 | 0 | return true; |
1951 | | //return Error(IDLoc, "expected immediate operand kind"); |
1952 | 0 | } |
1953 | 0 | Imm = Opnd.getImm(); |
1954 | 0 | if (Imm < -1 || Imm > 14) { |
1955 | 0 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
1956 | 0 | return true; |
1957 | | //return Error(IDLoc, "immediate operand value out of range"); |
1958 | 0 | } |
1959 | 0 | break; |
1960 | 0 | case Mips::SB16_MM: |
1961 | 0 | case Mips::SB16_MMR6: |
1962 | 0 | Opnd = Inst.getOperand(2); |
1963 | 0 | if (!Opnd.isImm()) { |
1964 | 0 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
1965 | 0 | return true; |
1966 | | //return Error(IDLoc, "expected immediate operand kind"); |
1967 | 0 | } |
1968 | 0 | Imm = Opnd.getImm(); |
1969 | 0 | if (Imm < 0 || Imm > 15) { |
1970 | 0 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
1971 | 0 | return true; |
1972 | | //return Error(IDLoc, "immediate operand value out of range"); |
1973 | 0 | } |
1974 | 0 | break; |
1975 | 0 | case Mips::LHU16_MM: |
1976 | 0 | case Mips::SH16_MM: |
1977 | 0 | case Mips::SH16_MMR6: |
1978 | 0 | Opnd = Inst.getOperand(2); |
1979 | 0 | if (!Opnd.isImm()) { |
1980 | 0 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
1981 | 0 | return true; |
1982 | | //return Error(IDLoc, "expected immediate operand kind"); |
1983 | 0 | } |
1984 | 0 | Imm = Opnd.getImm(); |
1985 | 0 | if (Imm < 0 || Imm > 30 || (Imm % 2 != 0)) { |
1986 | 0 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
1987 | 0 | return true; |
1988 | | //return Error(IDLoc, "immediate operand value out of range"); |
1989 | 0 | } |
1990 | 0 | break; |
1991 | 0 | case Mips::LW16_MM: |
1992 | 0 | case Mips::SW16_MM: |
1993 | 0 | case Mips::SW16_MMR6: |
1994 | 0 | Opnd = Inst.getOperand(2); |
1995 | 0 | if (!Opnd.isImm()) { |
1996 | 0 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
1997 | 0 | return true; |
1998 | | //return Error(IDLoc, "expected immediate operand kind"); |
1999 | 0 | } |
2000 | 0 | Imm = Opnd.getImm(); |
2001 | 0 | if (Imm < 0 || Imm > 60 || (Imm % 4 != 0)) { |
2002 | 0 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
2003 | 0 | return true; |
2004 | | //return Error(IDLoc, "immediate operand value out of range"); |
2005 | 0 | } |
2006 | 0 | break; |
2007 | 0 | case Mips::ADDIUPC_MM: |
2008 | 0 | MCOperand Opnd = Inst.getOperand(1); |
2009 | 0 | if (!Opnd.isImm()) { |
2010 | 0 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
2011 | 0 | return true; |
2012 | | //return Error(IDLoc, "expected immediate operand kind"); |
2013 | 0 | } |
2014 | 0 | int Imm = Opnd.getImm(); |
2015 | 0 | if ((Imm % 4 != 0) || !isInt<25>(Imm)) { |
2016 | 0 | KsError = KS_ERR_ASM_INVALIDOPERAND; |
2017 | 0 | return true; |
2018 | | //return Error(IDLoc, "immediate operand value out of range"); |
2019 | 0 | } |
2020 | 0 | break; |
2021 | 0 | } |
2022 | 0 | } |
2023 | | |
2024 | 14.2k | MacroExpanderResultTy ExpandResult = |
2025 | 14.2k | tryExpandInstruction(Inst, IDLoc, Instructions); |
2026 | 14.2k | switch (ExpandResult) { |
2027 | 13.1k | case MER_NotAMacro: |
2028 | 13.1k | Instructions.push_back(Inst); |
2029 | 13.1k | break; |
2030 | 1.06k | case MER_Success: |
2031 | 1.06k | break; |
2032 | 7 | case MER_Fail: |
2033 | 7 | return true; |
2034 | 14.2k | } |
2035 | | |
2036 | | // If this instruction has a delay slot and .set reorder is active, |
2037 | | // emit a NOP after it. |
2038 | 14.2k | if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) |
2039 | 11.8k | createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions); |
2040 | | |
2041 | 14.2k | if ((Inst.getOpcode() == Mips::JalOneReg || |
2042 | 14.2k | Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) && |
2043 | 21 | isPicAndNotNxxAbi()) { |
2044 | 0 | if (IsCpRestoreSet) { |
2045 | | // We need a NOP between the JALR and the LW: |
2046 | | // If .set reorder has been used, we've already emitted a NOP. |
2047 | | // If .set noreorder has been used, we need to emit a NOP at this point. |
2048 | 0 | if (!AssemblerOptions.back()->isReorder()) |
2049 | 0 | createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions); |
2050 | | |
2051 | | // Load the $gp from the stack. |
2052 | 0 | SmallVector<MCInst, 3> LoadInsts; |
2053 | 0 | createCpRestoreMemOp(true /*IsLoad*/, CpRestoreOffset /*StackOffset*/, |
2054 | 0 | IDLoc, LoadInsts); |
2055 | |
|
2056 | 0 | for (const MCInst &Inst : LoadInsts) |
2057 | 0 | Instructions.push_back(Inst); |
2058 | |
|
2059 | 0 | } else { |
2060 | | // Warning(IDLoc, "no .cprestore used in PIC mode"); |
2061 | 0 | } |
2062 | 0 | } |
2063 | | |
2064 | 14.2k | return false; |
2065 | 14.2k | } |
2066 | | |
2067 | | MipsAsmParser::MacroExpanderResultTy |
2068 | | MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, |
2069 | 14.2k | SmallVectorImpl<MCInst> &Instructions) { |
2070 | 14.2k | switch (Inst.getOpcode()) { |
2071 | 12.4k | default: |
2072 | 12.4k | return MER_NotAMacro; |
2073 | 4 | case Mips::LoadImm32: |
2074 | 4 | return expandLoadImm(Inst, true, IDLoc, Instructions) ? MER_Fail |
2075 | 4 | : MER_Success; |
2076 | 0 | case Mips::LoadImm64: |
2077 | 0 | return expandLoadImm(Inst, false, IDLoc, Instructions) ? MER_Fail |
2078 | 0 | : MER_Success; |
2079 | 22 | case Mips::LoadAddrImm32: |
2080 | 33 | case Mips::LoadAddrImm64: |
2081 | 33 | assert(Inst.getOperand(0).isReg() && "expected register operand kind"); |
2082 | 33 | assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) && |
2083 | 33 | "expected immediate operand kind"); |
2084 | | |
2085 | 33 | return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister, |
2086 | 33 | Inst.getOperand(1), |
2087 | 33 | Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc, |
2088 | 33 | Instructions) |
2089 | 33 | ? MER_Fail |
2090 | 33 | : MER_Success; |
2091 | 0 | case Mips::LoadAddrReg32: |
2092 | 0 | case Mips::LoadAddrReg64: |
2093 | 0 | assert(Inst.getOperand(0).isReg() && "expected register operand kind"); |
2094 | 0 | assert(Inst.getOperand(1).isReg() && "expected register operand kind"); |
2095 | 0 | assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) && |
2096 | 0 | "expected immediate operand kind"); |
2097 | | |
2098 | 0 | return expandLoadAddress(Inst.getOperand(0).getReg(), |
2099 | 0 | Inst.getOperand(1).getReg(), Inst.getOperand(2), |
2100 | 0 | Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc, |
2101 | 0 | Instructions) |
2102 | 0 | ? MER_Fail |
2103 | 0 | : MER_Success; |
2104 | 0 | case Mips::B_MM_Pseudo: |
2105 | 0 | case Mips::B_MMR6_Pseudo: |
2106 | 0 | return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions) ? MER_Fail |
2107 | 0 | : MER_Success; |
2108 | 0 | case Mips::SWM_MM: |
2109 | 0 | case Mips::LWM_MM: |
2110 | 0 | return expandLoadStoreMultiple(Inst, IDLoc, Instructions) ? MER_Fail |
2111 | 0 | : MER_Success; |
2112 | 11 | case Mips::JalOneReg: |
2113 | 11 | case Mips::JalTwoReg: |
2114 | 11 | return expandJalWithRegs(Inst, IDLoc, Instructions) ? MER_Fail |
2115 | 11 | : MER_Success; |
2116 | 0 | case Mips::BneImm: |
2117 | 0 | case Mips::BeqImm: |
2118 | 0 | return expandBranchImm(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success; |
2119 | 0 | case Mips::BLT: |
2120 | 0 | case Mips::BLE: |
2121 | 0 | case Mips::BGE: |
2122 | 0 | case Mips::BGT: |
2123 | 0 | case Mips::BLTU: |
2124 | 0 | case Mips::BLEU: |
2125 | 0 | case Mips::BGEU: |
2126 | 0 | case Mips::BGTU: |
2127 | 0 | case Mips::BLTL: |
2128 | 0 | case Mips::BLEL: |
2129 | 0 | case Mips::BGEL: |
2130 | 0 | case Mips::BGTL: |
2131 | 0 | case Mips::BLTUL: |
2132 | 0 | case Mips::BLEUL: |
2133 | 0 | case Mips::BGEUL: |
2134 | 0 | case Mips::BGTUL: |
2135 | 0 | case Mips::BLTImmMacro: |
2136 | 0 | case Mips::BLEImmMacro: |
2137 | 0 | case Mips::BGEImmMacro: |
2138 | 0 | case Mips::BGTImmMacro: |
2139 | 0 | case Mips::BLTUImmMacro: |
2140 | 0 | case Mips::BLEUImmMacro: |
2141 | 0 | case Mips::BGEUImmMacro: |
2142 | 0 | case Mips::BGTUImmMacro: |
2143 | 0 | case Mips::BLTLImmMacro: |
2144 | 0 | case Mips::BLELImmMacro: |
2145 | 0 | case Mips::BGELImmMacro: |
2146 | 0 | case Mips::BGTLImmMacro: |
2147 | 0 | case Mips::BLTULImmMacro: |
2148 | 0 | case Mips::BLEULImmMacro: |
2149 | 0 | case Mips::BGEULImmMacro: |
2150 | 0 | case Mips::BGTULImmMacro: |
2151 | 0 | return expandCondBranches(Inst, IDLoc, Instructions) ? MER_Fail |
2152 | 0 | : MER_Success; |
2153 | 0 | case Mips::SDivMacro: |
2154 | 0 | return expandDiv(Inst, IDLoc, Instructions, false, true) ? MER_Fail |
2155 | 0 | : MER_Success; |
2156 | 0 | case Mips::DSDivMacro: |
2157 | 0 | return expandDiv(Inst, IDLoc, Instructions, true, true) ? MER_Fail |
2158 | 0 | : MER_Success; |
2159 | 0 | case Mips::UDivMacro: |
2160 | 0 | return expandDiv(Inst, IDLoc, Instructions, false, false) ? MER_Fail |
2161 | 0 | : MER_Success; |
2162 | 0 | case Mips::DUDivMacro: |
2163 | 0 | return expandDiv(Inst, IDLoc, Instructions, true, false) ? MER_Fail |
2164 | 0 | : MER_Success; |
2165 | 0 | case Mips::Ulh: |
2166 | 0 | return expandUlh(Inst, true, IDLoc, Instructions) ? MER_Fail : MER_Success; |
2167 | 0 | case Mips::Ulhu: |
2168 | 0 | return expandUlh(Inst, false, IDLoc, Instructions) ? MER_Fail : MER_Success; |
2169 | 0 | case Mips::Ulw: |
2170 | 0 | return expandUlw(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success; |
2171 | 0 | case Mips::NORImm: |
2172 | 0 | return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail |
2173 | 0 | : MER_Success; |
2174 | 0 | case Mips::ADDi: |
2175 | 0 | case Mips::ADDiu: |
2176 | 0 | case Mips::SLTi: |
2177 | 0 | case Mips::SLTiu: |
2178 | 0 | if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() && |
2179 | 0 | Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) { |
2180 | 0 | int64_t ImmValue = Inst.getOperand(2).getImm(); |
2181 | 0 | if (isInt<16>(ImmValue)) |
2182 | 0 | return MER_NotAMacro; |
2183 | 0 | return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail |
2184 | 0 | : MER_Success; |
2185 | 0 | } |
2186 | 0 | return MER_NotAMacro; |
2187 | 1 | case Mips::ANDi: |
2188 | 1.72k | case Mips::ORi: |
2189 | 1.73k | case Mips::XORi: |
2190 | 1.73k | if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() && |
2191 | 1.73k | Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) { |
2192 | 1.17k | int64_t ImmValue = Inst.getOperand(2).getImm(); |
2193 | 1.17k | if (isUInt<16>(ImmValue)) |
2194 | 201 | return MER_NotAMacro; |
2195 | 973 | return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail |
2196 | 973 | : MER_Success; |
2197 | 1.17k | } |
2198 | 558 | return MER_NotAMacro; |
2199 | 0 | case Mips::ROL: |
2200 | 0 | case Mips::ROR: |
2201 | 0 | return expandRotation(Inst, IDLoc, Instructions) ? MER_Fail |
2202 | 0 | : MER_Success; |
2203 | 0 | case Mips::ROLImm: |
2204 | 18 | case Mips::RORImm: |
2205 | 18 | return expandRotationImm(Inst, IDLoc, Instructions) ? MER_Fail |
2206 | 18 | : MER_Success; |
2207 | 0 | case Mips::DROL: |
2208 | 0 | case Mips::DROR: |
2209 | 0 | return expandDRotation(Inst, IDLoc, Instructions) ? MER_Fail |
2210 | 0 | : MER_Success; |
2211 | 2 | case Mips::DROLImm: |
2212 | 2 | case Mips::DRORImm: |
2213 | 2 | return expandDRotationImm(Inst, IDLoc, Instructions) ? MER_Fail |
2214 | 2 | : MER_Success; |
2215 | 32 | case Mips::ABSMacro: |
2216 | 32 | return expandAbs(Inst, IDLoc, Instructions) ? MER_Fail |
2217 | 32 | : MER_Success; |
2218 | 14.2k | } |
2219 | 14.2k | } |
2220 | | |
2221 | | bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, |
2222 | 11 | SmallVectorImpl<MCInst> &Instructions) { |
2223 | | // Create a JALR instruction which is going to replace the pseudo-JAL. |
2224 | 11 | MCInst JalrInst; |
2225 | 11 | JalrInst.setLoc(IDLoc); |
2226 | 11 | const MCOperand FirstRegOp = Inst.getOperand(0); |
2227 | 11 | const unsigned Opcode = Inst.getOpcode(); |
2228 | | |
2229 | 11 | if (Opcode == Mips::JalOneReg) { |
2230 | | // jal $rs => jalr $rs |
2231 | 11 | if (IsCpRestoreSet && inMicroMipsMode()) { |
2232 | 0 | JalrInst.setOpcode(Mips::JALRS16_MM); |
2233 | 0 | JalrInst.addOperand(FirstRegOp); |
2234 | 11 | } else if (inMicroMipsMode()) { |
2235 | 0 | JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM); |
2236 | 0 | JalrInst.addOperand(FirstRegOp); |
2237 | 11 | } else { |
2238 | 11 | JalrInst.setOpcode(Mips::JALR); |
2239 | 11 | JalrInst.addOperand(MCOperand::createReg(Mips::RA)); |
2240 | 11 | JalrInst.addOperand(FirstRegOp); |
2241 | 11 | } |
2242 | 11 | } else if (Opcode == Mips::JalTwoReg) { |
2243 | | // jal $rd, $rs => jalr $rd, $rs |
2244 | 0 | if (IsCpRestoreSet && inMicroMipsMode()) |
2245 | 0 | JalrInst.setOpcode(Mips::JALRS_MM); |
2246 | 0 | else |
2247 | 0 | JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR); |
2248 | 0 | JalrInst.addOperand(FirstRegOp); |
2249 | 0 | const MCOperand SecondRegOp = Inst.getOperand(1); |
2250 | 0 | JalrInst.addOperand(SecondRegOp); |
2251 | 0 | } |
2252 | 11 | Instructions.push_back(JalrInst); |
2253 | | |
2254 | | // If .set reorder is active and branch instruction has a delay slot, |
2255 | | // emit a NOP after it. |
2256 | 11 | const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode()); |
2257 | 11 | if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) { |
2258 | 11 | createNop(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, Instructions); |
2259 | 11 | } |
2260 | | |
2261 | 11 | return false; |
2262 | 11 | } |
2263 | | |
2264 | | /// Can the value be represented by a unsigned N-bit value and a shift left? |
2265 | 661 | template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) { |
2266 | 661 | unsigned BitNum = findFirstSet(x); |
2267 | | |
2268 | 661 | return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum); |
2269 | 661 | } |
2270 | | |
2271 | | /// Load (or add) an immediate into a register. |
2272 | | /// |
2273 | | /// @param ImmValue The immediate to load. |
2274 | | /// @param DstReg The register that will hold the immediate. |
2275 | | /// @param SrcReg A register to add to the immediate or Mips::NoRegister |
2276 | | /// for a simple initialization. |
2277 | | /// @param Is32BitImm Is ImmValue 32-bit or 64-bit? |
2278 | | /// @param IsAddress True if the immediate represents an address. False if it |
2279 | | /// is an integer. |
2280 | | /// @param IDLoc Location of the immediate in the source file. |
2281 | | /// @param Instructions The instructions emitted by this expansion. |
2282 | | bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg, |
2283 | | unsigned SrcReg, bool Is32BitImm, |
2284 | | bool IsAddress, SMLoc IDLoc, |
2285 | 1.49k | SmallVectorImpl<MCInst> &Instructions) { |
2286 | 1.49k | if (!Is32BitImm && !isGP64bit()) { |
2287 | 1 | Error(IDLoc, "instruction requires a 64-bit architecture"); |
2288 | 1 | return true; |
2289 | 1 | } |
2290 | | |
2291 | 1.49k | if (Is32BitImm) { |
2292 | 822 | if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) { |
2293 | | // Sign extend up to 64-bit so that the predicates match the hardware |
2294 | | // behaviour. In particular, isInt<16>(0xffff8000) and similar should be |
2295 | | // true. |
2296 | 819 | ImmValue = SignExtend64<32>(ImmValue); |
2297 | 819 | } else { |
2298 | 3 | Error(IDLoc, "instruction requires a 32-bit immediate"); |
2299 | 3 | return true; |
2300 | 3 | } |
2301 | 822 | } |
2302 | | |
2303 | 1.49k | unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg(); |
2304 | 1.49k | unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu; |
2305 | | |
2306 | 1.49k | bool UseSrcReg = false; |
2307 | 1.49k | if (SrcReg != Mips::NoRegister) |
2308 | 0 | UseSrcReg = true; |
2309 | | |
2310 | 1.49k | unsigned TmpReg = DstReg; |
2311 | 1.49k | if (UseSrcReg && |
2312 | 0 | getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) { |
2313 | | // At this point we need AT to perform the expansions and we exit if it is |
2314 | | // not available. |
2315 | 0 | unsigned ATReg = getATReg(IDLoc); |
2316 | 0 | if (!ATReg) |
2317 | 0 | return true; |
2318 | 0 | TmpReg = ATReg; |
2319 | 0 | } |
2320 | | |
2321 | 1.49k | if (isInt<16>(ImmValue)) { |
2322 | 531 | if (!UseSrcReg) |
2323 | 531 | SrcReg = ZeroReg; |
2324 | | |
2325 | | // This doesn't quite follow the usual ABI expectations for N32 but matches |
2326 | | // traditional assembler behaviour. N32 would normally use addiu for both |
2327 | | // integers and addresses. |
2328 | 531 | if (IsAddress && !Is32BitImm) { |
2329 | 4 | emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions); |
2330 | 4 | return false; |
2331 | 4 | } |
2332 | | |
2333 | 527 | emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions); |
2334 | 527 | return false; |
2335 | 531 | } |
2336 | | |
2337 | 962 | if (isUInt<16>(ImmValue)) { |
2338 | 11 | unsigned TmpReg = DstReg; |
2339 | 11 | if (SrcReg == DstReg) { |
2340 | 0 | TmpReg = getATReg(IDLoc); |
2341 | 0 | if (!TmpReg) |
2342 | 0 | return true; |
2343 | 0 | } |
2344 | | |
2345 | 11 | emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, Instructions); |
2346 | 11 | if (UseSrcReg) |
2347 | 0 | emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, Instructions); |
2348 | 11 | return false; |
2349 | 11 | } |
2350 | | |
2351 | 951 | if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) { |
2352 | 290 | warnIfNoMacro(IDLoc); |
2353 | | |
2354 | 290 | uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff; |
2355 | 290 | uint16_t Bits15To0 = ImmValue & 0xffff; |
2356 | | |
2357 | 290 | if (!Is32BitImm && !isInt<32>(ImmValue)) { |
2358 | | // Traditional behaviour seems to special case this particular value. It's |
2359 | | // not clear why other masks are handled differently. |
2360 | 0 | if (ImmValue == 0xffffffff) { |
2361 | 0 | emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, Instructions); |
2362 | 0 | emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, Instructions); |
2363 | 0 | if (UseSrcReg) |
2364 | 0 | emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions); |
2365 | 0 | return false; |
2366 | 0 | } |
2367 | | |
2368 | | // Expand to an ORi instead of a LUi to avoid sign-extending into the |
2369 | | // upper 32 bits. |
2370 | 0 | emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, Instructions); |
2371 | 0 | emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions); |
2372 | 0 | if (Bits15To0) |
2373 | 0 | emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions); |
2374 | 0 | if (UseSrcReg) |
2375 | 0 | emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions); |
2376 | 0 | return false; |
2377 | 0 | } |
2378 | | |
2379 | 290 | emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions); |
2380 | 290 | if (Bits15To0) |
2381 | 265 | emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions); |
2382 | 290 | if (UseSrcReg) |
2383 | 0 | emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions); |
2384 | 290 | return false; |
2385 | 290 | } |
2386 | | |
2387 | 661 | if (isShiftedUIntAtAnyPosition<16>(ImmValue)) { |
2388 | 153 | if (Is32BitImm) { |
2389 | 0 | Error(IDLoc, "instruction requires a 32-bit immediate"); |
2390 | 0 | return true; |
2391 | 0 | } |
2392 | | |
2393 | | // Traditionally, these immediates are shifted as little as possible and as |
2394 | | // such we align the most significant bit to bit 15 of our temporary. |
2395 | 153 | unsigned FirstSet = findFirstSet((uint64_t)ImmValue); |
2396 | 153 | unsigned LastSet = findLastSet((uint64_t)ImmValue); |
2397 | 153 | unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet)); |
2398 | 153 | uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff; |
2399 | 153 | emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, Instructions); |
2400 | 153 | emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, Instructions); |
2401 | | |
2402 | 153 | if (UseSrcReg) |
2403 | 0 | emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions); |
2404 | | |
2405 | 153 | return false; |
2406 | 153 | } |
2407 | | |
2408 | 508 | warnIfNoMacro(IDLoc); |
2409 | | |
2410 | | // The remaining case is packed with a sequence of dsll and ori with zeros |
2411 | | // being omitted and any neighbouring dsll's being coalesced. |
2412 | | // The highest 32-bit's are equivalent to a 32-bit immediate load. |
2413 | | |
2414 | | // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register. |
2415 | 508 | if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false, |
2416 | 508 | IDLoc, Instructions)) |
2417 | 0 | return false; |
2418 | | |
2419 | | // Shift and accumulate into the register. If a 16-bit chunk is zero, then |
2420 | | // skip it and defer the shift to the next chunk. |
2421 | 508 | unsigned ShiftCarriedForwards = 16; |
2422 | 1.52k | for (int BitNum = 16; BitNum >= 0; BitNum -= 16) { |
2423 | 1.01k | uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff; |
2424 | | |
2425 | 1.01k | if (ImmChunk != 0) { |
2426 | 871 | emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, |
2427 | 871 | Instructions); |
2428 | 871 | emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, Instructions); |
2429 | 871 | ShiftCarriedForwards = 0; |
2430 | 871 | } |
2431 | | |
2432 | 1.01k | ShiftCarriedForwards += 16; |
2433 | 1.01k | } |
2434 | 508 | ShiftCarriedForwards -= 16; |
2435 | | |
2436 | | // Finish any remaining shifts left by trailing zeros. |
2437 | 508 | if (ShiftCarriedForwards) |
2438 | 108 | emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, |
2439 | 108 | Instructions); |
2440 | | |
2441 | 508 | if (UseSrcReg) |
2442 | 0 | emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions); |
2443 | | |
2444 | 508 | return false; |
2445 | 508 | } |
2446 | | |
2447 | | bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc, |
2448 | 4 | SmallVectorImpl<MCInst> &Instructions) { |
2449 | 4 | const MCOperand &ImmOp = Inst.getOperand(1); |
2450 | 4 | assert(ImmOp.isImm() && "expected immediate operand kind"); |
2451 | 4 | const MCOperand &DstRegOp = Inst.getOperand(0); |
2452 | 4 | assert(DstRegOp.isReg() && "expected register operand kind"); |
2453 | | |
2454 | 4 | if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister, |
2455 | 4 | Is32BitImm, false, IDLoc, Instructions)) |
2456 | 3 | return true; |
2457 | | |
2458 | 1 | return false; |
2459 | 4 | } |
2460 | | |
2461 | | bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg, |
2462 | | const MCOperand &Offset, |
2463 | | bool Is32BitAddress, SMLoc IDLoc, |
2464 | 33 | SmallVectorImpl<MCInst> &Instructions) { |
2465 | | // la can't produce a usable address when addresses are 64-bit. |
2466 | 33 | if (Is32BitAddress && ABI.ArePtrs64bit()) { |
2467 | | // FIXME: Demote this to a warning and continue as if we had 'dla' instead. |
2468 | | // We currently can't do this because we depend on the equality |
2469 | | // operator and N64 can end up with a GPR32/GPR64 mismatch. |
2470 | 22 | Error(IDLoc, "la used to load 64-bit address"); |
2471 | | // Continue as if we had 'dla' instead. |
2472 | 22 | Is32BitAddress = false; |
2473 | 22 | } |
2474 | | |
2475 | | // dla requires 64-bit addresses. |
2476 | 33 | if (!Is32BitAddress && !hasMips3()) { |
2477 | 1 | Error(IDLoc, "instruction requires a 64-bit architecture"); |
2478 | 1 | return true; |
2479 | 1 | } |
2480 | | |
2481 | 32 | if (!Offset.isImm()) |
2482 | 19 | return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg, |
2483 | 19 | Is32BitAddress, IDLoc, Instructions); |
2484 | | |
2485 | 13 | if (!ABI.ArePtrs64bit()) { |
2486 | | // Continue as if we had 'la' whether we had 'la' or 'dla'. |
2487 | 0 | Is32BitAddress = true; |
2488 | 0 | } |
2489 | | |
2490 | 13 | return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true, |
2491 | 13 | IDLoc, Instructions); |
2492 | 32 | } |
2493 | | |
2494 | | bool MipsAsmParser::loadAndAddSymbolAddress( |
2495 | | const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym, |
2496 | 19 | SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { |
2497 | 19 | warnIfNoMacro(IDLoc); |
2498 | | |
2499 | 19 | const MCExpr *Symbol = cast<MCExpr>(SymExpr); |
2500 | 19 | const MipsMCExpr *HiExpr = MipsMCExpr::create( |
2501 | 19 | MCSymbolRefExpr::VK_Mips_ABS_HI, Symbol, getContext()); |
2502 | 19 | const MipsMCExpr *LoExpr = MipsMCExpr::create( |
2503 | 19 | MCSymbolRefExpr::VK_Mips_ABS_LO, Symbol, getContext()); |
2504 | | |
2505 | 19 | bool UseSrcReg = SrcReg != Mips::NoRegister; |
2506 | | |
2507 | | // This is the 64-bit symbol address expansion. |
2508 | 19 | if (ABI.ArePtrs64bit() && isGP64bit()) { |
2509 | | // We always need AT for the 64-bit expansion. |
2510 | | // If it is not available we exit. |
2511 | 19 | unsigned ATReg = getATReg(IDLoc); |
2512 | 19 | if (!ATReg) |
2513 | 1 | return true; |
2514 | | |
2515 | 18 | const MipsMCExpr *HighestExpr = MipsMCExpr::create( |
2516 | 18 | MCSymbolRefExpr::VK_Mips_HIGHEST, Symbol, getContext()); |
2517 | 18 | const MipsMCExpr *HigherExpr = MipsMCExpr::create( |
2518 | 18 | MCSymbolRefExpr::VK_Mips_HIGHER, Symbol, getContext()); |
2519 | | |
2520 | 18 | if (UseSrcReg && |
2521 | 0 | getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, |
2522 | 0 | SrcReg)) { |
2523 | | // If $rs is the same as $rd: |
2524 | | // (d)la $rd, sym($rd) => lui $at, %highest(sym) |
2525 | | // daddiu $at, $at, %higher(sym) |
2526 | | // dsll $at, $at, 16 |
2527 | | // daddiu $at, $at, %hi(sym) |
2528 | | // dsll $at, $at, 16 |
2529 | | // daddiu $at, $at, %lo(sym) |
2530 | | // daddu $rd, $at, $rd |
2531 | 0 | emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc, |
2532 | 0 | Instructions); |
2533 | 0 | emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr), |
2534 | 0 | IDLoc, Instructions); |
2535 | 0 | emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions); |
2536 | 0 | emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc, |
2537 | 0 | Instructions); |
2538 | 0 | emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions); |
2539 | 0 | emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc, |
2540 | 0 | Instructions); |
2541 | 0 | emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions); |
2542 | |
|
2543 | 0 | return false; |
2544 | 0 | } |
2545 | | |
2546 | | // Otherwise, if the $rs is different from $rd or if $rs isn't specified: |
2547 | | // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym) |
2548 | | // lui $at, %hi(sym) |
2549 | | // daddiu $rd, $rd, %higher(sym) |
2550 | | // daddiu $at, $at, %lo(sym) |
2551 | | // dsll32 $rd, $rd, 0 |
2552 | | // daddu $rd, $rd, $at |
2553 | | // (daddu $rd, $rd, $rs) |
2554 | 18 | emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc, |
2555 | 18 | Instructions); |
2556 | 18 | emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, |
2557 | 18 | Instructions); |
2558 | 18 | emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr), |
2559 | 18 | IDLoc, Instructions); |
2560 | 18 | emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc, |
2561 | 18 | Instructions); |
2562 | 18 | emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions); |
2563 | 18 | emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions); |
2564 | 18 | if (UseSrcReg) |
2565 | 0 | emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions); |
2566 | | |
2567 | 18 | return false; |
2568 | 18 | } |
2569 | | |
2570 | | // And now, the 32-bit symbol address expansion: |
2571 | | // If $rs is the same as $rd: |
2572 | | // (d)la $rd, sym($rd) => lui $at, %hi(sym) |
2573 | | // ori $at, $at, %lo(sym) |
2574 | | // addu $rd, $at, $rd |
2575 | | // Otherwise, if the $rs is different from $rd or if $rs isn't specified: |
2576 | | // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym) |
2577 | | // ori $rd, $rd, %lo(sym) |
2578 | | // (addu $rd, $rd, $rs) |
2579 | 0 | unsigned TmpReg = DstReg; |
2580 | 0 | if (UseSrcReg && |
2581 | 0 | getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) { |
2582 | | // If $rs is the same as $rd, we need to use AT. |
2583 | | // If it is not available we exit. |
2584 | 0 | unsigned ATReg = getATReg(IDLoc); |
2585 | 0 | if (!ATReg) |
2586 | 0 | return true; |
2587 | 0 | TmpReg = ATReg; |
2588 | 0 | } |
2589 | | |
2590 | 0 | emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions); |
2591 | 0 | emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc, |
2592 | 0 | Instructions); |
2593 | |
|
2594 | 0 | if (UseSrcReg) |
2595 | 0 | emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions); |
2596 | 0 | else |
2597 | 0 | assert( |
2598 | 0 | getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg)); |
2599 | | |
2600 | 0 | return false; |
2601 | 0 | } |
2602 | | |
2603 | | bool MipsAsmParser::expandUncondBranchMMPseudo( |
2604 | 0 | MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { |
2605 | 0 | assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 && |
2606 | 0 | "unexpected number of operands"); |
2607 | | |
2608 | 0 | MCOperand Offset = Inst.getOperand(0); |
2609 | 0 | if (Offset.isExpr()) { |
2610 | 0 | Inst.clear(); |
2611 | 0 | Inst.setOpcode(Mips::BEQ_MM); |
2612 | 0 | Inst.addOperand(MCOperand::createReg(Mips::ZERO)); |
2613 | 0 | Inst.addOperand(MCOperand::createReg(Mips::ZERO)); |
2614 | 0 | Inst.addOperand(MCOperand::createExpr(Offset.getExpr())); |
2615 | 0 | } else { |
2616 | 0 | assert(Offset.isImm() && "expected immediate operand kind"); |
2617 | 0 | if (isInt<11>(Offset.getImm())) { |
2618 | | // If offset fits into 11 bits then this instruction becomes microMIPS |
2619 | | // 16-bit unconditional branch instruction. |
2620 | 0 | if (inMicroMipsMode()) |
2621 | 0 | Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM); |
2622 | 0 | } else { |
2623 | 0 | if (!isInt<17>(Offset.getImm())) |
2624 | 0 | Error(IDLoc, "branch target out of range"); |
2625 | 0 | if (OffsetToAlignment(Offset.getImm(), 1LL << 1)) |
2626 | 0 | Error(IDLoc, "branch to misaligned address"); |
2627 | 0 | Inst.clear(); |
2628 | 0 | Inst.setOpcode(Mips::BEQ_MM); |
2629 | 0 | Inst.addOperand(MCOperand::createReg(Mips::ZERO)); |
2630 | 0 | Inst.addOperand(MCOperand::createReg(Mips::ZERO)); |
2631 | 0 | Inst.addOperand(MCOperand::createImm(Offset.getImm())); |
2632 | 0 | } |
2633 | 0 | } |
2634 | 0 | Instructions.push_back(Inst); |
2635 | | |
2636 | | // If .set reorder is active and branch instruction has a delay slot, |
2637 | | // emit a NOP after it. |
2638 | 0 | const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode()); |
2639 | 0 | if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) |
2640 | 0 | createNop(true, IDLoc, Instructions); |
2641 | |
|
2642 | 0 | return false; |
2643 | 0 | } |
2644 | | |
2645 | | bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, |
2646 | 0 | SmallVectorImpl<MCInst> &Instructions) { |
2647 | 0 | const MCOperand &DstRegOp = Inst.getOperand(0); |
2648 | 0 | assert(DstRegOp.isReg() && "expected register operand kind"); |
2649 | | |
2650 | 0 | const MCOperand &ImmOp = Inst.getOperand(1); |
2651 | 0 | assert(ImmOp.isImm() && "expected immediate operand kind"); |
2652 | | |
2653 | 0 | const MCOperand &MemOffsetOp = Inst.getOperand(2); |
2654 | 0 | assert(MemOffsetOp.isImm() && "expected immediate operand kind"); |
2655 | | |
2656 | 0 | unsigned OpCode = 0; |
2657 | 0 | switch(Inst.getOpcode()) { |
2658 | 0 | case Mips::BneImm: |
2659 | 0 | OpCode = Mips::BNE; |
2660 | 0 | break; |
2661 | 0 | case Mips::BeqImm: |
2662 | 0 | OpCode = Mips::BEQ; |
2663 | 0 | break; |
2664 | 0 | default: |
2665 | 0 | llvm_unreachable("Unknown immediate branch pseudo-instruction."); |
2666 | 0 | break; |
2667 | 0 | } |
2668 | | |
2669 | 0 | int64_t ImmValue = ImmOp.getImm(); |
2670 | 0 | if (ImmValue == 0) |
2671 | 0 | emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc, |
2672 | 0 | Instructions); |
2673 | 0 | else { |
2674 | 0 | warnIfNoMacro(IDLoc); |
2675 | |
|
2676 | 0 | unsigned ATReg = getATReg(IDLoc); |
2677 | 0 | if (!ATReg) |
2678 | 0 | return true; |
2679 | | |
2680 | 0 | if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true, |
2681 | 0 | IDLoc, Instructions)) |
2682 | 0 | return true; |
2683 | | |
2684 | 0 | emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, Instructions); |
2685 | 0 | } |
2686 | 0 | return false; |
2687 | 0 | } |
2688 | | |
2689 | | void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, |
2690 | | SmallVectorImpl<MCInst> &Instructions, |
2691 | 551 | bool isLoad, bool isImmOpnd) { |
2692 | 551 | unsigned ImmOffset, HiOffset, LoOffset; |
2693 | 551 | const MCExpr *ExprOffset; |
2694 | 551 | unsigned TmpRegNum; |
2695 | | // 1st operand is either the source or destination register. |
2696 | 551 | assert(Inst.getOperand(0).isReg() && "expected register operand kind"); |
2697 | 551 | unsigned RegOpNum = Inst.getOperand(0).getReg(); |
2698 | | // 2nd operand is the base register. |
2699 | 551 | assert(Inst.getOperand(1).isReg() && "expected register operand kind"); |
2700 | 551 | unsigned BaseRegNum = Inst.getOperand(1).getReg(); |
2701 | | // 3rd operand is either an immediate or expression. |
2702 | 551 | if (isImmOpnd) { |
2703 | 243 | assert(Inst.getOperand(2).isImm() && "expected immediate operand kind"); |
2704 | 243 | ImmOffset = Inst.getOperand(2).getImm(); |
2705 | 243 | LoOffset = ImmOffset & 0x0000ffff; |
2706 | 243 | HiOffset = (ImmOffset & 0xffff0000) >> 16; |
2707 | | // If msb of LoOffset is 1(negative number) we must increment HiOffset. |
2708 | 243 | if (LoOffset & 0x8000) |
2709 | 79 | HiOffset++; |
2710 | 243 | } else |
2711 | 308 | ExprOffset = Inst.getOperand(2).getExpr(); |
2712 | | // These are some of the types of expansions we perform here: |
2713 | | // 1) lw $8, sym => lui $8, %hi(sym) |
2714 | | // lw $8, %lo(sym)($8) |
2715 | | // 2) lw $8, offset($9) => lui $8, %hi(offset) |
2716 | | // add $8, $8, $9 |
2717 | | // lw $8, %lo(offset)($9) |
2718 | | // 3) lw $8, offset($8) => lui $at, %hi(offset) |
2719 | | // add $at, $at, $8 |
2720 | | // lw $8, %lo(offset)($at) |
2721 | | // 4) sw $8, sym => lui $at, %hi(sym) |
2722 | | // sw $8, %lo(sym)($at) |
2723 | | // 5) sw $8, offset($8) => lui $at, %hi(offset) |
2724 | | // add $at, $at, $8 |
2725 | | // sw $8, %lo(offset)($at) |
2726 | | // 6) ldc1 $f0, sym => lui $at, %hi(sym) |
2727 | | // ldc1 $f0, %lo(sym)($at) |
2728 | | // |
2729 | | // For load instructions we can use the destination register as a temporary |
2730 | | // if base and dst are different (examples 1 and 2) and if the base register |
2731 | | // is general purpose otherwise we must use $at (example 6) and error if it's |
2732 | | // not available. For stores we must use $at (examples 4 and 5) because we |
2733 | | // must not clobber the source register setting up the offset. |
2734 | 551 | const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode()); |
2735 | 551 | int16_t RegClassOp0 = Desc.OpInfo[0].RegClass; |
2736 | 551 | unsigned RegClassIDOp0 = |
2737 | 551 | getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID(); |
2738 | 551 | bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) || |
2739 | 137 | (RegClassIDOp0 == Mips::GPR64RegClassID); |
2740 | 551 | if (isLoad && IsGPR && (BaseRegNum != RegOpNum)) |
2741 | 359 | TmpRegNum = RegOpNum; |
2742 | 192 | else { |
2743 | | // At this point we need AT to perform the expansions and we exit if it is |
2744 | | // not available. |
2745 | 192 | TmpRegNum = getATReg(IDLoc); |
2746 | 192 | if (!TmpRegNum) |
2747 | 3 | return; |
2748 | 192 | } |
2749 | | |
2750 | 548 | emitRX(Mips::LUi, TmpRegNum, |
2751 | 548 | isImmOpnd ? MCOperand::createImm(HiOffset) |
2752 | 548 | : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "hi")), |
2753 | 548 | IDLoc, Instructions); |
2754 | | // Add temp register to base. |
2755 | 548 | if (BaseRegNum != Mips::ZERO) |
2756 | 464 | emitRRR(Mips::ADDu, TmpRegNum, TmpRegNum, BaseRegNum, IDLoc, Instructions); |
2757 | | // And finally, create original instruction with low part |
2758 | | // of offset and new base. |
2759 | 548 | emitRRX(Inst.getOpcode(), RegOpNum, TmpRegNum, |
2760 | 548 | isImmOpnd |
2761 | 548 | ? MCOperand::createImm(LoOffset) |
2762 | 548 | : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "lo")), |
2763 | 548 | IDLoc, Instructions); |
2764 | 548 | } |
2765 | | |
2766 | | bool |
2767 | | MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, |
2768 | 0 | SmallVectorImpl<MCInst> &Instructions) { |
2769 | 0 | unsigned OpNum = Inst.getNumOperands(); |
2770 | 0 | unsigned Opcode = Inst.getOpcode(); |
2771 | 0 | unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM; |
2772 | |
|
2773 | 0 | assert (Inst.getOperand(OpNum - 1).isImm() && |
2774 | 0 | Inst.getOperand(OpNum - 2).isReg() && |
2775 | 0 | Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand."); |
2776 | | |
2777 | 0 | if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 && |
2778 | 0 | Inst.getOperand(OpNum - 1).getImm() >= 0 && |
2779 | 0 | (Inst.getOperand(OpNum - 2).getReg() == Mips::SP || |
2780 | 0 | Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) && |
2781 | 0 | (Inst.getOperand(OpNum - 3).getReg() == Mips::RA || |
2782 | 0 | Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) { |
2783 | | // It can be implemented as SWM16 or LWM16 instruction. |
2784 | 0 | if (inMicroMipsMode() && hasMips32r6()) |
2785 | 0 | NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6; |
2786 | 0 | else |
2787 | 0 | NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM; |
2788 | 0 | } |
2789 | |
|
2790 | 0 | Inst.setOpcode(NewOpcode); |
2791 | 0 | Instructions.push_back(Inst); |
2792 | 0 | return false; |
2793 | 0 | } |
2794 | | |
2795 | | bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc, |
2796 | 0 | SmallVectorImpl<MCInst> &Instructions) { |
2797 | 0 | bool EmittedNoMacroWarning = false; |
2798 | 0 | unsigned PseudoOpcode = Inst.getOpcode(); |
2799 | 0 | unsigned SrcReg = Inst.getOperand(0).getReg(); |
2800 | 0 | const MCOperand &TrgOp = Inst.getOperand(1); |
2801 | 0 | const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr(); |
2802 | |
|
2803 | 0 | unsigned ZeroSrcOpcode, ZeroTrgOpcode; |
2804 | 0 | bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality; |
2805 | |
|
2806 | 0 | unsigned TrgReg; |
2807 | 0 | if (TrgOp.isReg()) |
2808 | 0 | TrgReg = TrgOp.getReg(); |
2809 | 0 | else if (TrgOp.isImm()) { |
2810 | 0 | warnIfNoMacro(IDLoc); |
2811 | 0 | EmittedNoMacroWarning = true; |
2812 | |
|
2813 | 0 | TrgReg = getATReg(IDLoc); |
2814 | 0 | if (!TrgReg) |
2815 | 0 | return true; |
2816 | | |
2817 | 0 | switch(PseudoOpcode) { |
2818 | 0 | default: |
2819 | 0 | llvm_unreachable("unknown opcode for branch pseudo-instruction"); |
2820 | 0 | case Mips::BLTImmMacro: |
2821 | 0 | PseudoOpcode = Mips::BLT; |
2822 | 0 | break; |
2823 | 0 | case Mips::BLEImmMacro: |
2824 | 0 | PseudoOpcode = Mips::BLE; |
2825 | 0 | break; |
2826 | 0 | case Mips::BGEImmMacro: |
2827 | 0 | PseudoOpcode = Mips::BGE; |
2828 | 0 | break; |
2829 | 0 | case Mips::BGTImmMacro: |
2830 | 0 | PseudoOpcode = Mips::BGT; |
2831 | 0 | break; |
2832 | 0 | case Mips::BLTUImmMacro: |
2833 | 0 | PseudoOpcode = Mips::BLTU; |
2834 | 0 | break; |
2835 | 0 | case Mips::BLEUImmMacro: |
2836 | 0 | PseudoOpcode = Mips::BLEU; |
2837 | 0 | break; |
2838 | 0 | case Mips::BGEUImmMacro: |
2839 | 0 | PseudoOpcode = Mips::BGEU; |
2840 | 0 | break; |
2841 | 0 | case Mips::BGTUImmMacro: |
2842 | 0 | PseudoOpcode = Mips::BGTU; |
2843 | 0 | break; |
2844 | 0 | case Mips::BLTLImmMacro: |
2845 | 0 | PseudoOpcode = Mips::BLTL; |
2846 | 0 | break; |
2847 | 0 | case Mips::BLELImmMacro: |
2848 | 0 | PseudoOpcode = Mips::BLEL; |
2849 | 0 | break; |
2850 | 0 | case Mips::BGELImmMacro: |
2851 | 0 | PseudoOpcode = Mips::BGEL; |
2852 | 0 | break; |
2853 | 0 | case Mips::BGTLImmMacro: |
2854 | 0 | PseudoOpcode = Mips::BGTL; |
2855 | 0 | break; |
2856 | 0 | case Mips::BLTULImmMacro: |
2857 | 0 | PseudoOpcode = Mips::BLTUL; |
2858 | 0 | break; |
2859 | 0 | case Mips::BLEULImmMacro: |
2860 | 0 | PseudoOpcode = Mips::BLEUL; |
2861 | 0 | break; |
2862 | 0 | case Mips::BGEULImmMacro: |
2863 | 0 | PseudoOpcode = Mips::BGEUL; |
2864 | 0 | break; |
2865 | 0 | case Mips::BGTULImmMacro: |
2866 | 0 | PseudoOpcode = Mips::BGTUL; |
2867 | 0 | break; |
2868 | 0 | } |
2869 | | |
2870 | 0 | if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(), |
2871 | 0 | false, IDLoc, Instructions)) |
2872 | 0 | return true; |
2873 | 0 | } |
2874 | | |
2875 | 0 | switch (PseudoOpcode) { |
2876 | 0 | case Mips::BLT: |
2877 | 0 | case Mips::BLTU: |
2878 | 0 | case Mips::BLTL: |
2879 | 0 | case Mips::BLTUL: |
2880 | 0 | AcceptsEquality = false; |
2881 | 0 | ReverseOrderSLT = false; |
2882 | 0 | IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL)); |
2883 | 0 | IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL)); |
2884 | 0 | ZeroSrcOpcode = Mips::BGTZ; |
2885 | 0 | ZeroTrgOpcode = Mips::BLTZ; |
2886 | 0 | break; |
2887 | 0 | case Mips::BLE: |
2888 | 0 | case Mips::BLEU: |
2889 | 0 | case Mips::BLEL: |
2890 | 0 | case Mips::BLEUL: |
2891 | 0 | AcceptsEquality = true; |
2892 | 0 | ReverseOrderSLT = true; |
2893 | 0 | IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL)); |
2894 | 0 | IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL)); |
2895 | 0 | ZeroSrcOpcode = Mips::BGEZ; |
2896 | 0 | ZeroTrgOpcode = Mips::BLEZ; |
2897 | 0 | break; |
2898 | 0 | case Mips::BGE: |
2899 | 0 | case Mips::BGEU: |
2900 | 0 | case Mips::BGEL: |
2901 | 0 | case Mips::BGEUL: |
2902 | 0 | AcceptsEquality = true; |
2903 | 0 | ReverseOrderSLT = false; |
2904 | 0 | IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL)); |
2905 | 0 | IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL)); |
2906 | 0 | ZeroSrcOpcode = Mips::BLEZ; |
2907 | 0 | ZeroTrgOpcode = Mips::BGEZ; |
2908 | 0 | break; |
2909 | 0 | case Mips::BGT: |
2910 | 0 | case Mips::BGTU: |
2911 | 0 | case Mips::BGTL: |
2912 | 0 | case Mips::BGTUL: |
2913 | 0 | AcceptsEquality = false; |
2914 | 0 | ReverseOrderSLT = true; |
2915 | 0 | IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL)); |
2916 | 0 | IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL)); |
2917 | 0 | ZeroSrcOpcode = Mips::BLTZ; |
2918 | 0 | ZeroTrgOpcode = Mips::BGTZ; |
2919 | 0 | break; |
2920 | 0 | default: |
2921 | 0 | llvm_unreachable("unknown opcode for branch pseudo-instruction"); |
2922 | 0 | } |
2923 | | |
2924 | 0 | bool IsTrgRegZero = (TrgReg == Mips::ZERO); |
2925 | 0 | bool IsSrcRegZero = (SrcReg == Mips::ZERO); |
2926 | 0 | if (IsSrcRegZero && IsTrgRegZero) { |
2927 | | // FIXME: All of these Opcode-specific if's are needed for compatibility |
2928 | | // with GAS' behaviour. However, they may not generate the most efficient |
2929 | | // code in some circumstances. |
2930 | 0 | if (PseudoOpcode == Mips::BLT) { |
2931 | 0 | emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc, |
2932 | 0 | Instructions); |
2933 | 0 | return false; |
2934 | 0 | } |
2935 | 0 | if (PseudoOpcode == Mips::BLE) { |
2936 | 0 | emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc, |
2937 | 0 | Instructions); |
2938 | | // Warning(IDLoc, "branch is always taken"); |
2939 | 0 | return false; |
2940 | 0 | } |
2941 | 0 | if (PseudoOpcode == Mips::BGE) { |
2942 | 0 | emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc, |
2943 | 0 | Instructions); |
2944 | | // Warning(IDLoc, "branch is always taken"); |
2945 | 0 | return false; |
2946 | 0 | } |
2947 | 0 | if (PseudoOpcode == Mips::BGT) { |
2948 | 0 | emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc, |
2949 | 0 | Instructions); |
2950 | 0 | return false; |
2951 | 0 | } |
2952 | 0 | if (PseudoOpcode == Mips::BGTU) { |
2953 | 0 | emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO, |
2954 | 0 | MCOperand::createExpr(OffsetExpr), IDLoc, Instructions); |
2955 | 0 | return false; |
2956 | 0 | } |
2957 | 0 | if (AcceptsEquality) { |
2958 | | // If both registers are $0 and the pseudo-branch accepts equality, it |
2959 | | // will always be taken, so we emit an unconditional branch. |
2960 | 0 | emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO, |
2961 | 0 | MCOperand::createExpr(OffsetExpr), IDLoc, Instructions); |
2962 | | // Warning(IDLoc, "branch is always taken"); |
2963 | 0 | return false; |
2964 | 0 | } |
2965 | | // If both registers are $0 and the pseudo-branch does not accept |
2966 | | // equality, it will never be taken, so we don't have to emit anything. |
2967 | 0 | return false; |
2968 | 0 | } |
2969 | 0 | if (IsSrcRegZero || IsTrgRegZero) { |
2970 | 0 | if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) || |
2971 | 0 | (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) { |
2972 | | // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or |
2973 | | // if the $rt is $0 and the pseudo-branch is BLTU (x < 0), |
2974 | | // the pseudo-branch will never be taken, so we don't emit anything. |
2975 | | // This only applies to unsigned pseudo-branches. |
2976 | 0 | return false; |
2977 | 0 | } |
2978 | 0 | if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) || |
2979 | 0 | (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) { |
2980 | | // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or |
2981 | | // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0), |
2982 | | // the pseudo-branch will always be taken, so we emit an unconditional |
2983 | | // branch. |
2984 | | // This only applies to unsigned pseudo-branches. |
2985 | 0 | emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO, |
2986 | 0 | MCOperand::createExpr(OffsetExpr), IDLoc, Instructions); |
2987 | | // Warning(IDLoc, "branch is always taken"); |
2988 | 0 | return false; |
2989 | 0 | } |
2990 | 0 | if (IsUnsigned) { |
2991 | | // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or |
2992 | | // if the $rt is $0 and the pseudo-branch is BGTU (x > 0), |
2993 | | // the pseudo-branch will be taken only when the non-zero register is |
2994 | | // different from 0, so we emit a BNEZ. |
2995 | | // |
2996 | | // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or |
2997 | | // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0), |
2998 | | // the pseudo-branch will be taken only when the non-zero register is |
2999 | | // equal to 0, so we emit a BEQZ. |
3000 | | // |
3001 | | // Because only BLEU and BGEU branch on equality, we can use the |
3002 | | // AcceptsEquality variable to decide when to emit the BEQZ. |
3003 | 0 | emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE, |
3004 | 0 | IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO, |
3005 | 0 | MCOperand::createExpr(OffsetExpr), IDLoc, Instructions); |
3006 | 0 | return false; |
3007 | 0 | } |
3008 | | // If we have a signed pseudo-branch and one of the registers is $0, |
3009 | | // we can use an appropriate compare-to-zero branch. We select which one |
3010 | | // to use in the switch statement above. |
3011 | 0 | emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode, |
3012 | 0 | IsSrcRegZero ? TrgReg : SrcReg, MCOperand::createExpr(OffsetExpr), |
3013 | 0 | IDLoc, Instructions); |
3014 | 0 | return false; |
3015 | 0 | } |
3016 | | |
3017 | | // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the |
3018 | | // expansions. If it is not available, we return. |
3019 | 0 | unsigned ATRegNum = getATReg(IDLoc); |
3020 | 0 | if (!ATRegNum) |
3021 | 0 | return true; |
3022 | | |
3023 | 0 | if (!EmittedNoMacroWarning) |
3024 | 0 | warnIfNoMacro(IDLoc); |
3025 | | |
3026 | | // SLT fits well with 2 of our 4 pseudo-branches: |
3027 | | // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and |
3028 | | // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs". |
3029 | | // If the result of the SLT is 1, we branch, and if it's 0, we don't. |
3030 | | // This is accomplished by using a BNEZ with the result of the SLT. |
3031 | | // |
3032 | | // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT |
3033 | | // and BLE with BGT), so we change the BNEZ into a a BEQZ. |
3034 | | // Because only BGE and BLE branch on equality, we can use the |
3035 | | // AcceptsEquality variable to decide when to emit the BEQZ. |
3036 | | // Note that the order of the SLT arguments doesn't change between |
3037 | | // opposites. |
3038 | | // |
3039 | | // The same applies to the unsigned variants, except that SLTu is used |
3040 | | // instead of SLT. |
3041 | 0 | emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum, |
3042 | 0 | ReverseOrderSLT ? TrgReg : SrcReg, ReverseOrderSLT ? SrcReg : TrgReg, |
3043 | 0 | IDLoc, Instructions); |
3044 | |
|
3045 | 0 | emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL) |
3046 | 0 | : (AcceptsEquality ? Mips::BEQ : Mips::BNE), |
3047 | 0 | ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc, |
3048 | 0 | Instructions); |
3049 | 0 | return false; |
3050 | 0 | } |
3051 | | |
3052 | | bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, |
3053 | | SmallVectorImpl<MCInst> &Instructions, |
3054 | 0 | const bool IsMips64, const bool Signed) { |
3055 | 0 | if (hasMips32r6()) { |
3056 | 0 | Error(IDLoc, "instruction not supported on mips32r6 or mips64r6"); |
3057 | 0 | return false; |
3058 | 0 | } |
3059 | | |
3060 | 0 | warnIfNoMacro(IDLoc); |
3061 | |
|
3062 | 0 | const MCOperand &RsRegOp = Inst.getOperand(0); |
3063 | 0 | assert(RsRegOp.isReg() && "expected register operand kind"); |
3064 | 0 | unsigned RsReg = RsRegOp.getReg(); |
3065 | |
|
3066 | 0 | const MCOperand &RtRegOp = Inst.getOperand(1); |
3067 | 0 | assert(RtRegOp.isReg() && "expected register operand kind"); |
3068 | 0 | unsigned RtReg = RtRegOp.getReg(); |
3069 | 0 | unsigned DivOp; |
3070 | 0 | unsigned ZeroReg; |
3071 | |
|
3072 | 0 | if (IsMips64) { |
3073 | 0 | DivOp = Signed ? Mips::DSDIV : Mips::DUDIV; |
3074 | 0 | ZeroReg = Mips::ZERO_64; |
3075 | 0 | } else { |
3076 | 0 | DivOp = Signed ? Mips::SDIV : Mips::UDIV; |
3077 | 0 | ZeroReg = Mips::ZERO; |
3078 | 0 | } |
3079 | |
|
3080 | 0 | bool UseTraps = useTraps(); |
3081 | |
|
3082 | 0 | if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) { |
3083 | 0 | if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) { |
3084 | | // Warning(IDLoc, "dividing zero by zero"); |
3085 | 0 | } |
3086 | 0 | if (IsMips64) { |
3087 | 0 | if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) { |
3088 | 0 | if (UseTraps) { |
3089 | 0 | emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions); |
3090 | 0 | return false; |
3091 | 0 | } |
3092 | | |
3093 | 0 | emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions); |
3094 | 0 | return false; |
3095 | 0 | } |
3096 | 0 | } else { |
3097 | 0 | emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions); |
3098 | 0 | return false; |
3099 | 0 | } |
3100 | 0 | } |
3101 | | |
3102 | 0 | if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) { |
3103 | | // Warning(IDLoc, "division by zero"); |
3104 | 0 | if (Signed) { |
3105 | 0 | if (UseTraps) { |
3106 | 0 | emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions); |
3107 | 0 | return false; |
3108 | 0 | } |
3109 | | |
3110 | 0 | emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions); |
3111 | 0 | return false; |
3112 | 0 | } |
3113 | 0 | } |
3114 | | |
3115 | | // FIXME: The values for these two BranchTarget variables may be different in |
3116 | | // micromips. These magic numbers need to be removed. |
3117 | 0 | unsigned BranchTargetNoTraps; |
3118 | 0 | unsigned BranchTarget; |
3119 | |
|
3120 | 0 | if (UseTraps) { |
3121 | 0 | BranchTarget = IsMips64 ? 12 : 8; |
3122 | 0 | emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions); |
3123 | 0 | } else { |
3124 | 0 | BranchTarget = IsMips64 ? 20 : 16; |
3125 | 0 | BranchTargetNoTraps = 8; |
3126 | | // Branch to the li instruction. |
3127 | 0 | emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc, |
3128 | 0 | Instructions); |
3129 | 0 | } |
3130 | |
|
3131 | 0 | emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions); |
3132 | |
|
3133 | 0 | if (!UseTraps) |
3134 | 0 | emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions); |
3135 | |
|
3136 | 0 | if (!Signed) { |
3137 | 0 | emitR(Mips::MFLO, RsReg, IDLoc, Instructions); |
3138 | 0 | return false; |
3139 | 0 | } |
3140 | | |
3141 | 0 | unsigned ATReg = getATReg(IDLoc); |
3142 | 0 | if (!ATReg) |
3143 | 0 | return true; |
3144 | | |
3145 | 0 | emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, Instructions); |
3146 | 0 | if (IsMips64) { |
3147 | | // Branch to the mflo instruction. |
3148 | 0 | emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions); |
3149 | 0 | emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, Instructions); |
3150 | 0 | emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, Instructions); |
3151 | 0 | } else { |
3152 | | // Branch to the mflo instruction. |
3153 | 0 | emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions); |
3154 | 0 | emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, Instructions); |
3155 | 0 | } |
3156 | |
|
3157 | 0 | if (UseTraps) |
3158 | 0 | emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, Instructions); |
3159 | 0 | else { |
3160 | | // Branch to the mflo instruction. |
3161 | 0 | emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, Instructions); |
3162 | 0 | emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, Instructions); |
3163 | 0 | emitII(Mips::BREAK, 0x6, 0, IDLoc, Instructions); |
3164 | 0 | } |
3165 | 0 | emitR(Mips::MFLO, RsReg, IDLoc, Instructions); |
3166 | 0 | return false; |
3167 | 0 | } |
3168 | | |
3169 | | bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, |
3170 | 0 | SmallVectorImpl<MCInst> &Instructions) { |
3171 | 0 | if (hasMips32r6() || hasMips64r6()) { |
3172 | 0 | Error(IDLoc, "instruction not supported on mips32r6 or mips64r6"); |
3173 | 0 | return false; |
3174 | 0 | } |
3175 | | |
3176 | 0 | warnIfNoMacro(IDLoc); |
3177 | |
|
3178 | 0 | const MCOperand &DstRegOp = Inst.getOperand(0); |
3179 | 0 | assert(DstRegOp.isReg() && "expected register operand kind"); |
3180 | | |
3181 | 0 | const MCOperand &SrcRegOp = Inst.getOperand(1); |
3182 | 0 | assert(SrcRegOp.isReg() && "expected register operand kind"); |
3183 | | |
3184 | 0 | const MCOperand &OffsetImmOp = Inst.getOperand(2); |
3185 | 0 | assert(OffsetImmOp.isImm() && "expected immediate operand kind"); |
3186 | | |
3187 | 0 | unsigned DstReg = DstRegOp.getReg(); |
3188 | 0 | unsigned SrcReg = SrcRegOp.getReg(); |
3189 | 0 | int64_t OffsetValue = OffsetImmOp.getImm(); |
3190 | | |
3191 | | // NOTE: We always need AT for ULHU, as it is always used as the source |
3192 | | // register for one of the LBu's. |
3193 | 0 | unsigned ATReg = getATReg(IDLoc); |
3194 | 0 | if (!ATReg) |
3195 | 0 | return true; |
3196 | | |
3197 | | // When the value of offset+1 does not fit in 16 bits, we have to load the |
3198 | | // offset in AT, (D)ADDu the original source register (if there was one), and |
3199 | | // then use AT as the source register for the 2 generated LBu's. |
3200 | 0 | bool LoadedOffsetInAT = false; |
3201 | 0 | if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) { |
3202 | 0 | LoadedOffsetInAT = true; |
3203 | |
|
3204 | 0 | if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(), |
3205 | 0 | true, IDLoc, Instructions)) |
3206 | 0 | return true; |
3207 | | |
3208 | | // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate() |
3209 | | // because it will make our output more similar to GAS'. For example, |
3210 | | // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9", |
3211 | | // instead of just an "ori $1, $9, 32768". |
3212 | | // NOTE: If there is no source register specified in the ULHU, the parser |
3213 | | // will interpret it as $0. |
3214 | 0 | if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64) |
3215 | 0 | createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions); |
3216 | 0 | } |
3217 | | |
3218 | 0 | unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg; |
3219 | 0 | unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg; |
3220 | 0 | unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg; |
3221 | |
|
3222 | 0 | int64_t FirstLbuOffset = 0, SecondLbuOffset = 0; |
3223 | 0 | if (isLittle()) { |
3224 | 0 | FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1); |
3225 | 0 | SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue; |
3226 | 0 | } else { |
3227 | 0 | FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue; |
3228 | 0 | SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1); |
3229 | 0 | } |
3230 | |
|
3231 | 0 | unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg; |
3232 | |
|
3233 | 0 | emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg, |
3234 | 0 | FirstLbuOffset, IDLoc, Instructions); |
3235 | |
|
3236 | 0 | emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc, |
3237 | 0 | Instructions); |
3238 | |
|
3239 | 0 | emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, Instructions); |
3240 | |
|
3241 | 0 | emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, Instructions); |
3242 | |
|
3243 | 0 | return false; |
3244 | 0 | } |
3245 | | |
3246 | | bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc, |
3247 | 0 | SmallVectorImpl<MCInst> &Instructions) { |
3248 | 0 | if (hasMips32r6() || hasMips64r6()) { |
3249 | 0 | Error(IDLoc, "instruction not supported on mips32r6 or mips64r6"); |
3250 | 0 | return false; |
3251 | 0 | } |
3252 | | |
3253 | 0 | const MCOperand &DstRegOp = Inst.getOperand(0); |
3254 | 0 | assert(DstRegOp.isReg() && "expected register operand kind"); |
3255 | | |
3256 | 0 | const MCOperand &SrcRegOp = Inst.getOperand(1); |
3257 | 0 | assert(SrcRegOp.isReg() && "expected register operand kind"); |
3258 | | |
3259 | 0 | const MCOperand &OffsetImmOp = Inst.getOperand(2); |
3260 | 0 | assert(OffsetImmOp.isImm() && "expected immediate operand kind"); |
3261 | | |
3262 | 0 | unsigned SrcReg = SrcRegOp.getReg(); |
3263 | 0 | int64_t OffsetValue = OffsetImmOp.getImm(); |
3264 | 0 | unsigned ATReg = 0; |
3265 | | |
3266 | | // When the value of offset+3 does not fit in 16 bits, we have to load the |
3267 | | // offset in AT, (D)ADDu the original source register (if there was one), and |
3268 | | // then use AT as the source register for the generated LWL and LWR. |
3269 | 0 | bool LoadedOffsetInAT = false; |
3270 | 0 | if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) { |
3271 | 0 | ATReg = getATReg(IDLoc); |
3272 | 0 | if (!ATReg) |
3273 | 0 | return true; |
3274 | 0 | LoadedOffsetInAT = true; |
3275 | |
|
3276 | 0 | warnIfNoMacro(IDLoc); |
3277 | |
|
3278 | 0 | if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(), |
3279 | 0 | true, IDLoc, Instructions)) |
3280 | 0 | return true; |
3281 | | |
3282 | | // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate() |
3283 | | // because it will make our output more similar to GAS'. For example, |
3284 | | // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9", |
3285 | | // instead of just an "ori $1, $9, 32768". |
3286 | | // NOTE: If there is no source register specified in the ULW, the parser |
3287 | | // will interpret it as $0. |
3288 | 0 | if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64) |
3289 | 0 | createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions); |
3290 | 0 | } |
3291 | | |
3292 | 0 | unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg; |
3293 | 0 | int64_t LeftLoadOffset = 0, RightLoadOffset = 0; |
3294 | 0 | if (isLittle()) { |
3295 | 0 | LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3); |
3296 | 0 | RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue; |
3297 | 0 | } else { |
3298 | 0 | LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue; |
3299 | 0 | RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3); |
3300 | 0 | } |
3301 | |
|
3302 | 0 | emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc, |
3303 | 0 | Instructions); |
3304 | |
|
3305 | 0 | emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset, IDLoc, |
3306 | 0 | Instructions); |
3307 | |
|
3308 | 0 | return false; |
3309 | 0 | } |
3310 | | |
3311 | | bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, |
3312 | 973 | SmallVectorImpl<MCInst> &Instructions) { |
3313 | | |
3314 | 973 | assert (Inst.getNumOperands() == 3 && "Invalid operand count"); |
3315 | 973 | assert (Inst.getOperand(0).isReg() && |
3316 | 973 | Inst.getOperand(1).isReg() && |
3317 | 973 | Inst.getOperand(2).isImm() && "Invalid instruction operand."); |
3318 | | |
3319 | 973 | unsigned ATReg = Mips::NoRegister; |
3320 | 973 | unsigned FinalDstReg = Mips::NoRegister; |
3321 | 973 | unsigned DstReg = Inst.getOperand(0).getReg(); |
3322 | 973 | unsigned SrcReg = Inst.getOperand(1).getReg(); |
3323 | 973 | int64_t ImmValue = Inst.getOperand(2).getImm(); |
3324 | | |
3325 | 973 | bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue); |
3326 | | |
3327 | 973 | unsigned FinalOpcode = Inst.getOpcode(); |
3328 | | |
3329 | 973 | if (DstReg == SrcReg) { |
3330 | 750 | ATReg = getATReg(Inst.getLoc()); |
3331 | 750 | if (!ATReg) |
3332 | 1 | return true; |
3333 | 749 | FinalDstReg = DstReg; |
3334 | 749 | DstReg = ATReg; |
3335 | 749 | } |
3336 | | |
3337 | 972 | if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Instructions)) { |
3338 | 971 | switch (FinalOpcode) { |
3339 | 0 | default: |
3340 | 0 | llvm_unreachable("unimplemented expansion"); |
3341 | 0 | case (Mips::ADDi): |
3342 | 0 | FinalOpcode = Mips::ADD; |
3343 | 0 | break; |
3344 | 0 | case (Mips::ADDiu): |
3345 | 0 | FinalOpcode = Mips::ADDu; |
3346 | 0 | break; |
3347 | 0 | case (Mips::ANDi): |
3348 | 0 | FinalOpcode = Mips::AND; |
3349 | 0 | break; |
3350 | 0 | case (Mips::NORImm): |
3351 | 0 | FinalOpcode = Mips::NOR; |
3352 | 0 | break; |
3353 | 967 | case (Mips::ORi): |
3354 | 967 | FinalOpcode = Mips::OR; |
3355 | 967 | break; |
3356 | 0 | case (Mips::SLTi): |
3357 | 0 | FinalOpcode = Mips::SLT; |
3358 | 0 | break; |
3359 | 0 | case (Mips::SLTiu): |
3360 | 0 | FinalOpcode = Mips::SLTu; |
3361 | 0 | break; |
3362 | 4 | case (Mips::XORi): |
3363 | 4 | FinalOpcode = Mips::XOR; |
3364 | 4 | break; |
3365 | 971 | } |
3366 | | |
3367 | 971 | if (FinalDstReg == Mips::NoRegister) |
3368 | 223 | emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, Instructions); |
3369 | 748 | else |
3370 | 748 | emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, |
3371 | 748 | Instructions); |
3372 | 971 | return false; |
3373 | 971 | } |
3374 | 1 | return true; |
3375 | 972 | } |
3376 | | |
3377 | | bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, |
3378 | 0 | SmallVectorImpl<MCInst> &Instructions) { |
3379 | 0 | unsigned ATReg = Mips::NoRegister; |
3380 | 0 | unsigned DReg = Inst.getOperand(0).getReg(); |
3381 | 0 | unsigned SReg = Inst.getOperand(1).getReg(); |
3382 | 0 | unsigned TReg = Inst.getOperand(2).getReg(); |
3383 | 0 | unsigned TmpReg = DReg; |
3384 | |
|
3385 | 0 | unsigned FirstShift = Mips::NOP; |
3386 | 0 | unsigned SecondShift = Mips::NOP; |
3387 | |
|
3388 | 0 | if (hasMips32r2()) { |
3389 | |
|
3390 | 0 | if (DReg == SReg) { |
3391 | 0 | TmpReg = getATReg(Inst.getLoc()); |
3392 | 0 | if (!TmpReg) |
3393 | 0 | return true; |
3394 | 0 | } |
3395 | | |
3396 | 0 | if (Inst.getOpcode() == Mips::ROL) { |
3397 | 0 | emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions); |
3398 | 0 | emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), Instructions); |
3399 | 0 | return false; |
3400 | 0 | } |
3401 | | |
3402 | 0 | if (Inst.getOpcode() == Mips::ROR) { |
3403 | 0 | emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), Instructions); |
3404 | 0 | return false; |
3405 | 0 | } |
3406 | | |
3407 | 0 | return true; |
3408 | 0 | } |
3409 | | |
3410 | 0 | if (hasMips32()) { |
3411 | |
|
3412 | 0 | switch (Inst.getOpcode()) { |
3413 | 0 | default: |
3414 | 0 | llvm_unreachable("unexpected instruction opcode"); |
3415 | 0 | case Mips::ROL: |
3416 | 0 | FirstShift = Mips::SRLV; |
3417 | 0 | SecondShift = Mips::SLLV; |
3418 | 0 | break; |
3419 | 0 | case Mips::ROR: |
3420 | 0 | FirstShift = Mips::SLLV; |
3421 | 0 | SecondShift = Mips::SRLV; |
3422 | 0 | break; |
3423 | 0 | } |
3424 | | |
3425 | 0 | ATReg = getATReg(Inst.getLoc()); |
3426 | 0 | if (!ATReg) |
3427 | 0 | return true; |
3428 | | |
3429 | 0 | emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions); |
3430 | 0 | emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), Instructions); |
3431 | 0 | emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), Instructions); |
3432 | 0 | emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions); |
3433 | |
|
3434 | 0 | return false; |
3435 | 0 | } |
3436 | | |
3437 | 0 | return true; |
3438 | 0 | } |
3439 | | |
3440 | | bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc, |
3441 | 18 | SmallVectorImpl<MCInst> &Instructions) { |
3442 | | |
3443 | 18 | unsigned ATReg = Mips::NoRegister; |
3444 | 18 | unsigned DReg = Inst.getOperand(0).getReg(); |
3445 | 18 | unsigned SReg = Inst.getOperand(1).getReg(); |
3446 | 18 | int64_t ImmValue = Inst.getOperand(2).getImm(); |
3447 | | |
3448 | 18 | unsigned FirstShift = Mips::NOP; |
3449 | 18 | unsigned SecondShift = Mips::NOP; |
3450 | | |
3451 | 18 | if (hasMips32r2()) { |
3452 | | |
3453 | 1 | if (Inst.getOpcode() == Mips::ROLImm) { |
3454 | 0 | uint64_t MaxShift = 32; |
3455 | 0 | uint64_t ShiftValue = ImmValue; |
3456 | 0 | if (ImmValue != 0) |
3457 | 0 | ShiftValue = MaxShift - ImmValue; |
3458 | 0 | emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), Instructions); |
3459 | 0 | return false; |
3460 | 0 | } |
3461 | | |
3462 | 1 | if (Inst.getOpcode() == Mips::RORImm) { |
3463 | 1 | emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), Instructions); |
3464 | 1 | return false; |
3465 | 1 | } |
3466 | | |
3467 | 0 | return true; |
3468 | 1 | } |
3469 | | |
3470 | 17 | if (hasMips32()) { |
3471 | | |
3472 | 17 | if (ImmValue == 0) { |
3473 | 3 | emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), Instructions); |
3474 | 3 | return false; |
3475 | 3 | } |
3476 | | |
3477 | 14 | switch (Inst.getOpcode()) { |
3478 | 0 | default: |
3479 | 0 | llvm_unreachable("unexpected instruction opcode"); |
3480 | 0 | case Mips::ROLImm: |
3481 | 0 | FirstShift = Mips::SLL; |
3482 | 0 | SecondShift = Mips::SRL; |
3483 | 0 | break; |
3484 | 14 | case Mips::RORImm: |
3485 | 14 | FirstShift = Mips::SRL; |
3486 | 14 | SecondShift = Mips::SLL; |
3487 | 14 | break; |
3488 | 14 | } |
3489 | | |
3490 | 14 | ATReg = getATReg(Inst.getLoc()); |
3491 | 14 | if (!ATReg) |
3492 | 0 | return true; |
3493 | | |
3494 | 14 | emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), Instructions); |
3495 | 14 | emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), Instructions); |
3496 | 14 | emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions); |
3497 | | |
3498 | 14 | return false; |
3499 | 14 | } |
3500 | | |
3501 | 0 | return true; |
3502 | 17 | } |
3503 | | |
3504 | | bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, |
3505 | 0 | SmallVectorImpl<MCInst> &Instructions) { |
3506 | |
|
3507 | 0 | unsigned ATReg = Mips::NoRegister; |
3508 | 0 | unsigned DReg = Inst.getOperand(0).getReg(); |
3509 | 0 | unsigned SReg = Inst.getOperand(1).getReg(); |
3510 | 0 | unsigned TReg = Inst.getOperand(2).getReg(); |
3511 | 0 | unsigned TmpReg = DReg; |
3512 | |
|
3513 | 0 | unsigned FirstShift = Mips::NOP; |
3514 | 0 | unsigned SecondShift = Mips::NOP; |
3515 | |
|
3516 | 0 | if (hasMips64r2()) { |
3517 | |
|
3518 | 0 | if (TmpReg == SReg) { |
3519 | 0 | TmpReg = getATReg(Inst.getLoc()); |
3520 | 0 | if (!TmpReg) |
3521 | 0 | return true; |
3522 | 0 | } |
3523 | | |
3524 | 0 | if (Inst.getOpcode() == Mips::DROL) { |
3525 | 0 | emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions); |
3526 | 0 | emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), Instructions); |
3527 | 0 | return false; |
3528 | 0 | } |
3529 | | |
3530 | 0 | if (Inst.getOpcode() == Mips::DROR) { |
3531 | 0 | emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), Instructions); |
3532 | 0 | return false; |
3533 | 0 | } |
3534 | | |
3535 | 0 | return true; |
3536 | 0 | } |
3537 | | |
3538 | 0 | if (hasMips64()) { |
3539 | |
|
3540 | 0 | switch (Inst.getOpcode()) { |
3541 | 0 | default: |
3542 | 0 | llvm_unreachable("unexpected instruction opcode"); |
3543 | 0 | case Mips::DROL: |
3544 | 0 | FirstShift = Mips::DSRLV; |
3545 | 0 | SecondShift = Mips::DSLLV; |
3546 | 0 | break; |
3547 | 0 | case Mips::DROR: |
3548 | 0 | FirstShift = Mips::DSLLV; |
3549 | 0 | SecondShift = Mips::DSRLV; |
3550 | 0 | break; |
3551 | 0 | } |
3552 | | |
3553 | 0 | ATReg = getATReg(Inst.getLoc()); |
3554 | 0 | if (!ATReg) |
3555 | 0 | return true; |
3556 | | |
3557 | 0 | emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions); |
3558 | 0 | emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), Instructions); |
3559 | 0 | emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), Instructions); |
3560 | 0 | emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions); |
3561 | |
|
3562 | 0 | return false; |
3563 | 0 | } |
3564 | | |
3565 | 0 | return true; |
3566 | 0 | } |
3567 | | |
3568 | | bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc, |
3569 | 2 | SmallVectorImpl<MCInst> &Instructions) { |
3570 | | |
3571 | 2 | unsigned ATReg = Mips::NoRegister; |
3572 | 2 | unsigned DReg = Inst.getOperand(0).getReg(); |
3573 | 2 | unsigned SReg = Inst.getOperand(1).getReg(); |
3574 | 2 | int64_t ImmValue = Inst.getOperand(2).getImm() % 64; |
3575 | | |
3576 | 2 | unsigned FirstShift = Mips::NOP; |
3577 | 2 | unsigned SecondShift = Mips::NOP; |
3578 | | |
3579 | 2 | MCInst TmpInst; |
3580 | | |
3581 | 2 | if (hasMips64r2()) { |
3582 | |
|
3583 | 0 | unsigned FinalOpcode = Mips::NOP; |
3584 | 0 | if (ImmValue == 0) |
3585 | 0 | FinalOpcode = Mips::DROTR; |
3586 | 0 | else if (ImmValue % 32 == 0) |
3587 | 0 | FinalOpcode = Mips::DROTR32; |
3588 | 0 | else if ((ImmValue >= 1) && (ImmValue <= 32)) { |
3589 | 0 | if (Inst.getOpcode() == Mips::DROLImm) |
3590 | 0 | FinalOpcode = Mips::DROTR32; |
3591 | 0 | else |
3592 | 0 | FinalOpcode = Mips::DROTR; |
3593 | 0 | } else if (ImmValue >= 33) { |
3594 | 0 | if (Inst.getOpcode() == Mips::DROLImm) |
3595 | 0 | FinalOpcode = Mips::DROTR; |
3596 | 0 | else |
3597 | 0 | FinalOpcode = Mips::DROTR32; |
3598 | 0 | } |
3599 | |
|
3600 | 0 | uint64_t ShiftValue = ImmValue % 32; |
3601 | 0 | if (Inst.getOpcode() == Mips::DROLImm) |
3602 | 0 | ShiftValue = (32 - ImmValue % 32) % 32; |
3603 | |
|
3604 | 0 | emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), Instructions); |
3605 | |
|
3606 | 0 | return false; |
3607 | 0 | } |
3608 | | |
3609 | 2 | if (hasMips64()) { |
3610 | | |
3611 | 2 | if (ImmValue == 0) { |
3612 | 0 | emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), Instructions); |
3613 | 0 | return false; |
3614 | 0 | } |
3615 | | |
3616 | 2 | switch (Inst.getOpcode()) { |
3617 | 0 | default: |
3618 | 0 | llvm_unreachable("unexpected instruction opcode"); |
3619 | 2 | case Mips::DROLImm: |
3620 | 2 | if ((ImmValue >= 1) && (ImmValue <= 31)) { |
3621 | 2 | FirstShift = Mips::DSLL; |
3622 | 2 | SecondShift = Mips::DSRL32; |
3623 | 2 | } |
3624 | 2 | if (ImmValue == 32) { |
3625 | 0 | FirstShift = Mips::DSLL32; |
3626 | 0 | SecondShift = Mips::DSRL32; |
3627 | 0 | } |
3628 | 2 | if ((ImmValue >= 33) && (ImmValue <= 63)) { |
3629 | 0 | FirstShift = Mips::DSLL32; |
3630 | 0 | SecondShift = Mips::DSRL; |
3631 | 0 | } |
3632 | 2 | break; |
3633 | 0 | case Mips::DRORImm: |
3634 | 0 | if ((ImmValue >= 1) && (ImmValue <= 31)) { |
3635 | 0 | FirstShift = Mips::DSRL; |
3636 | 0 | SecondShift = Mips::DSLL32; |
3637 | 0 | } |
3638 | 0 | if (ImmValue == 32) { |
3639 | 0 | FirstShift = Mips::DSRL32; |
3640 | 0 | SecondShift = Mips::DSLL32; |
3641 | 0 | } |
3642 | 0 | if ((ImmValue >= 33) && (ImmValue <= 63)) { |
3643 | 0 | FirstShift = Mips::DSRL32; |
3644 | 0 | SecondShift = Mips::DSLL; |
3645 | 0 | } |
3646 | 0 | break; |
3647 | 2 | } |
3648 | | |
3649 | 2 | ATReg = getATReg(Inst.getLoc()); |
3650 | 2 | if (!ATReg) |
3651 | 0 | return true; |
3652 | | |
3653 | 2 | emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), Instructions); |
3654 | 2 | emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32, Inst.getLoc(), Instructions); |
3655 | 2 | emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions); |
3656 | | |
3657 | 2 | return false; |
3658 | 2 | } |
3659 | | |
3660 | 0 | return true; |
3661 | 2 | } |
3662 | | |
3663 | | bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, |
3664 | 32 | SmallVectorImpl<MCInst> &Instructions) { |
3665 | | |
3666 | 32 | unsigned FirstRegOp = Inst.getOperand(0).getReg(); |
3667 | 32 | unsigned SecondRegOp = Inst.getOperand(1).getReg(); |
3668 | | |
3669 | 32 | emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, Instructions); |
3670 | 32 | if (FirstRegOp != SecondRegOp) |
3671 | 32 | emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, Instructions); |
3672 | 0 | else |
3673 | 0 | createNop(false, IDLoc, Instructions); |
3674 | 32 | emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, Instructions); |
3675 | | |
3676 | 32 | return false; |
3677 | 32 | } |
3678 | | |
3679 | | void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc, |
3680 | 11.8k | SmallVectorImpl<MCInst> &Instructions) { |
3681 | 11.8k | if (hasShortDelaySlot) |
3682 | 0 | emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, Instructions); |
3683 | 11.8k | else |
3684 | 11.8k | emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, Instructions); |
3685 | 11.8k | } |
3686 | | |
3687 | | void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg, |
3688 | | unsigned TrgReg, bool Is64Bit, |
3689 | 0 | SmallVectorImpl<MCInst> &Instructions) { |
3690 | 0 | emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(), |
3691 | 0 | Instructions); |
3692 | 0 | } |
3693 | | |
3694 | | void MipsAsmParser::createCpRestoreMemOp( |
3695 | | bool IsLoad, int StackOffset, SMLoc IDLoc, |
3696 | 20 | SmallVectorImpl<MCInst> &Instructions) { |
3697 | | // If the offset can not fit into 16 bits, we need to expand. |
3698 | 20 | if (!isInt<16>(StackOffset)) { |
3699 | 2 | MCInst MemInst; |
3700 | 2 | MemInst.setOpcode(IsLoad ? Mips::LW : Mips::SW); |
3701 | 2 | MemInst.addOperand(MCOperand::createReg(Mips::GP)); |
3702 | 2 | MemInst.addOperand(MCOperand::createReg(Mips::SP)); |
3703 | 2 | MemInst.addOperand(MCOperand::createImm(StackOffset)); |
3704 | 2 | expandMemInst(MemInst, IDLoc, Instructions, IsLoad, true /*HasImmOpnd*/); |
3705 | 2 | return; |
3706 | 2 | } |
3707 | | |
3708 | 18 | emitRRI(IsLoad ? Mips::LW : Mips::SW, Mips::GP, Mips::SP, StackOffset, IDLoc, |
3709 | 18 | Instructions); |
3710 | 18 | } |
3711 | | |
3712 | 14.8k | unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) { |
3713 | | // As described by the Mips32r2 spec, the registers Rd and Rs for |
3714 | | // jalr.hb must be different. |
3715 | 14.8k | unsigned Opcode = Inst.getOpcode(); |
3716 | | |
3717 | 14.8k | if (Opcode == Mips::JALR_HB && |
3718 | 0 | (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())) |
3719 | 0 | return Match_RequiresDifferentSrcAndDst; |
3720 | | |
3721 | 14.8k | return Match_Success; |
3722 | 14.8k | } |
3723 | | |
3724 | | static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands, |
3725 | 5 | uint64_t ErrorInfo) { |
3726 | 5 | if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) { |
3727 | 5 | SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc(); |
3728 | 5 | if (ErrorLoc == SMLoc()) |
3729 | 0 | return Loc; |
3730 | 5 | return ErrorLoc; |
3731 | 5 | } |
3732 | 0 | return Loc; |
3733 | 5 | } |
3734 | | |
3735 | | bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, |
3736 | | OperandVector &Operands, |
3737 | | MCStreamer &Out, |
3738 | | uint64_t &ErrorInfo, |
3739 | | bool MatchingInlineAsm, unsigned int &ErrorCode, uint64_t &Address) |
3740 | 14.9k | { |
3741 | 14.9k | MCInst Inst(Address); |
3742 | 14.9k | SmallVector<MCInst, 8> Instructions; |
3743 | 14.9k | unsigned MatchResult = |
3744 | 14.9k | MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm); |
3745 | | |
3746 | 14.9k | switch (MatchResult) { |
3747 | 14.8k | case Match_Success: { |
3748 | 14.8k | if (processInstruction(Inst, IDLoc, Instructions, ErrorCode)) |
3749 | 32 | return true; |
3750 | 45.8k | for (unsigned i = 0; i < Instructions.size(); i++) |
3751 | 31.0k | Out.EmitInstruction(Instructions[i], getSTI(), ErrorCode); |
3752 | 14.8k | if (ErrorCode == 0) { |
3753 | 14.8k | Address = Inst.getAddress(); // Keystone update address |
3754 | 14.8k | return false; |
3755 | 14.8k | } else |
3756 | 0 | return true; |
3757 | | |
3758 | 14.8k | } |
3759 | 0 | case Match_MissingFeature: |
3760 | 0 | Error(IDLoc, "instruction requires a CPU feature not currently enabled"); |
3761 | 0 | return true; |
3762 | 143 | case Match_InvalidOperand: { |
3763 | 143 | SMLoc ErrorLoc = IDLoc; |
3764 | 143 | if (ErrorInfo != ~0ULL) { |
3765 | 143 | if (ErrorInfo >= Operands.size()) |
3766 | 37 | return Error(IDLoc, "too few operands for instruction"); |
3767 | | |
3768 | 106 | ErrorLoc = Operands[ErrorInfo]->getStartLoc(); |
3769 | 106 | if (ErrorLoc == SMLoc()) |
3770 | 0 | ErrorLoc = IDLoc; |
3771 | 106 | } |
3772 | | |
3773 | 106 | return Error(ErrorLoc, "invalid operand for instruction"); |
3774 | 143 | } |
3775 | 0 | case Match_MnemonicFail: |
3776 | 0 | return Error(IDLoc, "invalid instruction"); |
3777 | 0 | case Match_RequiresDifferentSrcAndDst: |
3778 | 0 | return Error(IDLoc, "source and destination must be different"); |
3779 | 0 | case Match_Immz: |
3780 | 0 | return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'"); |
3781 | 0 | case Match_UImm1_0: |
3782 | 0 | return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), |
3783 | 0 | "expected 1-bit unsigned immediate"); |
3784 | 0 | case Match_UImm2_0: |
3785 | 0 | return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), |
3786 | 0 | "expected 2-bit unsigned immediate"); |
3787 | 0 | case Match_UImm2_1: |
3788 | 0 | return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), |
3789 | 0 | "expected immediate in range 1 .. 4"); |
3790 | 0 | case Match_UImm3_0: |
3791 | 0 | return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), |
3792 | 0 | "expected 3-bit unsigned immediate"); |
3793 | 0 | case Match_UImm4_0: |
3794 | 0 | return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), |
3795 | 0 | "expected 4-bit unsigned immediate"); |
3796 | 0 | case Match_UImm5_0: |
3797 | 0 | return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), |
3798 | 0 | "expected 5-bit unsigned immediate"); |
3799 | 0 | case Match_UImm5_1: |
3800 | 0 | return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), |
3801 | 0 | "expected immediate in range 1 .. 32"); |
3802 | 0 | case Match_UImm5_32: |
3803 | 0 | return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), |
3804 | 0 | "expected immediate in range 32 .. 63"); |
3805 | 0 | case Match_UImm5_33: |
3806 | 0 | return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), |
3807 | 0 | "expected immediate in range 33 .. 64"); |
3808 | 0 | case Match_UImm5_0_Report_UImm6: |
3809 | | // This is used on UImm5 operands that have a corresponding UImm5_32 |
3810 | | // operand to avoid confusing the user. |
3811 | 0 | return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), |
3812 | 0 | "expected 6-bit unsigned immediate"); |
3813 | 0 | case Match_UImm5_Lsl2: |
3814 | 0 | return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), |
3815 | 0 | "expected both 7-bit unsigned immediate and multiple of 4"); |
3816 | 2 | case Match_UImm6_0: |
3817 | 2 | return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), |
3818 | 2 | "expected 6-bit unsigned immediate"); |
3819 | 0 | case Match_SImm6: |
3820 | 0 | return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), |
3821 | 0 | "expected 6-bit signed immediate"); |
3822 | 0 | case Match_UImm7_0: |
3823 | 0 | return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), |
3824 | 0 | "expected 7-bit unsigned immediate"); |
3825 | 0 | case Match_UImm8_0: |
3826 | 0 | return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), |
3827 | 0 | "expected 8-bit unsigned immediate"); |
3828 | 3 | case Match_UImm10_0: |
3829 | 3 | return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), |
3830 | 3 | "expected 10-bit unsigned immediate"); |
3831 | 0 | case Match_UImm16: |
3832 | 0 | case Match_UImm16_Relaxed: |
3833 | 0 | return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), |
3834 | 0 | "expected 16-bit unsigned immediate"); |
3835 | 14.9k | } |
3836 | | |
3837 | 14.9k | llvm_unreachable("Implement any new match types added!"); |
3838 | 14.9k | } |
3839 | | |
3840 | 5.86k | void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) { |
3841 | 5.86k | if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex) { |
3842 | | // Warning(Loc, "used $at (currently $" + Twine(RegIndex) + |
3843 | | // ") without \".set noat\""); |
3844 | 788 | } |
3845 | 5.86k | } |
3846 | | |
3847 | 827 | void MipsAsmParser::warnIfNoMacro(SMLoc Loc) { |
3848 | 827 | if (!AssemblerOptions.back()->isMacro()) { |
3849 | | // Warning(Loc, "macro instruction expanded into multiple instructions"); |
3850 | 0 | } |
3851 | 827 | } |
3852 | | |
3853 | | void |
3854 | | MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg, |
3855 | 1.02k | SMRange Range, bool ShowColors) { |
3856 | 1.02k | getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg, |
3857 | 1.02k | Range, SMFixIt(Range, FixMsg), |
3858 | 1.02k | ShowColors); |
3859 | 1.02k | } |
3860 | | |
3861 | 15.1k | int MipsAsmParser::matchCPURegisterName(StringRef Name) { |
3862 | 15.1k | int CC; |
3863 | | |
3864 | 15.1k | CC = StringSwitch<unsigned>(Name) |
3865 | 15.1k | .Case("zero", 0) |
3866 | 15.1k | .Case("at", 1) |
3867 | 15.1k | .Case("a0", 4) |
3868 | 15.1k | .Case("a1", 5) |
3869 | 15.1k | .Case("a2", 6) |
3870 | 15.1k | .Case("a3", 7) |
3871 | 15.1k | .Case("v0", 2) |
3872 | 15.1k | .Case("v1", 3) |
3873 | 15.1k | .Case("s0", 16) |
3874 | 15.1k | .Case("s1", 17) |
3875 | 15.1k | .Case("s2", 18) |
3876 | 15.1k | .Case("s3", 19) |
3877 | 15.1k | .Case("s4", 20) |
3878 | 15.1k | .Case("s5", 21) |
3879 | 15.1k | .Case("s6", 22) |
3880 | 15.1k | .Case("s7", 23) |
3881 | 15.1k | .Case("k0", 26) |
3882 | 15.1k | .Case("k1", 27) |
3883 | 15.1k | .Case("gp", 28) |
3884 | 15.1k | .Case("sp", 29) |
3885 | 15.1k | .Case("fp", 30) |
3886 | 15.1k | .Case("s8", 30) |
3887 | 15.1k | .Case("ra", 31) |
3888 | 15.1k | .Case("t0", 8) |
3889 | 15.1k | .Case("t1", 9) |
3890 | 15.1k | .Case("t2", 10) |
3891 | 15.1k | .Case("t3", 11) |
3892 | 15.1k | .Case("t4", 12) |
3893 | 15.1k | .Case("t5", 13) |
3894 | 15.1k | .Case("t6", 14) |
3895 | 15.1k | .Case("t7", 15) |
3896 | 15.1k | .Case("t8", 24) |
3897 | 15.1k | .Case("t9", 25) |
3898 | 15.1k | .Default(-1); |
3899 | | |
3900 | 15.1k | if (!(isABI_N32() || isABI_N64())) |
3901 | 5.25k | return CC; |
3902 | | |
3903 | 9.93k | if (12 <= CC && CC <= 15) { |
3904 | | // Name is one of t4-t7 |
3905 | 1.02k | AsmToken RegTok = getLexer().peekTok(); |
3906 | 1.02k | SMRange RegRange = RegTok.getLocRange(); |
3907 | | |
3908 | 1.02k | StringRef FixedName = StringSwitch<StringRef>(Name) |
3909 | 1.02k | .Case("t4", "t0") |
3910 | 1.02k | .Case("t5", "t1") |
3911 | 1.02k | .Case("t6", "t2") |
3912 | 1.02k | .Case("t7", "t3") |
3913 | 1.02k | .Default(""); |
3914 | 1.02k | assert(FixedName != "" && "Register name is not one of t4-t7."); |
3915 | | |
3916 | 1.02k | printWarningWithFixIt("register names $t4-$t7 are only available in O32.", |
3917 | 1.02k | "Did you mean $" + FixedName + "?", RegRange); |
3918 | 1.02k | } |
3919 | | |
3920 | | // Although SGI documentation just cuts out t0-t3 for n32/n64, |
3921 | | // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7 |
3922 | | // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7. |
3923 | 9.93k | if (8 <= CC && CC <= 11) |
3924 | 259 | CC += 4; |
3925 | | |
3926 | 9.93k | if (CC == -1) |
3927 | 6.53k | CC = StringSwitch<unsigned>(Name) |
3928 | 6.53k | .Case("a4", 8) |
3929 | 6.53k | .Case("a5", 9) |
3930 | 6.53k | .Case("a6", 10) |
3931 | 6.53k | .Case("a7", 11) |
3932 | 6.53k | .Case("kt0", 26) |
3933 | 6.53k | .Case("kt1", 27) |
3934 | 6.53k | .Default(-1); |
3935 | | |
3936 | 9.93k | return CC; |
3937 | 9.93k | } |
3938 | | |
3939 | 8.91k | int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) { |
3940 | 8.91k | int CC; |
3941 | | |
3942 | 8.91k | CC = StringSwitch<unsigned>(Name) |
3943 | 8.91k | .Case("hwr_cpunum", 0) |
3944 | 8.91k | .Case("hwr_synci_step", 1) |
3945 | 8.91k | .Case("hwr_cc", 2) |
3946 | 8.91k | .Case("hwr_ccres", 3) |
3947 | 8.91k | .Case("hwr_ulr", 29) |
3948 | 8.91k | .Default(-1); |
3949 | | |
3950 | 8.91k | return CC; |
3951 | 8.91k | } |
3952 | | |
3953 | 8.88k | int MipsAsmParser::matchFPURegisterName(StringRef Name) { |
3954 | | |
3955 | 8.88k | if (Name[0] == 'f') { |
3956 | 1.89k | StringRef NumString = Name.substr(1); |
3957 | 1.89k | unsigned IntVal; |
3958 | 1.89k | if (NumString.getAsInteger(10, IntVal)) |
3959 | 1.47k | return -1; // This is not an integer. |
3960 | 420 | if (IntVal > 31) // Maximum index for fpu register. |
3961 | 289 | return -1; |
3962 | 131 | return IntVal; |
3963 | 420 | } |
3964 | 6.99k | return -1; |
3965 | 8.88k | } |
3966 | | |
3967 | 8.75k | int MipsAsmParser::matchFCCRegisterName(StringRef Name) { |
3968 | | |
3969 | 8.75k | if (Name.startswith("fcc")) { |
3970 | 269 | StringRef NumString = Name.substr(3); |
3971 | 269 | unsigned IntVal; |
3972 | 269 | if (NumString.getAsInteger(10, IntVal)) |
3973 | 197 | return -1; // This is not an integer. |
3974 | 72 | if (IntVal > 7) // There are only 8 fcc registers. |
3975 | 1 | return -1; |
3976 | 71 | return IntVal; |
3977 | 72 | } |
3978 | 8.48k | return -1; |
3979 | 8.75k | } |
3980 | | |
3981 | 8.68k | int MipsAsmParser::matchACRegisterName(StringRef Name) { |
3982 | | |
3983 | 8.68k | if (Name.startswith("ac")) { |
3984 | 289 | StringRef NumString = Name.substr(2); |
3985 | 289 | unsigned IntVal; |
3986 | 289 | if (NumString.getAsInteger(10, IntVal)) |
3987 | 130 | return -1; // This is not an integer. |
3988 | 159 | if (IntVal > 3) // There are only 3 acc registers. |
3989 | 107 | return -1; |
3990 | 52 | return IntVal; |
3991 | 159 | } |
3992 | 8.39k | return -1; |
3993 | 8.68k | } |
3994 | | |
3995 | 8.63k | int MipsAsmParser::matchMSA128RegisterName(StringRef Name) { |
3996 | 8.63k | unsigned IntVal; |
3997 | | |
3998 | 8.63k | if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal)) |
3999 | 8.63k | return -1; |
4000 | | |
4001 | 3 | if (IntVal > 31) |
4002 | 2 | return -1; |
4003 | | |
4004 | 1 | return IntVal; |
4005 | 3 | } |
4006 | | |
4007 | 8.63k | int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) { |
4008 | 8.63k | int CC; |
4009 | | |
4010 | 8.63k | CC = StringSwitch<unsigned>(Name) |
4011 | 8.63k | .Case("msair", 0) |
4012 | 8.63k | .Case("msacsr", 1) |
4013 | 8.63k | .Case("msaaccess", 2) |
4014 | 8.63k | .Case("msasave", 3) |
4015 | 8.63k | .Case("msamodify", 4) |
4016 | 8.63k | .Case("msarequest", 5) |
4017 | 8.63k | .Case("msamap", 6) |
4018 | 8.63k | .Case("msaunmap", 7) |
4019 | 8.63k | .Default(-1); |
4020 | | |
4021 | 8.63k | return CC; |
4022 | 8.63k | } |
4023 | | |
4024 | 977 | unsigned MipsAsmParser::getATReg(SMLoc Loc) { |
4025 | 977 | unsigned ATIndex = AssemblerOptions.back()->getATRegIndex(); |
4026 | 977 | if (ATIndex == 0) { |
4027 | 5 | reportParseError(Loc, |
4028 | 5 | "pseudo-instruction requires $at, which is not available"); |
4029 | 5 | return 0; |
4030 | 5 | } |
4031 | 972 | unsigned AT = getReg( |
4032 | 972 | (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex); |
4033 | 972 | return AT; |
4034 | 977 | } |
4035 | | |
4036 | 972 | unsigned MipsAsmParser::getReg(int RC, int RegNo) { |
4037 | 972 | return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo); |
4038 | 972 | } |
4039 | | |
4040 | | bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic, unsigned int &ErrorCode) |
4041 | 47.9k | { |
4042 | 47.9k | MCAsmParser &Parser = getParser(); |
4043 | 47.9k | DEBUG(dbgs() << "parseOperand\n"); |
4044 | | |
4045 | | // Check if the current operand has a custom associated parser, if so, try to |
4046 | | // custom parse the operand, or fallback to the general approach. |
4047 | 47.9k | OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic); |
4048 | 47.9k | if (ResTy == MatchOperand_Success) |
4049 | 17.4k | return false; |
4050 | | // If there wasn't a custom match, try the generic matcher below. Otherwise, |
4051 | | // there was a match, but an error occurred, in which case, just return that |
4052 | | // the operand parsing failed. |
4053 | 30.5k | if (ResTy == MatchOperand_ParseFail) |
4054 | 13.1k | return true; |
4055 | | |
4056 | 17.4k | DEBUG(dbgs() << ".. Generic Parser\n"); |
4057 | | |
4058 | 17.4k | switch (getLexer().getKind()) { |
4059 | 86 | default: |
4060 | | // Error(Parser.getTok().getLoc(), "unexpected token in operand"); |
4061 | 86 | ErrorCode = KS_ERR_ASM_MIPS_INVALIDOPERAND; |
4062 | 86 | return true; |
4063 | 13.3k | case AsmToken::Dollar: { |
4064 | | // Parse the register. |
4065 | 13.3k | SMLoc S = Parser.getTok().getLoc(); |
4066 | | |
4067 | | // Almost all registers have been parsed by custom parsers. There is only |
4068 | | // one exception to this. $zero (and it's alias $0) will reach this point |
4069 | | // for div, divu, and similar instructions because it is not an operand |
4070 | | // to the instruction definition but an explicit register. Special case |
4071 | | // this situation for now. |
4072 | 13.3k | if (parseAnyRegister(Operands) != MatchOperand_NoMatch) |
4073 | 4.77k | return false; |
4074 | | |
4075 | | // Maybe it is a symbol reference. |
4076 | 8.59k | StringRef Identifier; |
4077 | 8.59k | if (Parser.parseIdentifier(Identifier)) |
4078 | 4.19k | return true; |
4079 | | |
4080 | 4.40k | SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); |
4081 | 4.40k | MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier); |
4082 | | // Otherwise create a symbol reference. |
4083 | 4.40k | const MCExpr *Res = |
4084 | 4.40k | MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); |
4085 | | |
4086 | 4.40k | Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this)); |
4087 | 4.40k | return false; |
4088 | 8.59k | } |
4089 | | // Else drop to expression parsing. |
4090 | 75 | case AsmToken::LParen: |
4091 | 1.80k | case AsmToken::Minus: |
4092 | 2.16k | case AsmToken::Plus: |
4093 | 3.82k | case AsmToken::Integer: |
4094 | 3.88k | case AsmToken::Tilde: |
4095 | 3.94k | case AsmToken::String: { |
4096 | 3.94k | DEBUG(dbgs() << ".. generic integer\n"); |
4097 | 3.94k | OperandMatchResultTy ResTy = parseImm(Operands); |
4098 | 3.94k | return ResTy != MatchOperand_Success; |
4099 | 3.88k | } |
4100 | 12 | case AsmToken::Percent: { |
4101 | | // It is a symbol reference or constant expression. |
4102 | 12 | const MCExpr *IdVal; |
4103 | 12 | SMLoc S = Parser.getTok().getLoc(); // Start location of the operand. |
4104 | 12 | if (parseRelocOperand(IdVal)) |
4105 | 12 | return true; |
4106 | | |
4107 | 0 | SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); |
4108 | |
|
4109 | 0 | Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this)); |
4110 | 0 | return false; |
4111 | 12 | } // case AsmToken::Percent |
4112 | 17.4k | } // switch(getLexer().getKind()) |
4113 | 0 | return true; |
4114 | 17.4k | } |
4115 | | |
4116 | | const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr, |
4117 | 12.7k | StringRef RelocStr) { |
4118 | 12.7k | const MCExpr *Res; |
4119 | | // Check the type of the expression. |
4120 | 12.7k | if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) { |
4121 | | // It's a constant, evaluate reloc value. |
4122 | 2.29k | int16_t Val; |
4123 | 2.29k | switch (getVariantKind(RelocStr)) { |
4124 | 1.14k | case MCSymbolRefExpr::VK_Mips_ABS_LO: |
4125 | | // Get the 1st 16-bits. |
4126 | 1.14k | Val = MCE->getValue() & 0xffff; |
4127 | 1.14k | break; |
4128 | 1.14k | case MCSymbolRefExpr::VK_Mips_ABS_HI: |
4129 | | // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low |
4130 | | // 16 bits being negative. |
4131 | 1.14k | Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff; |
4132 | 1.14k | break; |
4133 | 0 | case MCSymbolRefExpr::VK_Mips_HIGHER: |
4134 | | // Get the 3rd 16-bits. |
4135 | 0 | Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff; |
4136 | 0 | break; |
4137 | 0 | case MCSymbolRefExpr::VK_Mips_HIGHEST: |
4138 | | // Get the 4th 16-bits. |
4139 | 0 | Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff; |
4140 | 0 | break; |
4141 | 0 | default: |
4142 | 0 | report_fatal_error("unsupported reloc value"); |
4143 | 2.29k | } |
4144 | 2.29k | return MCConstantExpr::create(Val, getContext()); |
4145 | 2.29k | } |
4146 | | |
4147 | 10.4k | if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) { |
4148 | | // It's a symbol, create a symbolic expression from the symbol. |
4149 | 3.43k | const MCSymbol *Symbol = &MSRE->getSymbol(); |
4150 | 3.43k | MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr); |
4151 | 3.43k | Res = MCSymbolRefExpr::create(Symbol, VK, getContext()); |
4152 | 3.43k | return Res; |
4153 | 3.43k | } |
4154 | | |
4155 | 7.03k | if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) { |
4156 | 5.65k | MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr); |
4157 | | |
4158 | | // Try to create target expression. |
4159 | 5.65k | if (MipsMCExpr::isSupportedBinaryExpr(VK, BE)) |
4160 | 274 | return MipsMCExpr::create(VK, Expr, getContext()); |
4161 | | |
4162 | 5.38k | const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr); |
4163 | 5.38k | const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr); |
4164 | 5.38k | Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext()); |
4165 | 5.38k | return Res; |
4166 | 5.65k | } |
4167 | | |
4168 | 1.38k | if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) { |
4169 | 1.38k | const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr); |
4170 | 1.38k | Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext()); |
4171 | 1.38k | return Res; |
4172 | 1.38k | } |
4173 | | // Just return the original expression. |
4174 | 0 | return Expr; |
4175 | 1.38k | } |
4176 | | |
4177 | 3.35k | bool MipsAsmParser::isEvaluated(const MCExpr *Expr) { |
4178 | | |
4179 | 3.35k | switch (Expr->getKind()) { |
4180 | 194 | case MCExpr::Constant: |
4181 | 194 | return true; |
4182 | 203 | case MCExpr::SymbolRef: |
4183 | 203 | return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None); |
4184 | 2.64k | case MCExpr::Binary: |
4185 | 2.64k | if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) { |
4186 | 2.64k | if (!isEvaluated(BE->getLHS())) |
4187 | 2.45k | return false; |
4188 | 196 | return isEvaluated(BE->getRHS()); |
4189 | 2.64k | } |
4190 | 305 | case MCExpr::Unary: |
4191 | 305 | return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr()); |
4192 | 0 | case MCExpr::Target: |
4193 | 0 | return true; |
4194 | 3.35k | } |
4195 | 0 | return false; |
4196 | 3.35k | } |
4197 | | |
4198 | 13 | bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) { |
4199 | 13 | MCAsmParser &Parser = getParser(); |
4200 | 13 | Parser.Lex(); // Eat the % token. |
4201 | 13 | const AsmToken &Tok = Parser.getTok(); // Get next token, operation. |
4202 | 13 | if (Tok.isNot(AsmToken::Identifier)) |
4203 | 0 | return true; |
4204 | | |
4205 | 13 | std::string Str = Tok.getIdentifier(); |
4206 | | |
4207 | 13 | Parser.Lex(); // Eat the identifier. |
4208 | | // Now make an expression from the rest of the operand. |
4209 | 13 | const MCExpr *IdVal; |
4210 | 13 | SMLoc EndLoc; |
4211 | | |
4212 | 13 | if (getLexer().getKind() == AsmToken::LParen) { |
4213 | 10 | while (1) { |
4214 | 10 | Parser.Lex(); // Eat the '(' token. |
4215 | 10 | if (getLexer().getKind() == AsmToken::Percent) { |
4216 | 3 | Parser.Lex(); // Eat the % token. |
4217 | 3 | const AsmToken &nextTok = Parser.getTok(); |
4218 | 3 | if (nextTok.isNot(AsmToken::Identifier)) |
4219 | 0 | return true; |
4220 | 3 | Str += "(%"; |
4221 | 3 | Str += nextTok.getIdentifier(); |
4222 | 3 | Parser.Lex(); // Eat the identifier. |
4223 | 3 | if (getLexer().getKind() != AsmToken::LParen) |
4224 | 1 | return true; |
4225 | 3 | } else |
4226 | 7 | break; |
4227 | 10 | } |
4228 | 7 | if (getParser().parseParenExpression(IdVal, EndLoc)) |
4229 | 7 | return true; |
4230 | | |
4231 | 0 | while (getLexer().getKind() == AsmToken::RParen) |
4232 | 0 | Parser.Lex(); // Eat the ')' token. |
4233 | |
|
4234 | 0 | } else |
4235 | 5 | return true; // Parenthesis must follow the relocation operand. |
4236 | | |
4237 | 0 | Res = evaluateRelocExpr(IdVal, Str); |
4238 | 0 | return false; |
4239 | 13 | } |
4240 | | |
4241 | | bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, |
4242 | 0 | SMLoc &EndLoc, unsigned int &ErrorCode) { |
4243 | 0 | SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands; |
4244 | 0 | OperandMatchResultTy ResTy = parseAnyRegister(Operands); |
4245 | 0 | if (ResTy == MatchOperand_Success) { |
4246 | 0 | assert(Operands.size() == 1); |
4247 | 0 | MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front()); |
4248 | 0 | StartLoc = Operand.getStartLoc(); |
4249 | 0 | EndLoc = Operand.getEndLoc(); |
4250 | | |
4251 | | // AFAIK, we only support numeric registers and named GPR's in CFI |
4252 | | // directives. |
4253 | | // Don't worry about eating tokens before failing. Using an unrecognised |
4254 | | // register is a parse error. |
4255 | 0 | if (Operand.isGPRAsmReg()) { |
4256 | | // Resolve to GPR32 or GPR64 appropriately. |
4257 | 0 | RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg(); |
4258 | 0 | } |
4259 | |
|
4260 | 0 | return (RegNo == (unsigned)-1); |
4261 | 0 | } |
4262 | | |
4263 | 0 | assert(Operands.size() == 0); |
4264 | 0 | return (RegNo == (unsigned)-1); |
4265 | 0 | } |
4266 | | |
4267 | 1.05k | bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) { |
4268 | 1.05k | MCAsmParser &Parser = getParser(); |
4269 | 1.05k | SMLoc S; |
4270 | 1.05k | bool Result = true; |
4271 | 1.05k | unsigned NumOfLParen = 0; |
4272 | | |
4273 | 1.10k | while (getLexer().getKind() == AsmToken::LParen) { |
4274 | 46 | Parser.Lex(); |
4275 | 46 | ++NumOfLParen; |
4276 | 46 | } |
4277 | | |
4278 | 1.05k | switch (getLexer().getKind()) { |
4279 | 7 | default: |
4280 | 7 | return true; |
4281 | 195 | case AsmToken::Identifier: |
4282 | 195 | case AsmToken::LParen: |
4283 | 812 | case AsmToken::Integer: |
4284 | 973 | case AsmToken::Minus: |
4285 | 1.05k | case AsmToken::Plus: |
4286 | 1.05k | if (isParenExpr) |
4287 | 42 | Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S); |
4288 | 1.00k | else |
4289 | 1.00k | Result = (getParser().parseExpression(Res)); |
4290 | 1.36k | while (getLexer().getKind() == AsmToken::RParen) |
4291 | 310 | Parser.Lex(); |
4292 | 1.05k | break; |
4293 | 1 | case AsmToken::Percent: |
4294 | 1 | Result = parseRelocOperand(Res); |
4295 | 1.05k | } |
4296 | 1.05k | return Result; |
4297 | 1.05k | } |
4298 | | |
4299 | | MipsAsmParser::OperandMatchResultTy |
4300 | 1.11k | MipsAsmParser::parseMemOperand(OperandVector &Operands) { |
4301 | 1.11k | MCAsmParser &Parser = getParser(); |
4302 | 1.11k | DEBUG(dbgs() << "parseMemOperand\n"); |
4303 | 1.11k | const MCExpr *IdVal = nullptr; |
4304 | 1.11k | SMLoc S; |
4305 | 1.11k | bool isParenExpr = false; |
4306 | 1.11k | MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch; |
4307 | | // First operand is the offset. |
4308 | 1.11k | S = Parser.getTok().getLoc(); |
4309 | | |
4310 | 1.11k | if (getLexer().getKind() == AsmToken::LParen) { |
4311 | 45 | Parser.Lex(); |
4312 | 45 | isParenExpr = true; |
4313 | 45 | } |
4314 | | |
4315 | 1.11k | if (getLexer().getKind() != AsmToken::Dollar) { |
4316 | 1.05k | if (parseMemOffset(IdVal, isParenExpr)) |
4317 | 130 | return MatchOperand_ParseFail; |
4318 | | |
4319 | 928 | const AsmToken &Tok = Parser.getTok(); // Get the next token. |
4320 | 928 | if (Tok.isNot(AsmToken::LParen)) { |
4321 | 927 | MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]); |
4322 | 927 | if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") { |
4323 | 34 | SMLoc E = |
4324 | 34 | SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); |
4325 | 34 | Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this)); |
4326 | 34 | return MatchOperand_Success; |
4327 | 34 | } |
4328 | 893 | if (Tok.is(AsmToken::EndOfStatement)) { |
4329 | 878 | SMLoc E = |
4330 | 878 | SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); |
4331 | | |
4332 | | // Zero register assumed, add a memory operand with ZERO as its base. |
4333 | | // "Base" will be managed by k_Memory. |
4334 | 878 | auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(), |
4335 | 878 | S, E, *this); |
4336 | 878 | Operands.push_back( |
4337 | 878 | MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this)); |
4338 | 878 | return MatchOperand_Success; |
4339 | 878 | } |
4340 | 15 | Error(Parser.getTok().getLoc(), "'(' expected"); |
4341 | 15 | return MatchOperand_ParseFail; |
4342 | 893 | } |
4343 | | |
4344 | 1 | Parser.Lex(); // Eat the '(' token. |
4345 | 1 | } |
4346 | | |
4347 | 55 | Res = parseAnyRegister(Operands); |
4348 | 55 | if (Res != MatchOperand_Success) |
4349 | 55 | return Res; |
4350 | | |
4351 | 0 | if (Parser.getTok().isNot(AsmToken::RParen)) { |
4352 | 0 | Error(Parser.getTok().getLoc(), "')' expected"); |
4353 | 0 | return MatchOperand_ParseFail; |
4354 | 0 | } |
4355 | | |
4356 | 0 | SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); |
4357 | |
|
4358 | 0 | Parser.Lex(); // Eat the ')' token. |
4359 | |
|
4360 | 0 | if (!IdVal) |
4361 | 0 | IdVal = MCConstantExpr::create(0, getContext()); |
4362 | | |
4363 | | // Replace the register operand with the memory operand. |
4364 | 0 | std::unique_ptr<MipsOperand> op( |
4365 | 0 | static_cast<MipsOperand *>(Operands.back().release())); |
4366 | | // Remove the register from the operands. |
4367 | | // "op" will be managed by k_Memory. |
4368 | 0 | Operands.pop_back(); |
4369 | | // Add the memory operand. |
4370 | 0 | if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) { |
4371 | 0 | int64_t Imm; |
4372 | 0 | if (IdVal->evaluateAsAbsolute(Imm)) |
4373 | 0 | IdVal = MCConstantExpr::create(Imm, getContext()); |
4374 | 0 | else if (BE->getLHS()->getKind() != MCExpr::SymbolRef) |
4375 | 0 | IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(), |
4376 | 0 | getContext()); |
4377 | 0 | } |
4378 | |
|
4379 | 0 | Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this)); |
4380 | 0 | return MatchOperand_Success; |
4381 | 0 | } |
4382 | | |
4383 | 9.44k | bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) { |
4384 | 9.44k | MCAsmParser &Parser = getParser(); |
4385 | 9.44k | MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier()); |
4386 | 9.44k | if (Sym) { |
4387 | 5.72k | SMLoc S = Parser.getTok().getLoc(); |
4388 | 5.72k | const MCExpr *Expr; |
4389 | 5.72k | if (Sym->isVariable()) |
4390 | 566 | Expr = Sym->getVariableValue(); |
4391 | 5.16k | else |
4392 | 5.16k | return false; |
4393 | 566 | if (Expr->getKind() == MCExpr::SymbolRef) { |
4394 | 486 | const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr); |
4395 | 486 | StringRef DefSymbol = Ref->getSymbol().getName(); |
4396 | 486 | if (DefSymbol.startswith("$")) { |
4397 | 387 | OperandMatchResultTy ResTy = |
4398 | 387 | matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S); |
4399 | 387 | if (ResTy == MatchOperand_Success) { |
4400 | 1 | Parser.Lex(); |
4401 | 1 | return true; |
4402 | 386 | } else if (ResTy == MatchOperand_ParseFail) |
4403 | 0 | llvm_unreachable("Should never ParseFail"); |
4404 | 386 | return false; |
4405 | 387 | } |
4406 | 486 | } else if (Expr->getKind() == MCExpr::Constant) { |
4407 | 49 | Parser.Lex(); |
4408 | 49 | const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr); |
4409 | 49 | Operands.push_back( |
4410 | 49 | MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this)); |
4411 | 49 | return true; |
4412 | 49 | } |
4413 | 566 | } |
4414 | 3.85k | return false; |
4415 | 9.44k | } |
4416 | | |
4417 | | MipsAsmParser::OperandMatchResultTy |
4418 | | MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands, |
4419 | | StringRef Identifier, |
4420 | 15.1k | SMLoc S) { |
4421 | 15.1k | int Index = matchCPURegisterName(Identifier); |
4422 | 15.1k | if (Index != -1) { |
4423 | 6.23k | Operands.push_back(MipsOperand::createGPRReg( |
4424 | 6.23k | Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this)); |
4425 | 6.23k | return MatchOperand_Success; |
4426 | 6.23k | } |
4427 | | |
4428 | 8.91k | Index = matchHWRegsRegisterName(Identifier); |
4429 | 8.91k | if (Index != -1) { |
4430 | 21 | Operands.push_back(MipsOperand::createHWRegsReg( |
4431 | 21 | Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this)); |
4432 | 21 | return MatchOperand_Success; |
4433 | 21 | } |
4434 | | |
4435 | 8.88k | Index = matchFPURegisterName(Identifier); |
4436 | 8.88k | if (Index != -1) { |
4437 | 131 | Operands.push_back(MipsOperand::createFGRReg( |
4438 | 131 | Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this)); |
4439 | 131 | return MatchOperand_Success; |
4440 | 131 | } |
4441 | | |
4442 | 8.75k | Index = matchFCCRegisterName(Identifier); |
4443 | 8.75k | if (Index != -1) { |
4444 | 71 | Operands.push_back(MipsOperand::createFCCReg( |
4445 | 71 | Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this)); |
4446 | 71 | return MatchOperand_Success; |
4447 | 71 | } |
4448 | | |
4449 | 8.68k | Index = matchACRegisterName(Identifier); |
4450 | 8.68k | if (Index != -1) { |
4451 | 52 | Operands.push_back(MipsOperand::createACCReg( |
4452 | 52 | Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this)); |
4453 | 52 | return MatchOperand_Success; |
4454 | 52 | } |
4455 | | |
4456 | 8.63k | Index = matchMSA128RegisterName(Identifier); |
4457 | 8.63k | if (Index != -1) { |
4458 | 1 | Operands.push_back(MipsOperand::createMSA128Reg( |
4459 | 1 | Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this)); |
4460 | 1 | return MatchOperand_Success; |
4461 | 1 | } |
4462 | | |
4463 | 8.63k | Index = matchMSA128CtrlRegisterName(Identifier); |
4464 | 8.63k | if (Index != -1) { |
4465 | 180 | Operands.push_back(MipsOperand::createMSACtrlReg( |
4466 | 180 | Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this)); |
4467 | 180 | return MatchOperand_Success; |
4468 | 180 | } |
4469 | | |
4470 | 8.45k | return MatchOperand_NoMatch; |
4471 | 8.63k | } |
4472 | | |
4473 | | MipsAsmParser::OperandMatchResultTy |
4474 | | MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) |
4475 | 47.6k | { |
4476 | 47.6k | MCAsmParser &Parser = getParser(); |
4477 | 47.6k | auto Token = Parser.getLexer().peekTok(false); |
4478 | | |
4479 | 47.6k | if (Token.is(AsmToken::Identifier)) { |
4480 | 14.7k | DEBUG(dbgs() << ".. identifier\n"); |
4481 | 14.7k | StringRef Identifier = Token.getIdentifier(); |
4482 | 14.7k | OperandMatchResultTy ResTy = |
4483 | 14.7k | matchAnyRegisterNameWithoutDollar(Operands, Identifier, S); |
4484 | 14.7k | return ResTy; |
4485 | 32.9k | } else if (Token.is(AsmToken::Integer)) { |
4486 | 10.2k | DEBUG(dbgs() << ".. integer\n"); |
4487 | 10.2k | bool valid; |
4488 | 10.2k | unsigned Value = Token.getIntVal(valid); |
4489 | 10.2k | if (!valid) |
4490 | 0 | return MatchOperand_NoMatch; |
4491 | 10.2k | Operands.push_back(MipsOperand::createNumericReg( |
4492 | 10.2k | Value, getContext().getRegisterInfo(), S, Token.getLoc(), |
4493 | 10.2k | *this)); |
4494 | 10.2k | return MatchOperand_Success; |
4495 | 10.2k | } |
4496 | | |
4497 | 22.6k | DEBUG(dbgs() << Parser.getTok().getKind() << "\n"); |
4498 | | |
4499 | 22.6k | return MatchOperand_NoMatch; |
4500 | 47.6k | } |
4501 | | |
4502 | | MipsAsmParser::OperandMatchResultTy |
4503 | 79.6k | MipsAsmParser::parseAnyRegister(OperandVector &Operands) { |
4504 | 79.6k | MCAsmParser &Parser = getParser(); |
4505 | 79.6k | DEBUG(dbgs() << "parseAnyRegister\n"); |
4506 | | |
4507 | 79.6k | auto Token = Parser.getTok(); |
4508 | | |
4509 | 79.6k | SMLoc S = Token.getLoc(); |
4510 | | |
4511 | 79.6k | if (Token.isNot(AsmToken::Dollar)) { |
4512 | 31.9k | DEBUG(dbgs() << ".. !$ -> try sym aliasing\n"); |
4513 | 31.9k | if (Token.is(AsmToken::Identifier)) { |
4514 | 9.44k | if (searchSymbolAlias(Operands)) |
4515 | 50 | return MatchOperand_Success; |
4516 | 9.44k | } |
4517 | 31.9k | DEBUG(dbgs() << ".. !symalias -> NoMatch\n"); |
4518 | 31.9k | return MatchOperand_NoMatch; |
4519 | 31.9k | } |
4520 | 47.6k | DEBUG(dbgs() << ".. $\n"); |
4521 | | |
4522 | 47.6k | OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S); |
4523 | 47.6k | if (ResTy == MatchOperand_Success) { |
4524 | 16.9k | Parser.Lex(); // $ |
4525 | 16.9k | Parser.Lex(); // identifier |
4526 | 16.9k | } |
4527 | 47.6k | return ResTy; |
4528 | 79.6k | } |
4529 | | |
4530 | | MipsAsmParser::OperandMatchResultTy |
4531 | 28.8k | MipsAsmParser::parseImm(OperandVector &Operands) { |
4532 | 28.8k | MCAsmParser &Parser = getParser(); |
4533 | 28.8k | switch (getLexer().getKind()) { |
4534 | 9.49k | default: |
4535 | 9.49k | return MatchOperand_NoMatch; |
4536 | 186 | case AsmToken::LParen: |
4537 | 12.6k | case AsmToken::Minus: |
4538 | 17.0k | case AsmToken::Plus: |
4539 | 19.1k | case AsmToken::Integer: |
4540 | 19.2k | case AsmToken::Tilde: |
4541 | 19.3k | case AsmToken::String: |
4542 | 19.3k | break; |
4543 | 28.8k | } |
4544 | | |
4545 | 19.3k | const MCExpr *IdVal; |
4546 | 19.3k | SMLoc S = Parser.getTok().getLoc(); |
4547 | 19.3k | if (getParser().parseExpression(IdVal)) |
4548 | 11.4k | return MatchOperand_ParseFail; |
4549 | | |
4550 | 7.88k | SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); |
4551 | 7.88k | Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this)); |
4552 | 7.88k | return MatchOperand_Success; |
4553 | 19.3k | } |
4554 | | |
4555 | | MipsAsmParser::OperandMatchResultTy |
4556 | 24.8k | MipsAsmParser::parseJumpTarget(OperandVector &Operands) { |
4557 | 24.8k | MCAsmParser &Parser = getParser(); |
4558 | 24.8k | DEBUG(dbgs() << "parseJumpTarget\n"); |
4559 | | |
4560 | 24.8k | SMLoc S = getLexer().getLoc(); |
4561 | | |
4562 | | // Integers and expressions are acceptable |
4563 | 24.8k | OperandMatchResultTy ResTy = parseImm(Operands); |
4564 | 24.8k | if (ResTy != MatchOperand_NoMatch) |
4565 | 15.3k | return ResTy; |
4566 | | |
4567 | | // Registers are a valid target and have priority over symbols. |
4568 | 9.49k | ResTy = parseAnyRegister(Operands); |
4569 | 9.49k | if (ResTy != MatchOperand_NoMatch) |
4570 | 375 | return ResTy; |
4571 | | |
4572 | 9.11k | const MCExpr *Expr = nullptr; |
4573 | 9.11k | if (Parser.parseExpression(Expr)) { |
4574 | | // We have no way of knowing if a symbol was consumed so we must ParseFail |
4575 | 1.88k | return MatchOperand_ParseFail; |
4576 | 1.88k | } |
4577 | 7.23k | Operands.push_back( |
4578 | 7.23k | MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this)); |
4579 | 7.23k | return MatchOperand_Success; |
4580 | 9.11k | } |
4581 | | |
4582 | | MipsAsmParser::OperandMatchResultTy |
4583 | 19 | MipsAsmParser::parseInvNum(OperandVector &Operands) { |
4584 | 19 | MCAsmParser &Parser = getParser(); |
4585 | 19 | const MCExpr *IdVal; |
4586 | | // If the first token is '$' we may have register operand. |
4587 | 19 | if (Parser.getTok().is(AsmToken::Dollar)) |
4588 | 17 | return MatchOperand_NoMatch; |
4589 | 2 | SMLoc S = Parser.getTok().getLoc(); |
4590 | 2 | if (getParser().parseExpression(IdVal)) |
4591 | 2 | return MatchOperand_ParseFail; |
4592 | 0 | const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal); |
4593 | 0 | assert(MCE && "Unexpected MCExpr type."); |
4594 | 0 | int64_t Val = MCE->getValue(); |
4595 | 0 | SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); |
4596 | 0 | Operands.push_back(MipsOperand::CreateImm( |
4597 | 0 | MCConstantExpr::create(0 - Val, getContext()), S, E, *this)); |
4598 | 0 | return MatchOperand_Success; |
4599 | 0 | } |
4600 | | |
4601 | | MipsAsmParser::OperandMatchResultTy |
4602 | 0 | MipsAsmParser::parseRegisterList(OperandVector &Operands) { |
4603 | 0 | MCAsmParser &Parser = getParser(); |
4604 | 0 | SmallVector<unsigned, 10> Regs; |
4605 | 0 | unsigned RegNo; |
4606 | 0 | unsigned PrevReg = Mips::NoRegister; |
4607 | 0 | bool RegRange = false; |
4608 | 0 | SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands; |
4609 | |
|
4610 | 0 | if (Parser.getTok().isNot(AsmToken::Dollar)) |
4611 | 0 | return MatchOperand_ParseFail; |
4612 | | |
4613 | 0 | SMLoc S = Parser.getTok().getLoc(); |
4614 | 0 | while (parseAnyRegister(TmpOperands) == MatchOperand_Success) { |
4615 | 0 | SMLoc E = getLexer().getLoc(); |
4616 | 0 | MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back()); |
4617 | 0 | RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg(); |
4618 | 0 | if (RegRange) { |
4619 | | // Remove last register operand because registers from register range |
4620 | | // should be inserted first. |
4621 | 0 | if ((isGP64bit() && RegNo == Mips::RA_64) || |
4622 | 0 | (!isGP64bit() && RegNo == Mips::RA)) { |
4623 | 0 | Regs.push_back(RegNo); |
4624 | 0 | } else { |
4625 | 0 | unsigned TmpReg = PrevReg + 1; |
4626 | 0 | while (TmpReg <= RegNo) { |
4627 | 0 | if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) || |
4628 | 0 | (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) && |
4629 | 0 | isGP64bit())) { |
4630 | 0 | Error(E, "invalid register operand"); |
4631 | 0 | return MatchOperand_ParseFail; |
4632 | 0 | } |
4633 | | |
4634 | 0 | PrevReg = TmpReg; |
4635 | 0 | Regs.push_back(TmpReg++); |
4636 | 0 | } |
4637 | 0 | } |
4638 | | |
4639 | 0 | RegRange = false; |
4640 | 0 | } else { |
4641 | 0 | if ((PrevReg == Mips::NoRegister) && |
4642 | 0 | ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) || |
4643 | 0 | (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) { |
4644 | 0 | Error(E, "$16 or $31 expected"); |
4645 | 0 | return MatchOperand_ParseFail; |
4646 | 0 | } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA || |
4647 | 0 | (RegNo >= Mips::S0 && RegNo <= Mips::S7)) && |
4648 | 0 | !isGP64bit()) || |
4649 | 0 | ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 || |
4650 | 0 | (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) && |
4651 | 0 | isGP64bit()))) { |
4652 | 0 | Error(E, "invalid register operand"); |
4653 | 0 | return MatchOperand_ParseFail; |
4654 | 0 | } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) && |
4655 | 0 | ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) || |
4656 | 0 | (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 && |
4657 | 0 | isGP64bit()))) { |
4658 | 0 | Error(E, "consecutive register numbers expected"); |
4659 | 0 | return MatchOperand_ParseFail; |
4660 | 0 | } |
4661 | | |
4662 | 0 | Regs.push_back(RegNo); |
4663 | 0 | } |
4664 | | |
4665 | 0 | if (Parser.getTok().is(AsmToken::Minus)) |
4666 | 0 | RegRange = true; |
4667 | |
|
4668 | 0 | if (!Parser.getTok().isNot(AsmToken::Minus) && |
4669 | 0 | !Parser.getTok().isNot(AsmToken::Comma)) { |
4670 | 0 | Error(E, "',' or '-' expected"); |
4671 | 0 | return MatchOperand_ParseFail; |
4672 | 0 | } |
4673 | | |
4674 | 0 | Lex(); // Consume comma or minus |
4675 | 0 | if (Parser.getTok().isNot(AsmToken::Dollar)) |
4676 | 0 | break; |
4677 | | |
4678 | 0 | PrevReg = RegNo; |
4679 | 0 | } |
4680 | | |
4681 | 0 | SMLoc E = Parser.getTok().getLoc(); |
4682 | 0 | Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this)); |
4683 | 0 | parseMemOperand(Operands); |
4684 | 0 | return MatchOperand_Success; |
4685 | 0 | } |
4686 | | |
4687 | | MipsAsmParser::OperandMatchResultTy |
4688 | 0 | MipsAsmParser::parseRegisterPair(OperandVector &Operands) { |
4689 | 0 | MCAsmParser &Parser = getParser(); |
4690 | |
|
4691 | 0 | SMLoc S = Parser.getTok().getLoc(); |
4692 | 0 | if (parseAnyRegister(Operands) != MatchOperand_Success) |
4693 | 0 | return MatchOperand_ParseFail; |
4694 | | |
4695 | 0 | SMLoc E = Parser.getTok().getLoc(); |
4696 | 0 | MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back()); |
4697 | 0 | unsigned Reg = Op.getGPR32Reg(); |
4698 | 0 | Operands.pop_back(); |
4699 | 0 | Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this)); |
4700 | 0 | return MatchOperand_Success; |
4701 | 0 | } |
4702 | | |
4703 | | MipsAsmParser::OperandMatchResultTy |
4704 | 0 | MipsAsmParser::parseMovePRegPair(OperandVector &Operands) { |
4705 | 0 | MCAsmParser &Parser = getParser(); |
4706 | 0 | SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands; |
4707 | 0 | SmallVector<unsigned, 10> Regs; |
4708 | |
|
4709 | 0 | if (Parser.getTok().isNot(AsmToken::Dollar)) |
4710 | 0 | return MatchOperand_ParseFail; |
4711 | | |
4712 | 0 | SMLoc S = Parser.getTok().getLoc(); |
4713 | |
|
4714 | 0 | if (parseAnyRegister(TmpOperands) != MatchOperand_Success) |
4715 | 0 | return MatchOperand_ParseFail; |
4716 | | |
4717 | 0 | MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back()); |
4718 | 0 | unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg(); |
4719 | 0 | Regs.push_back(RegNo); |
4720 | |
|
4721 | 0 | SMLoc E = Parser.getTok().getLoc(); |
4722 | 0 | if (Parser.getTok().isNot(AsmToken::Comma)) { |
4723 | 0 | Error(E, "',' expected"); |
4724 | 0 | return MatchOperand_ParseFail; |
4725 | 0 | } |
4726 | | |
4727 | | // Remove comma. |
4728 | 0 | Parser.Lex(); |
4729 | |
|
4730 | 0 | if (parseAnyRegister(TmpOperands) != MatchOperand_Success) |
4731 | 0 | return MatchOperand_ParseFail; |
4732 | | |
4733 | 0 | Reg = &static_cast<MipsOperand &>(*TmpOperands.back()); |
4734 | 0 | RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg(); |
4735 | 0 | Regs.push_back(RegNo); |
4736 | |
|
4737 | 0 | Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this)); |
4738 | |
|
4739 | 0 | return MatchOperand_Success; |
4740 | 0 | } |
4741 | | |
4742 | 11.3k | MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) { |
4743 | | |
4744 | 11.3k | MCSymbolRefExpr::VariantKind VK = |
4745 | 11.3k | StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol) |
4746 | 11.3k | .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI) |
4747 | 11.3k | .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO) |
4748 | 11.3k | .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL) |
4749 | 11.3k | .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL) |
4750 | 11.3k | .Case("got", MCSymbolRefExpr::VK_Mips_GOT) |
4751 | 11.3k | .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD) |
4752 | 11.3k | .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM) |
4753 | 11.3k | .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI) |
4754 | 11.3k | .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO) |
4755 | 11.3k | .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL) |
4756 | 11.3k | .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI) |
4757 | 11.3k | .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO) |
4758 | 11.3k | .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP) |
4759 | 11.3k | .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE) |
4760 | 11.3k | .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST) |
4761 | 11.3k | .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI) |
4762 | 11.3k | .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO) |
4763 | 11.3k | .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16) |
4764 | 11.3k | .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16) |
4765 | 11.3k | .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16) |
4766 | 11.3k | .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16) |
4767 | 11.3k | .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER) |
4768 | 11.3k | .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST) |
4769 | 11.3k | .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16) |
4770 | 11.3k | .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16) |
4771 | 11.3k | .Default(MCSymbolRefExpr::VK_None); |
4772 | | |
4773 | 11.3k | assert(VK != MCSymbolRefExpr::VK_None); |
4774 | | |
4775 | 11.3k | return VK; |
4776 | 11.3k | } |
4777 | | |
4778 | | /// Sometimes (i.e. load/stores) the operand may be followed immediately by |
4779 | | /// either this. |
4780 | | /// ::= '(', register, ')' |
4781 | | /// handle it before we iterate so we don't get tripped up by the lack of |
4782 | | /// a comma. |
4783 | 31 | bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands, unsigned int &ErrorCode) { |
4784 | 31 | MCAsmParser &Parser = getParser(); |
4785 | 31 | if (getLexer().is(AsmToken::LParen)) { |
4786 | 31 | Operands.push_back( |
4787 | 31 | MipsOperand::CreateToken("(", getLexer().getLoc(), *this)); |
4788 | 31 | Parser.Lex(); |
4789 | 31 | if (parseOperand(Operands, Name, ErrorCode)) { |
4790 | | // SMLoc Loc = getLexer().getLoc(); |
4791 | 10 | Parser.eatToEndOfStatement(); |
4792 | | //return Error(Loc, "unexpected token in argument list"); |
4793 | 10 | return true; |
4794 | 10 | } |
4795 | 21 | if (Parser.getTok().isNot(AsmToken::RParen)) { |
4796 | | // SMLoc Loc = getLexer().getLoc(); |
4797 | 4 | Parser.eatToEndOfStatement(); |
4798 | | // return Error(Loc, "unexpected token, expected ')'"); |
4799 | 4 | ErrorCode = KS_ERR_ASM_MIPS_INVALIDOPERAND; |
4800 | 4 | return true; |
4801 | 4 | } |
4802 | 17 | Operands.push_back( |
4803 | 17 | MipsOperand::CreateToken(")", getLexer().getLoc(), *this)); |
4804 | 17 | Parser.Lex(); |
4805 | 17 | } |
4806 | 17 | return false; |
4807 | 31 | } |
4808 | | |
4809 | | /// Sometimes (i.e. in MSA) the operand may be followed immediately by |
4810 | | /// either one of these. |
4811 | | /// ::= '[', register, ']' |
4812 | | /// ::= '[', integer, ']' |
4813 | | /// handle it before we iterate so we don't get tripped up by the lack of |
4814 | | /// a comma. |
4815 | | bool MipsAsmParser::parseBracketSuffix(StringRef Name, |
4816 | 116 | OperandVector &Operands, unsigned int &ErrorCode) { |
4817 | 116 | MCAsmParser &Parser = getParser(); |
4818 | 116 | if (getLexer().is(AsmToken::LBrac)) { |
4819 | 116 | Operands.push_back( |
4820 | 116 | MipsOperand::CreateToken("[", getLexer().getLoc(), *this)); |
4821 | 116 | Parser.Lex(); |
4822 | 116 | if (parseOperand(Operands, Name, ErrorCode)) { |
4823 | | // SMLoc Loc = getLexer().getLoc(); |
4824 | 38 | Parser.eatToEndOfStatement(); |
4825 | | //return Error(Loc, "unexpected token in argument list"); |
4826 | 38 | return true; |
4827 | 38 | } |
4828 | 78 | if (Parser.getTok().isNot(AsmToken::RBrac)) { |
4829 | | // SMLoc Loc = getLexer().getLoc(); |
4830 | 2 | Parser.eatToEndOfStatement(); |
4831 | | //return Error(Loc, "unexpected token, expected ']'"); |
4832 | 2 | ErrorCode = KS_ERR_ASM_MIPS_INVALIDOPERAND; |
4833 | 2 | return true; |
4834 | 2 | } |
4835 | 76 | Operands.push_back( |
4836 | 76 | MipsOperand::CreateToken("]", getLexer().getLoc(), *this)); |
4837 | 76 | Parser.Lex(); |
4838 | 76 | } |
4839 | 76 | return false; |
4840 | 116 | } |
4841 | | |
4842 | | bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, |
4843 | | SMLoc NameLoc, OperandVector &Operands, unsigned int &ErrorCode) |
4844 | 34.1k | { |
4845 | 34.1k | MCAsmParser &Parser = getParser(); |
4846 | 34.1k | DEBUG(dbgs() << "ParseInstruction\n"); |
4847 | | |
4848 | | // We have reached first instruction, module directive are now forbidden. |
4849 | | //getTargetStreamer().forbidModuleDirective(); |
4850 | | |
4851 | | // Check if we have valid mnemonic |
4852 | 34.1k | if (!mnemonicIsValid(Name, 0)) { |
4853 | 891 | Parser.eatToEndOfStatement(); |
4854 | | // return Error(NameLoc, "unknown instruction"); |
4855 | 891 | ErrorCode = KS_ERR_ASM_MIPS_MNEMONICFAIL; |
4856 | 891 | return true; |
4857 | 891 | } |
4858 | | // First operand in MCInst is instruction mnemonic. |
4859 | 33.2k | Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this)); |
4860 | | |
4861 | | // Read the remaining operands. |
4862 | 33.2k | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
4863 | | // Read the first operand. |
4864 | 33.1k | if (parseOperand(Operands, Name, ErrorCode)) { |
4865 | | // SMLoc Loc = getLexer().getLoc(); |
4866 | 16.7k | Parser.eatToEndOfStatement(); |
4867 | | // return Error(Loc, "unexpected token in argument list"); |
4868 | | // ErrorCode = KS_ERR_ASM_MIPS_INVALIDOPERAND; |
4869 | 16.7k | return true; |
4870 | 16.7k | } |
4871 | 16.3k | if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands, ErrorCode)) |
4872 | 39 | return true; |
4873 | | // AFAIK, parenthesis suffixes are never on the first operand |
4874 | | |
4875 | 30.0k | while (getLexer().is(AsmToken::Comma)) { |
4876 | 14.6k | Parser.Lex(); // Eat the comma. |
4877 | | // Parse and remember the operand. |
4878 | 14.6k | if (parseOperand(Operands, Name, ErrorCode)) { |
4879 | | // SMLoc Loc = getLexer().getLoc(); |
4880 | 937 | Parser.eatToEndOfStatement(); |
4881 | | // return Error(Loc, "unexpected token in argument list"); |
4882 | 937 | return true; |
4883 | 937 | } |
4884 | | // Parse bracket and parenthesis suffixes before we iterate |
4885 | 13.7k | if (getLexer().is(AsmToken::LBrac)) { |
4886 | 62 | if (parseBracketSuffix(Name, Operands, ErrorCode)) |
4887 | 1 | return true; |
4888 | 13.6k | } else if (getLexer().is(AsmToken::LParen) && |
4889 | 31 | parseParenSuffix(Name, Operands, ErrorCode)) |
4890 | 14 | return true; |
4891 | 13.7k | } |
4892 | 16.3k | } |
4893 | 15.5k | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
4894 | | // SMLoc Loc = getLexer().getLoc(); |
4895 | 523 | Parser.eatToEndOfStatement(); |
4896 | | // return Error(Loc, "unexpected token in argument list"); |
4897 | 523 | ErrorCode = KS_ERR_ASM_MIPS_INVALIDOPERAND; |
4898 | 523 | return true; |
4899 | 523 | } |
4900 | 14.9k | Parser.Lex(); // Consume the EndOfStatement. |
4901 | 14.9k | return false; |
4902 | 15.5k | } |
4903 | | |
4904 | 37.4k | bool MipsAsmParser::reportParseError(Twine ErrorMsg) { |
4905 | 37.4k | MCAsmParser &Parser = getParser(); |
4906 | 37.4k | SMLoc Loc = getLexer().getLoc(); |
4907 | 37.4k | Parser.eatToEndOfStatement(); |
4908 | 37.4k | return Error(Loc, ErrorMsg); |
4909 | 37.4k | } |
4910 | | |
4911 | 2.00k | bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) { |
4912 | 2.00k | return Error(Loc, ErrorMsg); |
4913 | 2.00k | } |
4914 | | |
4915 | 91 | bool MipsAsmParser::parseSetNoAtDirective() { |
4916 | 91 | MCAsmParser &Parser = getParser(); |
4917 | | // Line should look like: ".set noat". |
4918 | | |
4919 | | // Set the $at register to $0. |
4920 | 91 | AssemblerOptions.back()->setATRegIndex(0); |
4921 | | |
4922 | 91 | Parser.Lex(); // Eat "noat". |
4923 | | |
4924 | | // If this is not the end of the statement, report an error. |
4925 | 91 | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
4926 | 52 | reportParseError("unexpected token, expected end of statement"); |
4927 | 52 | return false; |
4928 | 52 | } |
4929 | | |
4930 | | //getTargetStreamer().emitDirectiveSetNoAt(); |
4931 | 39 | Parser.Lex(); // Consume the EndOfStatement. |
4932 | 39 | return false; |
4933 | 91 | } |
4934 | | |
4935 | | bool MipsAsmParser::parseSetAtDirective() |
4936 | 891 | { |
4937 | | // Line can be: ".set at", which sets $at to $1 |
4938 | | // or ".set at=$reg", which sets $at to $reg. |
4939 | 891 | MCAsmParser &Parser = getParser(); |
4940 | 891 | Parser.Lex(); // Eat "at". |
4941 | | |
4942 | 891 | if (getLexer().is(AsmToken::EndOfStatement)) { |
4943 | | // No register was specified, so we set $at to $1. |
4944 | 58 | AssemblerOptions.back()->setATRegIndex(1); |
4945 | | |
4946 | | //getTargetStreamer().emitDirectiveSetAt(); |
4947 | 58 | Parser.Lex(); // Consume the EndOfStatement. |
4948 | 58 | return false; |
4949 | 58 | } |
4950 | | |
4951 | 833 | if (getLexer().isNot(AsmToken::Equal)) { |
4952 | 109 | reportParseError("unexpected token, expected equals sign"); |
4953 | 109 | return false; |
4954 | 109 | } |
4955 | 724 | Parser.Lex(); // Eat "=". |
4956 | | |
4957 | 724 | if (getLexer().isNot(AsmToken::Dollar)) { |
4958 | 418 | if (getLexer().is(AsmToken::EndOfStatement)) { |
4959 | 137 | reportParseError("no register specified"); |
4960 | 137 | return false; |
4961 | 281 | } else { |
4962 | 281 | reportParseError("unexpected token, expected dollar sign '$'"); |
4963 | 281 | return false; |
4964 | 281 | } |
4965 | 418 | } |
4966 | 306 | Parser.Lex(); // Eat "$". |
4967 | | |
4968 | | // Find out what "reg" is. |
4969 | 306 | unsigned AtRegNo; |
4970 | 306 | const AsmToken &Reg = Parser.getTok(); |
4971 | 306 | if (Reg.is(AsmToken::Identifier)) { |
4972 | 49 | AtRegNo = matchCPURegisterName(Reg.getIdentifier()); |
4973 | 257 | } else if (Reg.is(AsmToken::Integer)) { |
4974 | 215 | bool valid; |
4975 | 215 | AtRegNo = Reg.getIntVal(valid); |
4976 | 215 | if (!valid) |
4977 | 0 | return true; |
4978 | 215 | } else { |
4979 | 42 | reportParseError("unexpected token, expected identifier or integer"); |
4980 | 42 | return false; |
4981 | 42 | } |
4982 | | |
4983 | | // Check if $reg is a valid register. If it is, set $at to $reg. |
4984 | 264 | if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) { |
4985 | 132 | reportParseError("invalid register"); |
4986 | 132 | return false; |
4987 | 132 | } |
4988 | 132 | Parser.Lex(); // Eat "reg". |
4989 | | |
4990 | | // If this is not the end of the statement, report an error. |
4991 | 132 | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
4992 | 101 | reportParseError("unexpected token, expected end of statement"); |
4993 | 101 | return false; |
4994 | 101 | } |
4995 | | |
4996 | | //getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo); |
4997 | | |
4998 | 31 | Parser.Lex(); // Consume the EndOfStatement. |
4999 | 31 | return false; |
5000 | 132 | } |
5001 | | |
5002 | 75 | bool MipsAsmParser::parseSetReorderDirective() { |
5003 | 75 | MCAsmParser &Parser = getParser(); |
5004 | 75 | Parser.Lex(); |
5005 | | // If this is not the end of the statement, report an error. |
5006 | 75 | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
5007 | 6 | reportParseError("unexpected token, expected end of statement"); |
5008 | 6 | return false; |
5009 | 6 | } |
5010 | 69 | AssemblerOptions.back()->setReorder(); |
5011 | | //getTargetStreamer().emitDirectiveSetReorder(); |
5012 | 69 | Parser.Lex(); // Consume the EndOfStatement. |
5013 | 69 | return false; |
5014 | 75 | } |
5015 | | |
5016 | 147 | bool MipsAsmParser::parseSetNoReorderDirective() { |
5017 | 147 | MCAsmParser &Parser = getParser(); |
5018 | 147 | Parser.Lex(); |
5019 | | // If this is not the end of the statement, report an error. |
5020 | 147 | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
5021 | 41 | reportParseError("unexpected token, expected end of statement"); |
5022 | 41 | return false; |
5023 | 41 | } |
5024 | 106 | AssemblerOptions.back()->setNoReorder(); |
5025 | | //getTargetStreamer().emitDirectiveSetNoReorder(); |
5026 | 106 | Parser.Lex(); // Consume the EndOfStatement. |
5027 | 106 | return false; |
5028 | 147 | } |
5029 | | |
5030 | 101 | bool MipsAsmParser::parseSetMacroDirective() { |
5031 | 101 | MCAsmParser &Parser = getParser(); |
5032 | 101 | Parser.Lex(); |
5033 | | // If this is not the end of the statement, report an error. |
5034 | 101 | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
5035 | 70 | reportParseError("unexpected token, expected end of statement"); |
5036 | 70 | return false; |
5037 | 70 | } |
5038 | 31 | AssemblerOptions.back()->setMacro(); |
5039 | | //getTargetStreamer().emitDirectiveSetMacro(); |
5040 | 31 | Parser.Lex(); // Consume the EndOfStatement. |
5041 | 31 | return false; |
5042 | 101 | } |
5043 | | |
5044 | 18 | bool MipsAsmParser::parseSetNoMacroDirective() { |
5045 | 18 | MCAsmParser &Parser = getParser(); |
5046 | 18 | Parser.Lex(); |
5047 | | // If this is not the end of the statement, report an error. |
5048 | 18 | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
5049 | 10 | reportParseError("unexpected token, expected end of statement"); |
5050 | 10 | return false; |
5051 | 10 | } |
5052 | 8 | if (AssemblerOptions.back()->isReorder()) { |
5053 | 8 | reportParseError("`noreorder' must be set before `nomacro'"); |
5054 | 8 | return false; |
5055 | 8 | } |
5056 | 0 | AssemblerOptions.back()->setNoMacro(); |
5057 | | //getTargetStreamer().emitDirectiveSetNoMacro(); |
5058 | 0 | Parser.Lex(); // Consume the EndOfStatement. |
5059 | 0 | return false; |
5060 | 8 | } |
5061 | | |
5062 | 4.01k | bool MipsAsmParser::parseSetMsaDirective() { |
5063 | 4.01k | MCAsmParser &Parser = getParser(); |
5064 | 4.01k | Parser.Lex(); |
5065 | | |
5066 | | // If this is not the end of the statement, report an error. |
5067 | 4.01k | if (getLexer().isNot(AsmToken::EndOfStatement)) |
5068 | 97 | return reportParseError("unexpected token, expected end of statement"); |
5069 | | |
5070 | 3.91k | setFeatureBits(Mips::FeatureMSA, "msa"); |
5071 | | //getTargetStreamer().emitDirectiveSetMsa(); |
5072 | 3.91k | return false; |
5073 | 4.01k | } |
5074 | | |
5075 | 7.58k | bool MipsAsmParser::parseSetNoMsaDirective() { |
5076 | 7.58k | MCAsmParser &Parser = getParser(); |
5077 | 7.58k | Parser.Lex(); |
5078 | | |
5079 | | // If this is not the end of the statement, report an error. |
5080 | 7.58k | if (getLexer().isNot(AsmToken::EndOfStatement)) |
5081 | 1.36k | return reportParseError("unexpected token, expected end of statement"); |
5082 | | |
5083 | 6.22k | clearFeatureBits(Mips::FeatureMSA, "msa"); |
5084 | | //getTargetStreamer().emitDirectiveSetNoMsa(); |
5085 | 6.22k | return false; |
5086 | 7.58k | } |
5087 | | |
5088 | 26 | bool MipsAsmParser::parseSetNoDspDirective() { |
5089 | 26 | MCAsmParser &Parser = getParser(); |
5090 | 26 | Parser.Lex(); // Eat "nodsp". |
5091 | | |
5092 | | // If this is not the end of the statement, report an error. |
5093 | 26 | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
5094 | 10 | reportParseError("unexpected token, expected end of statement"); |
5095 | 10 | return false; |
5096 | 10 | } |
5097 | | |
5098 | 16 | clearFeatureBits(Mips::FeatureDSP, "dsp"); |
5099 | | //getTargetStreamer().emitDirectiveSetNoDsp(); |
5100 | 16 | return false; |
5101 | 26 | } |
5102 | | |
5103 | 239 | bool MipsAsmParser::parseSetMips16Directive() { |
5104 | 239 | MCAsmParser &Parser = getParser(); |
5105 | 239 | Parser.Lex(); // Eat "mips16". |
5106 | | |
5107 | | // If this is not the end of the statement, report an error. |
5108 | 239 | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
5109 | 191 | reportParseError("unexpected token, expected end of statement"); |
5110 | 191 | return false; |
5111 | 191 | } |
5112 | | |
5113 | 48 | setFeatureBits(Mips::FeatureMips16, "mips16"); |
5114 | | //getTargetStreamer().emitDirectiveSetMips16(); |
5115 | 48 | Parser.Lex(); // Consume the EndOfStatement. |
5116 | 48 | return false; |
5117 | 239 | } |
5118 | | |
5119 | 28 | bool MipsAsmParser::parseSetNoMips16Directive() { |
5120 | 28 | MCAsmParser &Parser = getParser(); |
5121 | 28 | Parser.Lex(); // Eat "nomips16". |
5122 | | |
5123 | | // If this is not the end of the statement, report an error. |
5124 | 28 | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
5125 | 19 | reportParseError("unexpected token, expected end of statement"); |
5126 | 19 | return false; |
5127 | 19 | } |
5128 | | |
5129 | 9 | clearFeatureBits(Mips::FeatureMips16, "mips16"); |
5130 | | //getTargetStreamer().emitDirectiveSetNoMips16(); |
5131 | 9 | Parser.Lex(); // Consume the EndOfStatement. |
5132 | 9 | return false; |
5133 | 28 | } |
5134 | | |
5135 | 813 | bool MipsAsmParser::parseSetFpDirective() { |
5136 | 813 | MCAsmParser &Parser = getParser(); |
5137 | 813 | MipsABIFlagsSection::FpABIKind FpAbiVal; |
5138 | | // Line can be: .set fp=32 |
5139 | | // .set fp=xx |
5140 | | // .set fp=64 |
5141 | 813 | Parser.Lex(); // Eat fp token |
5142 | 813 | AsmToken Tok = Parser.getTok(); |
5143 | 813 | if (Tok.isNot(AsmToken::Equal)) { |
5144 | 32 | reportParseError("unexpected token, expected equals sign '='"); |
5145 | 32 | return false; |
5146 | 32 | } |
5147 | 781 | Parser.Lex(); // Eat '=' token. |
5148 | 781 | Tok = Parser.getTok(); |
5149 | | |
5150 | 781 | if (!parseFpABIValue(FpAbiVal, ".set")) |
5151 | 622 | return false; |
5152 | | |
5153 | 159 | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
5154 | 31 | reportParseError("unexpected token, expected end of statement"); |
5155 | 31 | return false; |
5156 | 31 | } |
5157 | | //getTargetStreamer().emitDirectiveSetFp(FpAbiVal); |
5158 | 128 | Parser.Lex(); // Consume the EndOfStatement. |
5159 | 128 | return false; |
5160 | 159 | } |
5161 | | |
5162 | 377 | bool MipsAsmParser::parseSetOddSPRegDirective() { |
5163 | 377 | MCAsmParser &Parser = getParser(); |
5164 | | |
5165 | 377 | Parser.Lex(); // Eat "oddspreg". |
5166 | 377 | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
5167 | 34 | reportParseError("unexpected token, expected end of statement"); |
5168 | 34 | return false; |
5169 | 34 | } |
5170 | | |
5171 | 343 | clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg"); |
5172 | | //getTargetStreamer().emitDirectiveSetOddSPReg(); |
5173 | 343 | return false; |
5174 | 377 | } |
5175 | | |
5176 | 0 | bool MipsAsmParser::parseSetNoOddSPRegDirective() { |
5177 | 0 | MCAsmParser &Parser = getParser(); |
5178 | |
|
5179 | 0 | Parser.Lex(); // Eat "nooddspreg". |
5180 | 0 | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
5181 | 0 | reportParseError("unexpected token, expected end of statement"); |
5182 | 0 | return false; |
5183 | 0 | } |
5184 | | |
5185 | 0 | setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg"); |
5186 | | //getTargetStreamer().emitDirectiveSetNoOddSPReg(); |
5187 | 0 | return false; |
5188 | 0 | } |
5189 | | |
5190 | 40 | bool MipsAsmParser::parseSetPopDirective() { |
5191 | 40 | MCAsmParser &Parser = getParser(); |
5192 | 40 | SMLoc Loc = getLexer().getLoc(); |
5193 | | |
5194 | 40 | Parser.Lex(); |
5195 | 40 | if (getLexer().isNot(AsmToken::EndOfStatement)) |
5196 | 39 | return reportParseError("unexpected token, expected end of statement"); |
5197 | | |
5198 | | // Always keep an element on the options "stack" to prevent the user |
5199 | | // from changing the initial options. This is how we remember them. |
5200 | 1 | if (AssemblerOptions.size() == 2) |
5201 | 1 | return reportParseError(Loc, ".set pop with no .set push"); |
5202 | | |
5203 | 0 | MCSubtargetInfo &STI = copySTI(); |
5204 | 0 | AssemblerOptions.pop_back(); |
5205 | 0 | setAvailableFeatures( |
5206 | 0 | ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures())); |
5207 | 0 | STI.setFeatureBits(AssemblerOptions.back()->getFeatures()); |
5208 | | |
5209 | | //getTargetStreamer().emitDirectiveSetPop(); |
5210 | 0 | return false; |
5211 | 1 | } |
5212 | | |
5213 | 88 | bool MipsAsmParser::parseSetPushDirective() { |
5214 | 88 | MCAsmParser &Parser = getParser(); |
5215 | 88 | Parser.Lex(); |
5216 | 88 | if (getLexer().isNot(AsmToken::EndOfStatement)) |
5217 | 77 | return reportParseError("unexpected token, expected end of statement"); |
5218 | | |
5219 | | // Create a copy of the current assembler options environment and push it. |
5220 | 11 | AssemblerOptions.push_back( |
5221 | 11 | make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get())); |
5222 | | |
5223 | | //getTargetStreamer().emitDirectiveSetPush(); |
5224 | 11 | return false; |
5225 | 88 | } |
5226 | | |
5227 | 16 | bool MipsAsmParser::parseSetSoftFloatDirective() { |
5228 | 16 | MCAsmParser &Parser = getParser(); |
5229 | 16 | Parser.Lex(); |
5230 | 16 | if (getLexer().isNot(AsmToken::EndOfStatement)) |
5231 | 2 | return reportParseError("unexpected token, expected end of statement"); |
5232 | | |
5233 | 14 | setFeatureBits(Mips::FeatureSoftFloat, "soft-float"); |
5234 | | //getTargetStreamer().emitDirectiveSetSoftFloat(); |
5235 | 14 | return false; |
5236 | 16 | } |
5237 | | |
5238 | 225 | bool MipsAsmParser::parseSetHardFloatDirective() { |
5239 | 225 | MCAsmParser &Parser = getParser(); |
5240 | 225 | Parser.Lex(); |
5241 | 225 | if (getLexer().isNot(AsmToken::EndOfStatement)) |
5242 | 8 | return reportParseError("unexpected token, expected end of statement"); |
5243 | | |
5244 | 217 | clearFeatureBits(Mips::FeatureSoftFloat, "soft-float"); |
5245 | | //getTargetStreamer().emitDirectiveSetHardFloat(); |
5246 | 217 | return false; |
5247 | 225 | } |
5248 | | |
5249 | 14.9k | bool MipsAsmParser::parseSetAssignment() { |
5250 | 14.9k | StringRef Name; |
5251 | 14.9k | const MCExpr *Value; |
5252 | 14.9k | MCAsmParser &Parser = getParser(); |
5253 | | |
5254 | 14.9k | if (Parser.parseIdentifier(Name)) |
5255 | 2.72k | reportParseError("expected identifier after .set"); |
5256 | | |
5257 | 14.9k | if (getLexer().isNot(AsmToken::Comma)) |
5258 | 14.0k | return reportParseError("unexpected token, expected comma"); |
5259 | 837 | Lex(); // Eat comma |
5260 | | |
5261 | 837 | if (Parser.parseExpression(Value)) |
5262 | 477 | return reportParseError("expected valid expression after comma"); |
5263 | | |
5264 | 360 | MCSymbol *Sym = getContext().getOrCreateSymbol(Name); |
5265 | 360 | bool valid; |
5266 | 360 | Sym->setVariableValue(Value, valid); |
5267 | 360 | if (!valid) |
5268 | 0 | return true; |
5269 | | |
5270 | 360 | return false; |
5271 | 360 | } |
5272 | | |
5273 | 453 | bool MipsAsmParser::parseSetMips0Directive() { |
5274 | 453 | MCAsmParser &Parser = getParser(); |
5275 | 453 | Parser.Lex(); |
5276 | 453 | if (getLexer().isNot(AsmToken::EndOfStatement)) |
5277 | 106 | return reportParseError("unexpected token, expected end of statement"); |
5278 | | |
5279 | | // Reset assembler options to their initial values. |
5280 | 347 | MCSubtargetInfo &STI = copySTI(); |
5281 | 347 | setAvailableFeatures( |
5282 | 347 | ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures())); |
5283 | 347 | STI.setFeatureBits(AssemblerOptions.front()->getFeatures()); |
5284 | 347 | AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures()); |
5285 | | |
5286 | | //getTargetStreamer().emitDirectiveSetMips0(); |
5287 | 347 | return false; |
5288 | 453 | } |
5289 | | |
5290 | 138 | bool MipsAsmParser::parseSetArchDirective() { |
5291 | 138 | MCAsmParser &Parser = getParser(); |
5292 | 138 | Parser.Lex(); |
5293 | 138 | if (getLexer().isNot(AsmToken::Equal)) |
5294 | 5 | return reportParseError("unexpected token, expected equals sign"); |
5295 | | |
5296 | 133 | Parser.Lex(); |
5297 | 133 | StringRef Arch; |
5298 | 133 | if (Parser.parseIdentifier(Arch)) |
5299 | 1 | return reportParseError("expected arch identifier"); |
5300 | | |
5301 | 132 | StringRef ArchFeatureName = |
5302 | 132 | StringSwitch<StringRef>(Arch) |
5303 | 132 | .Case("mips1", "mips1") |
5304 | 132 | .Case("mips2", "mips2") |
5305 | 132 | .Case("mips3", "mips3") |
5306 | 132 | .Case("mips4", "mips4") |
5307 | 132 | .Case("mips5", "mips5") |
5308 | 132 | .Case("mips32", "mips32") |
5309 | 132 | .Case("mips32r2", "mips32r2") |
5310 | 132 | .Case("mips32r3", "mips32r3") |
5311 | 132 | .Case("mips32r5", "mips32r5") |
5312 | 132 | .Case("mips32r6", "mips32r6") |
5313 | 132 | .Case("mips64", "mips64") |
5314 | 132 | .Case("mips64r2", "mips64r2") |
5315 | 132 | .Case("mips64r3", "mips64r3") |
5316 | 132 | .Case("mips64r5", "mips64r5") |
5317 | 132 | .Case("mips64r6", "mips64r6") |
5318 | 132 | .Case("cnmips", "cnmips") |
5319 | 132 | .Case("r4000", "mips3") // This is an implementation of Mips3. |
5320 | 132 | .Default(""); |
5321 | | |
5322 | 132 | if (ArchFeatureName.empty()) |
5323 | 80 | return reportParseError("unsupported architecture"); |
5324 | | |
5325 | 52 | selectArch(ArchFeatureName); |
5326 | | //getTargetStreamer().emitDirectiveSetArch(Arch); |
5327 | 52 | return false; |
5328 | 132 | } |
5329 | | |
5330 | 5.80k | bool MipsAsmParser::parseSetFeature(uint64_t Feature) { |
5331 | 5.80k | MCAsmParser &Parser = getParser(); |
5332 | 5.80k | Parser.Lex(); |
5333 | 5.80k | if (getLexer().isNot(AsmToken::EndOfStatement)) |
5334 | 3.07k | return reportParseError("unexpected token, expected end of statement"); |
5335 | | |
5336 | 2.72k | switch (Feature) { |
5337 | 0 | default: |
5338 | 0 | llvm_unreachable("Unimplemented feature"); |
5339 | 15 | case Mips::FeatureDSP: |
5340 | 15 | setFeatureBits(Mips::FeatureDSP, "dsp"); |
5341 | | //getTargetStreamer().emitDirectiveSetDsp(); |
5342 | 15 | break; |
5343 | 0 | case Mips::FeatureMicroMips: |
5344 | | //getTargetStreamer().emitDirectiveSetMicroMips(); |
5345 | 0 | break; |
5346 | 384 | case Mips::FeatureMips1: |
5347 | 384 | selectArch("mips1"); |
5348 | | //getTargetStreamer().emitDirectiveSetMips1(); |
5349 | 384 | break; |
5350 | 98 | case Mips::FeatureMips2: |
5351 | 98 | selectArch("mips2"); |
5352 | | //getTargetStreamer().emitDirectiveSetMips2(); |
5353 | 98 | break; |
5354 | 43 | case Mips::FeatureMips3: |
5355 | 43 | selectArch("mips3"); |
5356 | | //getTargetStreamer().emitDirectiveSetMips3(); |
5357 | 43 | break; |
5358 | 177 | case Mips::FeatureMips4: |
5359 | 177 | selectArch("mips4"); |
5360 | | //getTargetStreamer().emitDirectiveSetMips4(); |
5361 | 177 | break; |
5362 | 87 | case Mips::FeatureMips5: |
5363 | 87 | selectArch("mips5"); |
5364 | | //getTargetStreamer().emitDirectiveSetMips5(); |
5365 | 87 | break; |
5366 | 695 | case Mips::FeatureMips32: |
5367 | 695 | selectArch("mips32"); |
5368 | | //getTargetStreamer().emitDirectiveSetMips32(); |
5369 | 695 | break; |
5370 | 9 | case Mips::FeatureMips32r2: |
5371 | 9 | selectArch("mips32r2"); |
5372 | | //getTargetStreamer().emitDirectiveSetMips32R2(); |
5373 | 9 | break; |
5374 | 5 | case Mips::FeatureMips32r3: |
5375 | 5 | selectArch("mips32r3"); |
5376 | | //getTargetStreamer().emitDirectiveSetMips32R3(); |
5377 | 5 | break; |
5378 | 3 | case Mips::FeatureMips32r5: |
5379 | 3 | selectArch("mips32r5"); |
5380 | | //getTargetStreamer().emitDirectiveSetMips32R5(); |
5381 | 3 | break; |
5382 | 21 | case Mips::FeatureMips32r6: |
5383 | 21 | selectArch("mips32r6"); |
5384 | | //getTargetStreamer().emitDirectiveSetMips32R6(); |
5385 | 21 | break; |
5386 | 841 | case Mips::FeatureMips64: |
5387 | 841 | selectArch("mips64"); |
5388 | | //getTargetStreamer().emitDirectiveSetMips64(); |
5389 | 841 | break; |
5390 | 143 | case Mips::FeatureMips64r2: |
5391 | 143 | selectArch("mips64r2"); |
5392 | | //getTargetStreamer().emitDirectiveSetMips64R2(); |
5393 | 143 | break; |
5394 | 35 | case Mips::FeatureMips64r3: |
5395 | 35 | selectArch("mips64r3"); |
5396 | | //getTargetStreamer().emitDirectiveSetMips64R3(); |
5397 | 35 | break; |
5398 | 53 | case Mips::FeatureMips64r5: |
5399 | 53 | selectArch("mips64r5"); |
5400 | | //getTargetStreamer().emitDirectiveSetMips64R5(); |
5401 | 53 | break; |
5402 | 119 | case Mips::FeatureMips64r6: |
5403 | 119 | selectArch("mips64r6"); |
5404 | | //getTargetStreamer().emitDirectiveSetMips64R6(); |
5405 | 119 | break; |
5406 | 2.72k | } |
5407 | 2.72k | return false; |
5408 | 2.72k | } |
5409 | | |
5410 | 3.70k | bool MipsAsmParser::eatComma(StringRef ErrorStr) { |
5411 | 3.70k | MCAsmParser &Parser = getParser(); |
5412 | 3.70k | if (getLexer().isNot(AsmToken::Comma)) { |
5413 | 1.30k | SMLoc Loc = getLexer().getLoc(); |
5414 | 1.30k | Parser.eatToEndOfStatement(); |
5415 | 1.30k | return Error(Loc, ErrorStr); |
5416 | 1.30k | } |
5417 | | |
5418 | 2.40k | Parser.Lex(); // Eat the comma. |
5419 | 2.40k | return true; |
5420 | 3.70k | } |
5421 | | |
5422 | | // Used to determine if .cpload, .cprestore, and .cpsetup have any effect. |
5423 | | // In this class, it is only used for .cprestore. |
5424 | | // FIXME: Only keep track of IsPicEnabled in one place, instead of in both |
5425 | | // MipsTargetELFStreamer and MipsAsmParser. |
5426 | 21 | bool MipsAsmParser::isPicAndNotNxxAbi() { |
5427 | 21 | return inPicMode() && !(isABI_N32() || isABI_N64()); |
5428 | 21 | } |
5429 | | |
5430 | 230 | bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) { |
5431 | 230 | if (AssemblerOptions.back()->isReorder()) { |
5432 | | // Warning(Loc, ".cpload should be inside a noreorder section"); |
5433 | 230 | } |
5434 | | |
5435 | 230 | if (inMips16Mode()) { |
5436 | 10 | reportParseError(".cpload is not supported in Mips16 mode"); |
5437 | 10 | return false; |
5438 | 10 | } |
5439 | | |
5440 | 220 | SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg; |
5441 | 220 | OperandMatchResultTy ResTy = parseAnyRegister(Reg); |
5442 | 220 | if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) { |
5443 | 86 | reportParseError("expected register containing function address"); |
5444 | 86 | return false; |
5445 | 86 | } |
5446 | | |
5447 | 134 | MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]); |
5448 | 134 | if (!RegOpnd.isGPRAsmReg()) { |
5449 | 30 | reportParseError(RegOpnd.getStartLoc(), "invalid register"); |
5450 | 30 | return false; |
5451 | 30 | } |
5452 | | |
5453 | | // If this is not the end of the statement, report an error. |
5454 | 104 | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
5455 | 25 | reportParseError("unexpected token, expected end of statement"); |
5456 | 25 | return false; |
5457 | 25 | } |
5458 | | |
5459 | | //getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg()); |
5460 | 79 | return false; |
5461 | 104 | } |
5462 | | |
5463 | 386 | bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) { |
5464 | 386 | MCAsmParser &Parser = getParser(); |
5465 | | |
5466 | | // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it |
5467 | | // is used in non-PIC mode. |
5468 | | |
5469 | 386 | if (inMips16Mode()) { |
5470 | 45 | reportParseError(".cprestore is not supported in Mips16 mode"); |
5471 | 45 | return false; |
5472 | 45 | } |
5473 | | |
5474 | | // Get the stack offset value. |
5475 | 341 | const MCExpr *StackOffset; |
5476 | 341 | int64_t StackOffsetVal; |
5477 | 341 | if (Parser.parseExpression(StackOffset)) { |
5478 | 28 | reportParseError("expected stack offset value"); |
5479 | 28 | return false; |
5480 | 28 | } |
5481 | | |
5482 | 313 | if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) { |
5483 | 56 | reportParseError("stack offset is not an absolute expression"); |
5484 | 56 | return false; |
5485 | 56 | } |
5486 | | |
5487 | 257 | if (StackOffsetVal < 0) { |
5488 | | // Warning(Loc, ".cprestore with negative stack offset has no effect"); |
5489 | 57 | IsCpRestoreSet = false; |
5490 | 200 | } else { |
5491 | 200 | IsCpRestoreSet = true; |
5492 | 200 | CpRestoreOffset = StackOffsetVal; |
5493 | 200 | } |
5494 | | |
5495 | | // If this is not the end of the statement, report an error. |
5496 | 257 | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
5497 | 237 | reportParseError("unexpected token, expected end of statement"); |
5498 | 237 | return false; |
5499 | 237 | } |
5500 | | |
5501 | | // Store the $gp on the stack. |
5502 | 20 | SmallVector<MCInst, 3> StoreInsts; |
5503 | 20 | createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc, |
5504 | 20 | StoreInsts); |
5505 | | |
5506 | | //getTargetStreamer().emitDirectiveCpRestore(StoreInsts, CpRestoreOffset); |
5507 | 20 | Parser.Lex(); // Consume the EndOfStatement. |
5508 | 20 | return false; |
5509 | 257 | } |
5510 | | |
5511 | 3.10k | bool MipsAsmParser::parseDirectiveCPSetup() { |
5512 | 3.10k | MCAsmParser &Parser = getParser(); |
5513 | | //unsigned FuncReg; |
5514 | 3.10k | unsigned Save; |
5515 | 3.10k | bool SaveIsReg = true; |
5516 | | |
5517 | 3.10k | SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg; |
5518 | 3.10k | OperandMatchResultTy ResTy = parseAnyRegister(TmpReg); |
5519 | 3.10k | if (ResTy == MatchOperand_NoMatch) { |
5520 | 112 | reportParseError("expected register containing function address"); |
5521 | 112 | Parser.eatToEndOfStatement(); |
5522 | 112 | return false; |
5523 | 112 | } |
5524 | | |
5525 | 2.99k | MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]); |
5526 | 2.99k | if (!FuncRegOpnd.isGPRAsmReg()) { |
5527 | 440 | reportParseError(FuncRegOpnd.getStartLoc(), "invalid register"); |
5528 | 440 | Parser.eatToEndOfStatement(); |
5529 | 440 | return false; |
5530 | 440 | } |
5531 | | |
5532 | | //FuncReg = FuncRegOpnd.getGPR32Reg(); |
5533 | 2.55k | TmpReg.clear(); |
5534 | | |
5535 | 2.55k | if (!eatComma("unexpected token, expected comma")) |
5536 | 0 | return true; |
5537 | | |
5538 | 2.55k | ResTy = parseAnyRegister(TmpReg); |
5539 | 2.55k | if (ResTy == MatchOperand_NoMatch) { |
5540 | 2.31k | const MCExpr *OffsetExpr; |
5541 | 2.31k | int64_t OffsetVal; |
5542 | 2.31k | SMLoc ExprLoc = getLexer().getLoc(); |
5543 | | |
5544 | 2.31k | if (Parser.parseExpression(OffsetExpr) || |
5545 | 2.09k | !OffsetExpr->evaluateAsAbsolute(OffsetVal)) { |
5546 | 1.32k | reportParseError(ExprLoc, "expected save register or stack offset"); |
5547 | 1.32k | Parser.eatToEndOfStatement(); |
5548 | 1.32k | return false; |
5549 | 1.32k | } |
5550 | | |
5551 | 989 | Save = OffsetVal; |
5552 | 989 | SaveIsReg = false; |
5553 | 989 | } else { |
5554 | 242 | MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]); |
5555 | 242 | if (!SaveOpnd.isGPRAsmReg()) { |
5556 | 83 | reportParseError(SaveOpnd.getStartLoc(), "invalid register"); |
5557 | 83 | Parser.eatToEndOfStatement(); |
5558 | 83 | return false; |
5559 | 83 | } |
5560 | 159 | Save = SaveOpnd.getGPR32Reg(); |
5561 | 159 | } |
5562 | | |
5563 | 1.14k | if (!eatComma("unexpected token, expected comma")) |
5564 | 0 | return true; |
5565 | | |
5566 | 1.14k | const MCExpr *Expr; |
5567 | 1.14k | if (Parser.parseExpression(Expr)) { |
5568 | 805 | reportParseError("expected expression"); |
5569 | 805 | return false; |
5570 | 805 | } |
5571 | | |
5572 | 343 | if (Expr->getKind() != MCExpr::SymbolRef) { |
5573 | 269 | reportParseError("expected symbol"); |
5574 | 269 | return false; |
5575 | 269 | } |
5576 | | //const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr); |
5577 | | |
5578 | 74 | CpSaveLocation = Save; |
5579 | 74 | CpSaveLocationIsRegister = SaveIsReg; |
5580 | | |
5581 | | //getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(), |
5582 | | // SaveIsReg); |
5583 | 74 | return false; |
5584 | 343 | } |
5585 | | |
5586 | 4 | bool MipsAsmParser::parseDirectiveCPReturn() { |
5587 | | //getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation, |
5588 | | // CpSaveLocationIsRegister); |
5589 | 4 | return false; |
5590 | 4 | } |
5591 | | |
5592 | 1.14k | bool MipsAsmParser::parseDirectiveNaN() { |
5593 | 1.14k | MCAsmParser &Parser = getParser(); |
5594 | 1.14k | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
5595 | 615 | const AsmToken &Tok = Parser.getTok(); |
5596 | | |
5597 | 615 | if (Tok.getString() == "2008") { |
5598 | 0 | Parser.Lex(); |
5599 | | //getTargetStreamer().emitDirectiveNaN2008(); |
5600 | 0 | return false; |
5601 | 615 | } else if (Tok.getString() == "legacy") { |
5602 | 0 | Parser.Lex(); |
5603 | | //getTargetStreamer().emitDirectiveNaNLegacy(); |
5604 | 0 | return false; |
5605 | 0 | } |
5606 | 615 | } |
5607 | | // If we don't recognize the option passed to the .nan |
5608 | | // directive (e.g. no option or unknown option), emit an error. |
5609 | 1.14k | reportParseError("invalid option in .nan directive"); |
5610 | 1.14k | return false; |
5611 | 1.14k | } |
5612 | | |
5613 | 36.0k | bool MipsAsmParser::parseDirectiveSet() { |
5614 | 36.0k | MCAsmParser &Parser = getParser(); |
5615 | | // Get the next token. |
5616 | 36.0k | const AsmToken &Tok = Parser.getTok(); |
5617 | | |
5618 | 36.0k | if (Tok.getString() == "noat") { |
5619 | 91 | return parseSetNoAtDirective(); |
5620 | 35.9k | } else if (Tok.getString() == "at") { |
5621 | 891 | return parseSetAtDirective(); |
5622 | 35.1k | } else if (Tok.getString() == "arch") { |
5623 | 138 | return parseSetArchDirective(); |
5624 | 34.9k | } else if (Tok.getString() == "fp") { |
5625 | 813 | return parseSetFpDirective(); |
5626 | 34.1k | } else if (Tok.getString() == "oddspreg") { |
5627 | 377 | return parseSetOddSPRegDirective(); |
5628 | 33.7k | } else if (Tok.getString() == "nooddspreg") { |
5629 | 0 | return parseSetNoOddSPRegDirective(); |
5630 | 33.7k | } else if (Tok.getString() == "pop") { |
5631 | 40 | return parseSetPopDirective(); |
5632 | 33.7k | } else if (Tok.getString() == "push") { |
5633 | 88 | return parseSetPushDirective(); |
5634 | 33.6k | } else if (Tok.getString() == "reorder") { |
5635 | 75 | return parseSetReorderDirective(); |
5636 | 33.5k | } else if (Tok.getString() == "noreorder") { |
5637 | 147 | return parseSetNoReorderDirective(); |
5638 | 33.4k | } else if (Tok.getString() == "macro") { |
5639 | 101 | return parseSetMacroDirective(); |
5640 | 33.3k | } else if (Tok.getString() == "nomacro") { |
5641 | 18 | return parseSetNoMacroDirective(); |
5642 | 33.3k | } else if (Tok.getString() == "mips16") { |
5643 | 239 | return parseSetMips16Directive(); |
5644 | 33.0k | } else if (Tok.getString() == "nomips16") { |
5645 | 28 | return parseSetNoMips16Directive(); |
5646 | 33.0k | } else if (Tok.getString() == "nomicromips") { |
5647 | | //getTargetStreamer().emitDirectiveSetNoMicroMips(); |
5648 | 0 | Parser.eatToEndOfStatement(); |
5649 | 0 | return false; |
5650 | 33.0k | } else if (Tok.getString() == "micromips") { |
5651 | 0 | return parseSetFeature(Mips::FeatureMicroMips); |
5652 | 33.0k | } else if (Tok.getString() == "mips0") { |
5653 | 453 | return parseSetMips0Directive(); |
5654 | 32.5k | } else if (Tok.getString() == "mips1") { |
5655 | 385 | return parseSetFeature(Mips::FeatureMips1); |
5656 | 32.1k | } else if (Tok.getString() == "mips2") { |
5657 | 124 | return parseSetFeature(Mips::FeatureMips2); |
5658 | 32.0k | } else if (Tok.getString() == "mips3") { |
5659 | 94 | return parseSetFeature(Mips::FeatureMips3); |
5660 | 31.9k | } else if (Tok.getString() == "mips4") { |
5661 | 2.98k | return parseSetFeature(Mips::FeatureMips4); |
5662 | 28.9k | } else if (Tok.getString() == "mips5") { |
5663 | 87 | return parseSetFeature(Mips::FeatureMips5); |
5664 | 28.9k | } else if (Tok.getString() == "mips32") { |
5665 | 752 | return parseSetFeature(Mips::FeatureMips32); |
5666 | 28.1k | } else if (Tok.getString() == "mips32r2") { |
5667 | 9 | return parseSetFeature(Mips::FeatureMips32r2); |
5668 | 28.1k | } else if (Tok.getString() == "mips32r3") { |
5669 | 5 | return parseSetFeature(Mips::FeatureMips32r3); |
5670 | 28.1k | } else if (Tok.getString() == "mips32r5") { |
5671 | 3 | return parseSetFeature(Mips::FeatureMips32r5); |
5672 | 28.1k | } else if (Tok.getString() == "mips32r6") { |
5673 | 21 | return parseSetFeature(Mips::FeatureMips32r6); |
5674 | 28.1k | } else if (Tok.getString() == "mips64") { |
5675 | 979 | return parseSetFeature(Mips::FeatureMips64); |
5676 | 27.1k | } else if (Tok.getString() == "mips64r2") { |
5677 | 143 | return parseSetFeature(Mips::FeatureMips64r2); |
5678 | 27.0k | } else if (Tok.getString() == "mips64r3") { |
5679 | 35 | return parseSetFeature(Mips::FeatureMips64r3); |
5680 | 26.9k | } else if (Tok.getString() == "mips64r5") { |
5681 | 53 | return parseSetFeature(Mips::FeatureMips64r5); |
5682 | 26.9k | } else if (Tok.getString() == "mips64r6") { |
5683 | 119 | return parseSetFeature(Mips::FeatureMips64r6); |
5684 | 26.7k | } else if (Tok.getString() == "dsp") { |
5685 | 15 | return parseSetFeature(Mips::FeatureDSP); |
5686 | 26.7k | } else if (Tok.getString() == "nodsp") { |
5687 | 26 | return parseSetNoDspDirective(); |
5688 | 26.7k | } else if (Tok.getString() == "msa") { |
5689 | 4.01k | return parseSetMsaDirective(); |
5690 | 22.7k | } else if (Tok.getString() == "nomsa") { |
5691 | 7.58k | return parseSetNoMsaDirective(); |
5692 | 15.1k | } else if (Tok.getString() == "softfloat") { |
5693 | 16 | return parseSetSoftFloatDirective(); |
5694 | 15.1k | } else if (Tok.getString() == "hardfloat") { |
5695 | 225 | return parseSetHardFloatDirective(); |
5696 | 14.9k | } else { |
5697 | | // It is just an identifier, look for an assignment. |
5698 | 14.9k | parseSetAssignment(); |
5699 | 14.9k | return false; |
5700 | 14.9k | } |
5701 | | |
5702 | 0 | return true; |
5703 | 36.0k | } |
5704 | | |
5705 | | /// parseDataDirective |
5706 | | /// ::= .word [ expression (, expression)* ] |
5707 | 19.1k | bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) { |
5708 | 19.1k | MCAsmParser &Parser = getParser(); |
5709 | 19.1k | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
5710 | 108k | for (;;) { |
5711 | 108k | const MCExpr *Value; |
5712 | 108k | if (getParser().parseExpression(Value)) |
5713 | 693 | return true; |
5714 | | |
5715 | 107k | getParser().getStreamer().EmitValue(Value, Size); |
5716 | | |
5717 | 107k | if (getLexer().is(AsmToken::EndOfStatement)) |
5718 | 17.3k | break; |
5719 | | |
5720 | 90.5k | if (getLexer().isNot(AsmToken::Comma)) |
5721 | 756 | return Error(L, "unexpected token, expected comma"); |
5722 | 89.7k | Parser.Lex(); |
5723 | 89.7k | } |
5724 | 18.7k | } |
5725 | | |
5726 | 17.7k | Parser.Lex(); |
5727 | 17.7k | return false; |
5728 | 19.1k | } |
5729 | | |
5730 | | /// parseDirectiveGpWord |
5731 | | /// ::= .gpword local_sym |
5732 | 493 | bool MipsAsmParser::parseDirectiveGpWord() { |
5733 | 493 | MCAsmParser &Parser = getParser(); |
5734 | 493 | const MCExpr *Value; |
5735 | | // EmitGPRel32Value requires an expression, so we are using base class |
5736 | | // method to evaluate the expression. |
5737 | 493 | if (getParser().parseExpression(Value)) |
5738 | 12 | return true; |
5739 | 481 | getParser().getStreamer().EmitGPRel32Value(Value); |
5740 | | |
5741 | 481 | if (getLexer().isNot(AsmToken::EndOfStatement)) |
5742 | 55 | return Error(getLexer().getLoc(), |
5743 | 55 | "unexpected token, expected end of statement"); |
5744 | 426 | Parser.Lex(); // Eat EndOfStatement token. |
5745 | 426 | return false; |
5746 | 481 | } |
5747 | | |
5748 | | /// parseDirectiveGpDWord |
5749 | | /// ::= .gpdword local_sym |
5750 | 136 | bool MipsAsmParser::parseDirectiveGpDWord() { |
5751 | 136 | MCAsmParser &Parser = getParser(); |
5752 | 136 | const MCExpr *Value; |
5753 | | // EmitGPRel64Value requires an expression, so we are using base class |
5754 | | // method to evaluate the expression. |
5755 | 136 | if (getParser().parseExpression(Value)) |
5756 | 11 | return true; |
5757 | 125 | getParser().getStreamer().EmitGPRel64Value(Value); |
5758 | | |
5759 | 125 | if (getLexer().isNot(AsmToken::EndOfStatement)) |
5760 | 43 | return Error(getLexer().getLoc(), |
5761 | 43 | "unexpected token, expected end of statement"); |
5762 | 82 | Parser.Lex(); // Eat EndOfStatement token. |
5763 | 82 | return false; |
5764 | 125 | } |
5765 | | |
5766 | 661 | bool MipsAsmParser::parseDirectiveOption() { |
5767 | 661 | MCAsmParser &Parser = getParser(); |
5768 | | // Get the option token. |
5769 | 661 | AsmToken Tok = Parser.getTok(); |
5770 | | // At the moment only identifiers are supported. |
5771 | 661 | if (Tok.isNot(AsmToken::Identifier)) { |
5772 | 258 | Error(Parser.getTok().getLoc(), "unexpected token, expected identifier"); |
5773 | 258 | Parser.eatToEndOfStatement(); |
5774 | 258 | return false; |
5775 | 258 | } |
5776 | | |
5777 | 403 | StringRef Option = Tok.getIdentifier(); |
5778 | | |
5779 | 403 | if (Option == "pic0") { |
5780 | | // MipsAsmParser needs to know if the current PIC mode changes. |
5781 | 151 | IsPicEnabled = false; |
5782 | | |
5783 | | //getTargetStreamer().emitDirectiveOptionPic0(); |
5784 | 151 | Parser.Lex(); |
5785 | 151 | if (Parser.getTok().isNot(AsmToken::EndOfStatement)) { |
5786 | 87 | Error(Parser.getTok().getLoc(), |
5787 | 87 | "unexpected token, expected end of statement"); |
5788 | 87 | Parser.eatToEndOfStatement(); |
5789 | 87 | } |
5790 | 151 | return false; |
5791 | 151 | } |
5792 | | |
5793 | 252 | if (Option == "pic2") { |
5794 | | // MipsAsmParser needs to know if the current PIC mode changes. |
5795 | 56 | IsPicEnabled = true; |
5796 | | |
5797 | | //getTargetStreamer().emitDirectiveOptionPic2(); |
5798 | 56 | Parser.Lex(); |
5799 | 56 | if (Parser.getTok().isNot(AsmToken::EndOfStatement)) { |
5800 | 45 | Error(Parser.getTok().getLoc(), |
5801 | 45 | "unexpected token, expected end of statement"); |
5802 | 45 | Parser.eatToEndOfStatement(); |
5803 | 45 | } |
5804 | 56 | return false; |
5805 | 56 | } |
5806 | | |
5807 | | // Unknown option. |
5808 | | // Warning(Parser.getTok().getLoc(), |
5809 | | // "unknown option, expected 'pic0' or 'pic2'"); |
5810 | 196 | Parser.eatToEndOfStatement(); |
5811 | 196 | return false; |
5812 | 252 | } |
5813 | | |
5814 | | /// parseInsnDirective |
5815 | | /// ::= .insn |
5816 | 122 | bool MipsAsmParser::parseInsnDirective() { |
5817 | | // If this is not the end of the statement, report an error. |
5818 | 122 | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
5819 | 31 | reportParseError("unexpected token, expected end of statement"); |
5820 | 31 | return false; |
5821 | 31 | } |
5822 | | |
5823 | | // The actual label marking happens in |
5824 | | // MipsELFStreamer::createPendingLabelRelocs(). |
5825 | | //getTargetStreamer().emitDirectiveInsn(); |
5826 | | |
5827 | 91 | getParser().Lex(); // Eat EndOfStatement token. |
5828 | 91 | return false; |
5829 | 122 | } |
5830 | | |
5831 | | /// parseDirectiveModule |
5832 | | /// ::= .module oddspreg |
5833 | | /// ::= .module nooddspreg |
5834 | | /// ::= .module fp=value |
5835 | | /// ::= .module softfloat |
5836 | | /// ::= .module hardfloat |
5837 | 103 | bool MipsAsmParser::parseDirectiveModule() { |
5838 | 103 | MCAsmParser &Parser = getParser(); |
5839 | 103 | MCAsmLexer &Lexer = getLexer(); |
5840 | 103 | SMLoc L = Lexer.getLoc(); |
5841 | | |
5842 | | #if 0 |
5843 | | if (!getTargetStreamer().isModuleDirectiveAllowed()) { |
5844 | | // TODO : get a better message. |
5845 | | reportParseError(".module directive must appear before any code"); |
5846 | | return false; |
5847 | | } |
5848 | | #endif |
5849 | | |
5850 | 103 | StringRef Option; |
5851 | 103 | if (Parser.parseIdentifier(Option)) { |
5852 | 9 | reportParseError("expected .module option identifier"); |
5853 | 9 | return false; |
5854 | 9 | } |
5855 | | |
5856 | 94 | if (Option == "oddspreg") { |
5857 | 4 | clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg"); |
5858 | | |
5859 | | // Synchronize the abiflags information with the FeatureBits information we |
5860 | | // changed above. |
5861 | | //getTargetStreamer().updateABIInfo(*this); |
5862 | | |
5863 | | // If printing assembly, use the recently updated abiflags information. |
5864 | | // If generating ELF, don't do anything (the .MIPS.abiflags section gets |
5865 | | // emitted at the end). |
5866 | | //getTargetStreamer().emitDirectiveModuleOddSPReg(); |
5867 | | |
5868 | | // If this is not the end of the statement, report an error. |
5869 | 4 | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
5870 | 2 | reportParseError("unexpected token, expected end of statement"); |
5871 | 2 | return false; |
5872 | 2 | } |
5873 | | |
5874 | 2 | return false; // parseDirectiveModule has finished successfully. |
5875 | 90 | } else if (Option == "nooddspreg") { |
5876 | 0 | if (!isABI_O32()) { |
5877 | 0 | Error(L, "'.module nooddspreg' requires the O32 ABI"); |
5878 | 0 | return false; |
5879 | 0 | } |
5880 | | |
5881 | 0 | setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg"); |
5882 | | |
5883 | | // Synchronize the abiflags information with the FeatureBits information we |
5884 | | // changed above. |
5885 | | //getTargetStreamer().updateABIInfo(*this); |
5886 | | |
5887 | | // If printing assembly, use the recently updated abiflags information. |
5888 | | // If generating ELF, don't do anything (the .MIPS.abiflags section gets |
5889 | | // emitted at the end). |
5890 | | //getTargetStreamer().emitDirectiveModuleOddSPReg(); |
5891 | | |
5892 | | // If this is not the end of the statement, report an error. |
5893 | 0 | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
5894 | 0 | reportParseError("unexpected token, expected end of statement"); |
5895 | 0 | return false; |
5896 | 0 | } |
5897 | | |
5898 | 0 | return false; // parseDirectiveModule has finished successfully. |
5899 | 90 | } else if (Option == "fp") { |
5900 | 5 | return parseDirectiveModuleFP(); |
5901 | 85 | } else if (Option == "softfloat") { |
5902 | 0 | setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float"); |
5903 | | |
5904 | | // Synchronize the ABI Flags information with the FeatureBits information we |
5905 | | // updated above. |
5906 | | //getTargetStreamer().updateABIInfo(*this); |
5907 | | |
5908 | | // If printing assembly, use the recently updated ABI Flags information. |
5909 | | // If generating ELF, don't do anything (the .MIPS.abiflags section gets |
5910 | | // emitted later). |
5911 | | //getTargetStreamer().emitDirectiveModuleSoftFloat(); |
5912 | | |
5913 | | // If this is not the end of the statement, report an error. |
5914 | 0 | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
5915 | 0 | reportParseError("unexpected token, expected end of statement"); |
5916 | 0 | return false; |
5917 | 0 | } |
5918 | | |
5919 | 0 | return false; // parseDirectiveModule has finished successfully. |
5920 | 85 | } else if (Option == "hardfloat") { |
5921 | 0 | clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float"); |
5922 | | |
5923 | | // Synchronize the ABI Flags information with the FeatureBits information we |
5924 | | // updated above. |
5925 | | //getTargetStreamer().updateABIInfo(*this); |
5926 | | |
5927 | | // If printing assembly, use the recently updated ABI Flags information. |
5928 | | // If generating ELF, don't do anything (the .MIPS.abiflags section gets |
5929 | | // emitted later). |
5930 | | //getTargetStreamer().emitDirectiveModuleHardFloat(); |
5931 | | |
5932 | | // If this is not the end of the statement, report an error. |
5933 | 0 | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
5934 | 0 | reportParseError("unexpected token, expected end of statement"); |
5935 | 0 | return false; |
5936 | 0 | } |
5937 | | |
5938 | 0 | return false; // parseDirectiveModule has finished successfully. |
5939 | 85 | } else { |
5940 | 85 | return Error(L, "'" + Twine(Option) + "' is not a valid .module option."); |
5941 | 85 | } |
5942 | 94 | } |
5943 | | |
5944 | | /// parseDirectiveModuleFP |
5945 | | /// ::= =32 |
5946 | | /// ::= =xx |
5947 | | /// ::= =64 |
5948 | 5 | bool MipsAsmParser::parseDirectiveModuleFP() { |
5949 | 5 | MCAsmParser &Parser = getParser(); |
5950 | 5 | MCAsmLexer &Lexer = getLexer(); |
5951 | | |
5952 | 5 | if (Lexer.isNot(AsmToken::Equal)) { |
5953 | 5 | reportParseError("unexpected token, expected equals sign '='"); |
5954 | 5 | return false; |
5955 | 5 | } |
5956 | 0 | Parser.Lex(); // Eat '=' token. |
5957 | |
|
5958 | 0 | MipsABIFlagsSection::FpABIKind FpABI; |
5959 | 0 | if (!parseFpABIValue(FpABI, ".module")) |
5960 | 0 | return false; |
5961 | | |
5962 | 0 | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
5963 | 0 | reportParseError("unexpected token, expected end of statement"); |
5964 | 0 | return false; |
5965 | 0 | } |
5966 | | |
5967 | | // Synchronize the abiflags information with the FeatureBits information we |
5968 | | // changed above. |
5969 | | //getTargetStreamer().updateABIInfo(*this); |
5970 | | |
5971 | | // If printing assembly, use the recently updated abiflags information. |
5972 | | // If generating ELF, don't do anything (the .MIPS.abiflags section gets |
5973 | | // emitted at the end). |
5974 | | //getTargetStreamer().emitDirectiveModuleFP(); |
5975 | | |
5976 | 0 | Parser.Lex(); // Consume the EndOfStatement. |
5977 | 0 | return false; |
5978 | 0 | } |
5979 | | |
5980 | | bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI, |
5981 | | StringRef Directive) |
5982 | 781 | { |
5983 | 781 | MCAsmParser &Parser = getParser(); |
5984 | 781 | MCAsmLexer &Lexer = getLexer(); |
5985 | 781 | bool ModuleLevelOptions = Directive == ".module"; |
5986 | | |
5987 | 781 | if (Lexer.is(AsmToken::Identifier)) { |
5988 | 366 | StringRef Value = Parser.getTok().getString(); |
5989 | 366 | Parser.Lex(); |
5990 | | |
5991 | 366 | if (Value != "xx") { |
5992 | 250 | reportParseError("unsupported value, expected 'xx', '32' or '64'"); |
5993 | 250 | return false; |
5994 | 250 | } |
5995 | | |
5996 | 116 | if (!isABI_O32()) { |
5997 | 0 | reportParseError("'" + Directive + " fp=xx' requires the O32 ABI"); |
5998 | 0 | return false; |
5999 | 0 | } |
6000 | | |
6001 | 116 | FpABI = MipsABIFlagsSection::FpABIKind::XX; |
6002 | 116 | if (ModuleLevelOptions) { |
6003 | 0 | setModuleFeatureBits(Mips::FeatureFPXX, "fpxx"); |
6004 | 0 | clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64"); |
6005 | 116 | } else { |
6006 | 116 | setFeatureBits(Mips::FeatureFPXX, "fpxx"); |
6007 | 116 | clearFeatureBits(Mips::FeatureFP64Bit, "fp64"); |
6008 | 116 | } |
6009 | 116 | return true; |
6010 | 116 | } |
6011 | | |
6012 | 415 | if (Lexer.is(AsmToken::Integer)) { |
6013 | 364 | bool valid; |
6014 | 364 | unsigned Value = Parser.getTok().getIntVal(valid); |
6015 | 364 | if (!valid) |
6016 | 0 | return true; |
6017 | 364 | Parser.Lex(); |
6018 | | |
6019 | 364 | if (Value != 32 && Value != 64) { |
6020 | 318 | reportParseError("unsupported value, expected 'xx', '32' or '64'"); |
6021 | 318 | return false; |
6022 | 318 | } |
6023 | | |
6024 | 46 | if (Value == 32) { |
6025 | 9 | if (!isABI_O32()) { |
6026 | 3 | reportParseError("'" + Directive + " fp=32' requires the O32 ABI"); |
6027 | 3 | return false; |
6028 | 3 | } |
6029 | | |
6030 | 6 | FpABI = MipsABIFlagsSection::FpABIKind::S32; |
6031 | 6 | if (ModuleLevelOptions) { |
6032 | 0 | clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx"); |
6033 | 0 | clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64"); |
6034 | 6 | } else { |
6035 | 6 | clearFeatureBits(Mips::FeatureFPXX, "fpxx"); |
6036 | 6 | clearFeatureBits(Mips::FeatureFP64Bit, "fp64"); |
6037 | 6 | } |
6038 | 37 | } else { |
6039 | 37 | FpABI = MipsABIFlagsSection::FpABIKind::S64; |
6040 | 37 | if (ModuleLevelOptions) { |
6041 | 0 | clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx"); |
6042 | 0 | setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64"); |
6043 | 37 | } else { |
6044 | 37 | clearFeatureBits(Mips::FeatureFPXX, "fpxx"); |
6045 | 37 | setFeatureBits(Mips::FeatureFP64Bit, "fp64"); |
6046 | 37 | } |
6047 | 37 | } |
6048 | | |
6049 | 43 | return true; |
6050 | 46 | } |
6051 | | |
6052 | 51 | return false; |
6053 | 415 | } |
6054 | | |
6055 | 306k | bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) { |
6056 | 306k | MCAsmParser &Parser = getParser(); |
6057 | 306k | StringRef IDVal = DirectiveID.getString(); |
6058 | | |
6059 | 306k | if (IDVal == ".cpload") |
6060 | 230 | return parseDirectiveCpLoad(DirectiveID.getLoc()); |
6061 | 306k | if (IDVal == ".cprestore") |
6062 | 386 | return parseDirectiveCpRestore(DirectiveID.getLoc()); |
6063 | 306k | if (IDVal == ".dword") { |
6064 | 64 | parseDataDirective(8, DirectiveID.getLoc()); |
6065 | 64 | return false; |
6066 | 64 | } |
6067 | 306k | if (IDVal == ".ent") { |
6068 | 903 | StringRef SymbolName; |
6069 | | |
6070 | 903 | if (Parser.parseIdentifier(SymbolName)) { |
6071 | 727 | reportParseError("expected identifier after .ent"); |
6072 | 727 | return false; |
6073 | 727 | } |
6074 | | |
6075 | | // There's an undocumented extension that allows an integer to |
6076 | | // follow the name of the procedure which AFAICS is ignored by GAS. |
6077 | | // Example: .ent foo,2 |
6078 | 176 | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
6079 | 148 | if (getLexer().isNot(AsmToken::Comma)) { |
6080 | | // Even though we accept this undocumented extension for compatibility |
6081 | | // reasons, the additional integer argument does not actually change |
6082 | | // the behaviour of the '.ent' directive, so we would like to discourage |
6083 | | // its use. We do this by not referring to the extended version in |
6084 | | // error messages which are not directly related to its use. |
6085 | 28 | reportParseError("unexpected token, expected end of statement"); |
6086 | 28 | return false; |
6087 | 28 | } |
6088 | 120 | Parser.Lex(); // Eat the comma. |
6089 | 120 | const MCExpr *DummyNumber; |
6090 | 120 | int64_t DummyNumberVal; |
6091 | | // If the user was explicitly trying to use the extended version, |
6092 | | // we still give helpful extension-related error messages. |
6093 | 120 | if (Parser.parseExpression(DummyNumber)) { |
6094 | 17 | reportParseError("expected number after comma"); |
6095 | 17 | return false; |
6096 | 17 | } |
6097 | 103 | if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) { |
6098 | 50 | reportParseError("expected an absolute expression after comma"); |
6099 | 50 | return false; |
6100 | 50 | } |
6101 | 103 | } |
6102 | | |
6103 | | // If this is not the end of the statement, report an error. |
6104 | 81 | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
6105 | 53 | reportParseError("unexpected token, expected end of statement"); |
6106 | 53 | return false; |
6107 | 53 | } |
6108 | | |
6109 | 28 | MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName); |
6110 | | |
6111 | | //getTargetStreamer().emitDirectiveEnt(*Sym); |
6112 | 28 | CurrentFn = Sym; |
6113 | 28 | IsCpRestoreSet = false; |
6114 | 28 | return false; |
6115 | 81 | } |
6116 | | |
6117 | 305k | if (IDVal == ".end") { |
6118 | 568 | StringRef SymbolName; |
6119 | | |
6120 | 568 | if (Parser.parseIdentifier(SymbolName)) { |
6121 | 466 | reportParseError("expected identifier after .end"); |
6122 | 466 | return false; |
6123 | 466 | } |
6124 | | |
6125 | 102 | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
6126 | 47 | reportParseError("unexpected token, expected end of statement"); |
6127 | 47 | return false; |
6128 | 47 | } |
6129 | | |
6130 | 55 | if (CurrentFn == nullptr) { |
6131 | 25 | reportParseError(".end used without .ent"); |
6132 | 25 | return false; |
6133 | 25 | } |
6134 | | |
6135 | 30 | if ((SymbolName != CurrentFn->getName())) { |
6136 | 24 | reportParseError(".end symbol does not match .ent symbol"); |
6137 | 24 | return false; |
6138 | 24 | } |
6139 | | |
6140 | | //getTargetStreamer().emitDirectiveEnd(SymbolName); |
6141 | 6 | CurrentFn = nullptr; |
6142 | 6 | IsCpRestoreSet = false; |
6143 | 6 | return false; |
6144 | 30 | } |
6145 | | |
6146 | 304k | if (IDVal == ".frame") { |
6147 | | // .frame $stack_reg, frame_size_in_bytes, $return_reg |
6148 | 7.78k | SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg; |
6149 | 7.78k | OperandMatchResultTy ResTy = parseAnyRegister(TmpReg); |
6150 | 7.78k | if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) { |
6151 | 3.91k | reportParseError("expected stack register"); |
6152 | 3.91k | return false; |
6153 | 3.91k | } |
6154 | | |
6155 | 3.87k | MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]); |
6156 | 3.87k | if (!StackRegOpnd.isGPRAsmReg()) { |
6157 | 99 | reportParseError(StackRegOpnd.getStartLoc(), |
6158 | 99 | "expected general purpose register"); |
6159 | 99 | return false; |
6160 | 99 | } |
6161 | | //unsigned StackReg = StackRegOpnd.getGPR32Reg(); |
6162 | | |
6163 | 3.77k | if (Parser.getTok().is(AsmToken::Comma)) |
6164 | 3.62k | Parser.Lex(); |
6165 | 143 | else { |
6166 | 143 | reportParseError("unexpected token, expected comma"); |
6167 | 143 | return false; |
6168 | 143 | } |
6169 | | |
6170 | | // Parse the frame size. |
6171 | 3.62k | const MCExpr *FrameSize; |
6172 | 3.62k | int64_t FrameSizeVal; |
6173 | | |
6174 | 3.62k | if (Parser.parseExpression(FrameSize)) { |
6175 | 228 | reportParseError("expected frame size value"); |
6176 | 228 | return false; |
6177 | 228 | } |
6178 | | |
6179 | 3.40k | if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) { |
6180 | 105 | reportParseError("frame size not an absolute expression"); |
6181 | 105 | return false; |
6182 | 105 | } |
6183 | | |
6184 | 3.29k | if (Parser.getTok().is(AsmToken::Comma)) |
6185 | 3.05k | Parser.Lex(); |
6186 | 245 | else { |
6187 | 245 | reportParseError("unexpected token, expected comma"); |
6188 | 245 | return false; |
6189 | 245 | } |
6190 | | |
6191 | | // Parse the return register. |
6192 | 3.05k | TmpReg.clear(); |
6193 | 3.05k | ResTy = parseAnyRegister(TmpReg); |
6194 | 3.05k | if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) { |
6195 | 3.02k | reportParseError("expected return register"); |
6196 | 3.02k | return false; |
6197 | 3.02k | } |
6198 | | |
6199 | 29 | MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]); |
6200 | 29 | if (!ReturnRegOpnd.isGPRAsmReg()) { |
6201 | 18 | reportParseError(ReturnRegOpnd.getStartLoc(), |
6202 | 18 | "expected general purpose register"); |
6203 | 18 | return false; |
6204 | 18 | } |
6205 | | |
6206 | | // If this is not the end of the statement, report an error. |
6207 | 11 | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
6208 | 11 | reportParseError("unexpected token, expected end of statement"); |
6209 | 11 | return false; |
6210 | 11 | } |
6211 | | |
6212 | | //getTargetStreamer().emitFrame(StackReg, FrameSizeVal, |
6213 | | // ReturnRegOpnd.getGPR32Reg()); |
6214 | 0 | IsCpRestoreSet = false; |
6215 | 0 | return false; |
6216 | 11 | } |
6217 | | |
6218 | 296k | if (IDVal == ".set") { |
6219 | 36.0k | return parseDirectiveSet(); |
6220 | 36.0k | } |
6221 | | |
6222 | 260k | if (IDVal == ".mask" || IDVal == ".fmask") { |
6223 | | // .mask bitmask, frame_offset |
6224 | | // bitmask: One bit for each register used. |
6225 | | // frame_offset: Offset from Canonical Frame Address ($sp on entry) where |
6226 | | // first register is expected to be saved. |
6227 | | // Examples: |
6228 | | // .mask 0x80000000, -4 |
6229 | | // .fmask 0x80000000, -4 |
6230 | | // |
6231 | | |
6232 | | // Parse the bitmask |
6233 | 1.48k | const MCExpr *BitMask; |
6234 | 1.48k | int64_t BitMaskVal; |
6235 | | |
6236 | 1.48k | if (Parser.parseExpression(BitMask)) { |
6237 | 451 | reportParseError("expected bitmask value"); |
6238 | 451 | return false; |
6239 | 451 | } |
6240 | | |
6241 | 1.03k | if (!BitMask->evaluateAsAbsolute(BitMaskVal)) { |
6242 | 246 | reportParseError("bitmask not an absolute expression"); |
6243 | 246 | return false; |
6244 | 246 | } |
6245 | | |
6246 | 787 | if (Parser.getTok().is(AsmToken::Comma)) |
6247 | 553 | Parser.Lex(); |
6248 | 234 | else { |
6249 | 234 | reportParseError("unexpected token, expected comma"); |
6250 | 234 | return false; |
6251 | 234 | } |
6252 | | |
6253 | | // Parse the frame_offset |
6254 | 553 | const MCExpr *FrameOffset; |
6255 | 553 | int64_t FrameOffsetVal; |
6256 | | |
6257 | 553 | if (Parser.parseExpression(FrameOffset)) { |
6258 | 354 | reportParseError("expected frame offset value"); |
6259 | 354 | return false; |
6260 | 354 | } |
6261 | | |
6262 | 199 | if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) { |
6263 | 98 | reportParseError("frame offset not an absolute expression"); |
6264 | 98 | return false; |
6265 | 98 | } |
6266 | | |
6267 | | // If this is not the end of the statement, report an error. |
6268 | 101 | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
6269 | 96 | reportParseError("unexpected token, expected end of statement"); |
6270 | 96 | return false; |
6271 | 96 | } |
6272 | | |
6273 | | #if 0 |
6274 | | if (IDVal == ".mask") |
6275 | | getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal); |
6276 | | else |
6277 | | getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal); |
6278 | | #endif |
6279 | 5 | return false; |
6280 | 101 | } |
6281 | | |
6282 | 259k | if (IDVal == ".nan") |
6283 | 1.14k | return parseDirectiveNaN(); |
6284 | | |
6285 | 258k | if (IDVal == ".gpword") { |
6286 | 493 | parseDirectiveGpWord(); |
6287 | 493 | return false; |
6288 | 493 | } |
6289 | | |
6290 | 257k | if (IDVal == ".gpdword") { |
6291 | 136 | parseDirectiveGpDWord(); |
6292 | 136 | return false; |
6293 | 136 | } |
6294 | | |
6295 | 257k | if (IDVal == ".word") { |
6296 | 19.1k | parseDataDirective(4, DirectiveID.getLoc()); |
6297 | 19.1k | return false; |
6298 | 19.1k | } |
6299 | | |
6300 | 238k | if (IDVal == ".option") |
6301 | 661 | return parseDirectiveOption(); |
6302 | | |
6303 | 237k | if (IDVal == ".abicalls") { |
6304 | | //getTargetStreamer().emitDirectiveAbiCalls(); |
6305 | 48 | if (Parser.getTok().isNot(AsmToken::EndOfStatement)) { |
6306 | 12 | Error(Parser.getTok().getLoc(), |
6307 | 12 | "unexpected token, expected end of statement"); |
6308 | | // Clear line |
6309 | 12 | Parser.eatToEndOfStatement(); |
6310 | 12 | } |
6311 | 48 | return false; |
6312 | 48 | } |
6313 | | |
6314 | 237k | if (IDVal == ".cpsetup") |
6315 | 3.10k | return parseDirectiveCPSetup(); |
6316 | | |
6317 | 234k | if (IDVal == ".cpreturn") |
6318 | 4 | return parseDirectiveCPReturn(); |
6319 | | |
6320 | 234k | if (IDVal == ".module") |
6321 | 103 | return parseDirectiveModule(); |
6322 | | |
6323 | 234k | if (IDVal == ".llvm_internal_mips_reallow_module_directive") |
6324 | 0 | return parseInternalDirectiveReallowModule(); |
6325 | | |
6326 | 234k | if (IDVal == ".insn") |
6327 | 122 | return parseInsnDirective(); |
6328 | | |
6329 | 234k | return true; |
6330 | 234k | } |
6331 | | |
6332 | 0 | bool MipsAsmParser::parseInternalDirectiveReallowModule() { |
6333 | | // If this is not the end of the statement, report an error. |
6334 | 0 | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
6335 | 0 | reportParseError("unexpected token, expected end of statement"); |
6336 | 0 | return false; |
6337 | 0 | } |
6338 | | |
6339 | | //getTargetStreamer().reallowModuleDirective(); |
6340 | | |
6341 | 0 | getParser().Lex(); // Eat EndOfStatement token. |
6342 | 0 | return false; |
6343 | 0 | } |
6344 | | |
6345 | 25 | extern "C" void LLVMInitializeMipsAsmParser() { |
6346 | 25 | RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget); |
6347 | 25 | RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget); |
6348 | 25 | RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target); |
6349 | 25 | RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget); |
6350 | 25 | } |
6351 | | |
6352 | | #define GET_REGISTER_MATCHER |
6353 | | #define GET_MATCHER_IMPLEMENTATION |
6354 | | #include "MipsGenAsmMatcher.inc" |