Deleted Added
sdiff udiff text old ( 276479 ) new ( 277320 )
full compact
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/MipsMCExpr.h"
11#include "MCTargetDesc/MipsMCTargetDesc.h"
12#include "MipsRegisterInfo.h"
13#include "MipsTargetStreamer.h"
14#include "llvm/ADT/APInt.h"
15#include "llvm/ADT/StringSwitch.h"
16#include "llvm/MC/MCContext.h"
17#include "llvm/MC/MCExpr.h"
18#include "llvm/MC/MCInst.h"
19#include "llvm/MC/MCInstBuilder.h"
20#include "llvm/MC/MCParser/MCAsmLexer.h"
21#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
22#include "llvm/MC/MCStreamer.h"
23#include "llvm/MC/MCSubtargetInfo.h"
24#include "llvm/MC/MCSymbol.h"
25#include "llvm/MC/MCTargetAsmParser.h"
26#include "llvm/Support/Debug.h"
27#include "llvm/Support/MathExtras.h"
28#include "llvm/Support/TargetRegistry.h"
29
30using namespace llvm;
31
32#define DEBUG_TYPE "mips-asm-parser"
33
34namespace llvm {
35class MCInstrInfo;
36}
37
38namespace {
39class MipsAssemblerOptions {
40public:
41 MipsAssemblerOptions() : aTReg(1), reorder(true), macro(true) {}
42
43 unsigned getATRegNum() { return aTReg; }
44 bool setATReg(unsigned Reg);
45
46 bool isReorder() { return reorder; }
47 void setReorder() { reorder = true; }
48 void setNoreorder() { reorder = false; }
49
50 bool isMacro() { return macro; }
51 void setMacro() { macro = true; }
52 void setNomacro() { macro = false; }
53
54private:
55 unsigned aTReg;
56 bool reorder;
57 bool macro;
58};
59}
60
61namespace {
62class MipsAsmParser : public MCTargetAsmParser {
63 MipsTargetStreamer &getTargetStreamer() {
64 MCTargetStreamer &TS = *Parser.getStreamer().getTargetStreamer();
65 return static_cast<MipsTargetStreamer &>(TS);
66 }
67
68 MCSubtargetInfo &STI;
69 MCAsmParser &Parser;
70 MipsAssemblerOptions Options;
71
72#define GET_ASSEMBLER_HEADER
73#include "MipsGenAsmMatcher.inc"
74
75 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
76
77 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
78 OperandVector &Operands, MCStreamer &Out,
79 unsigned &ErrorInfo,
80 bool MatchingInlineAsm) override;
81
82 /// Parse a register as used in CFI directives
83 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
84
85 bool ParseParenSuffix(StringRef Name, OperandVector &Operands);
86
87 bool ParseBracketSuffix(StringRef Name, OperandVector &Operands);
88
89 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
90 SMLoc NameLoc, OperandVector &Operands) override;
91
92 bool ParseDirective(AsmToken DirectiveID) override;
93
94 MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
95
96 MipsAsmParser::OperandMatchResultTy
97 MatchAnyRegisterNameWithoutDollar(OperandVector &Operands,
98 StringRef Identifier, SMLoc S);
99
100 MipsAsmParser::OperandMatchResultTy
101 MatchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
102
103 MipsAsmParser::OperandMatchResultTy ParseAnyRegister(OperandVector &Operands);
104
105 MipsAsmParser::OperandMatchResultTy ParseImm(OperandVector &Operands);
106
107 MipsAsmParser::OperandMatchResultTy ParseJumpTarget(OperandVector &Operands);
108
109 MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
110
111 MipsAsmParser::OperandMatchResultTy ParseLSAImm(OperandVector &Operands);
112
113 bool searchSymbolAlias(OperandVector &Operands);
114
115 bool ParseOperand(OperandVector &, StringRef Mnemonic);
116
117 bool needsExpansion(MCInst &Inst);
118
119 // Expands assembly pseudo instructions.
120 // Returns false on success, true otherwise.
121 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
122 SmallVectorImpl<MCInst> &Instructions);
123
124 bool expandLoadImm(MCInst &Inst, SMLoc IDLoc,
125 SmallVectorImpl<MCInst> &Instructions);
126
127 bool expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
128 SmallVectorImpl<MCInst> &Instructions);
129
130 bool expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
131 SmallVectorImpl<MCInst> &Instructions);
132
133 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
134 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
135 bool isImmOpnd);
136 bool reportParseError(Twine ErrorMsg);
137 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
138
139 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
140 bool parseRelocOperand(const MCExpr *&Res);
141
142 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
143
144 bool isEvaluated(const MCExpr *Expr);
145 bool parseSetFeature(uint64_t Feature);
146 bool parseDirectiveCPLoad(SMLoc Loc);
147 bool parseDirectiveCPSetup();
148 bool parseDirectiveNaN();
149 bool parseDirectiveSet();
150 bool parseDirectiveOption();
151
152 bool parseSetAtDirective();
153 bool parseSetNoAtDirective();
154 bool parseSetMacroDirective();
155 bool parseSetNoMacroDirective();
156 bool parseSetReorderDirective();
157 bool parseSetNoReorderDirective();
158 bool parseSetNoMips16Directive();
159 bool parseSetFpDirective();
160
161 bool parseSetAssignment();
162
163 bool parseDataDirective(unsigned Size, SMLoc L);
164 bool parseDirectiveGpWord();
165 bool parseDirectiveGpDWord();
166 bool parseDirectiveModule();
167 bool parseDirectiveModuleFP();
168 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
169 StringRef Directive);
170
171 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
172
173 bool eatComma(StringRef ErrorStr);
174
175 int matchCPURegisterName(StringRef Symbol);
176
177 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
178
179 int matchFPURegisterName(StringRef Name);
180
181 int matchFCCRegisterName(StringRef Name);
182
183 int matchACRegisterName(StringRef Name);
184
185 int matchMSA128RegisterName(StringRef Name);
186
187 int matchMSA128CtrlRegisterName(StringRef Name);
188
189 unsigned getReg(int RC, int RegNo);
190
191 unsigned getGPR(int RegNo);
192
193 int getATReg(SMLoc Loc);
194
195 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
196 SmallVectorImpl<MCInst> &Instructions);
197
198 // Helper function that checks if the value of a vector index is within the
199 // boundaries of accepted values for each RegisterKind
200 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
201 bool validateMSAIndex(int Val, int RegKind);
202
203 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
204 if (!(STI.getFeatureBits() & Feature)) {
205 setAvailableFeatures(
206 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
207 }
208 }
209
210 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
211 if (STI.getFeatureBits() & Feature) {
212 setAvailableFeatures(
213 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
214 }
215 }
216
217public:
218 enum MipsMatchResultTy {
219 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
220#define GET_OPERAND_DIAGNOSTIC_TYPES
221#include "MipsGenAsmMatcher.inc"
222#undef GET_OPERAND_DIAGNOSTIC_TYPES
223
224 };
225
226 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
227 const MCInstrInfo &MII, const MCTargetOptions &Options)
228 : MCTargetAsmParser(), STI(sti), Parser(parser) {
229 // Initialize the set of available features.
230 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
231
232 getTargetStreamer().updateABIInfo(*this);
233
234 // Assert exactly one ABI was chosen.
235 assert((((STI.getFeatureBits() & Mips::FeatureO32) != 0) +
236 ((STI.getFeatureBits() & Mips::FeatureEABI) != 0) +
237 ((STI.getFeatureBits() & Mips::FeatureN32) != 0) +
238 ((STI.getFeatureBits() & Mips::FeatureN64) != 0)) == 1);
239
240 if (!isABI_O32() && !useOddSPReg() != 0)
241 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
242 }
243
244 MCAsmParser &getParser() const { return Parser; }
245 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
246
247 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
248 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
249
250 bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; }
251 bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; }
252 bool isABI_N32() const { return STI.getFeatureBits() & Mips::FeatureN32; }
253 bool isABI_N64() const { return STI.getFeatureBits() & Mips::FeatureN64; }
254 bool isABI_O32() const { return STI.getFeatureBits() & Mips::FeatureO32; }
255 bool isABI_FPXX() const { return STI.getFeatureBits() & Mips::FeatureFPXX; }
256
257 bool useOddSPReg() const {
258 return !(STI.getFeatureBits() & Mips::FeatureNoOddSPReg);
259 }
260
261 bool inMicroMipsMode() const {
262 return STI.getFeatureBits() & Mips::FeatureMicroMips;
263 }
264 bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; }
265 bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; }
266 bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; }
267 bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
268 bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; }
269 bool hasMips32() const {
270 return (STI.getFeatureBits() & Mips::FeatureMips32);
271 }
272 bool hasMips64() const {
273 return (STI.getFeatureBits() & Mips::FeatureMips64);
274 }
275 bool hasMips32r2() const {
276 return (STI.getFeatureBits() & Mips::FeatureMips32r2);
277 }
278 bool hasMips64r2() const {
279 return (STI.getFeatureBits() & Mips::FeatureMips64r2);
280 }
281 bool hasMips32r6() const {
282 return (STI.getFeatureBits() & Mips::FeatureMips32r6);
283 }
284 bool hasMips64r6() const {
285 return (STI.getFeatureBits() & Mips::FeatureMips64r6);
286 }
287 bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
288 bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
289 bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }
290
291 bool inMips16Mode() const {
292 return STI.getFeatureBits() & Mips::FeatureMips16;
293 }
294 // TODO: see how can we get this info.
295 bool abiUsesSoftFloat() const { return false; }
296
297 /// Warn if RegNo is the current assembler temporary.
298 void WarnIfAssemblerTemporary(int RegNo, SMLoc Loc);
299};
300}
301
302namespace {
303
304/// MipsOperand - Instances of this class represent a parsed Mips machine
305/// instruction.
306class MipsOperand : public MCParsedAsmOperand {
307public:
308 /// Broad categories of register classes
309 /// The exact class is finalized by the render method.
310 enum RegKind {
311 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
312 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
313 /// isFP64bit())
314 RegKind_FCC = 4, /// FCC
315 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
316 RegKind_MSACtrl = 16, /// MSA control registers
317 RegKind_COP2 = 32, /// COP2
318 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
319 /// context).
320 RegKind_CCR = 128, /// CCR
321 RegKind_HWRegs = 256, /// HWRegs
322 RegKind_COP3 = 512, /// COP3
323
324 /// Potentially any (e.g. $1)
325 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
326 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
327 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
328 };
329
330private:
331 enum KindTy {
332 k_Immediate, /// An immediate (possibly involving symbol references)
333 k_Memory, /// Base + Offset Memory Address
334 k_PhysRegister, /// A physical register from the Mips namespace
335 k_RegisterIndex, /// A register index in one or more RegKind.
336 k_Token /// A simple token
337 } Kind;
338
339public:
340 MipsOperand(KindTy K, MipsAsmParser &Parser)
341 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
342
343private:
344 /// For diagnostics, and checking the assembler temporary
345 MipsAsmParser &AsmParser;
346
347 struct Token {
348 const char *Data;
349 unsigned Length;
350 };
351
352 struct PhysRegOp {
353 unsigned Num; /// Register Number
354 };
355
356 struct RegIdxOp {
357 unsigned Index; /// Index into the register class
358 RegKind Kind; /// Bitfield of the kinds it could possibly be
359 const MCRegisterInfo *RegInfo;
360 };
361
362 struct ImmOp {
363 const MCExpr *Val;
364 };
365
366 struct MemOp {
367 MipsOperand *Base;
368 const MCExpr *Off;
369 };
370
371 union {
372 struct Token Tok;
373 struct PhysRegOp PhysReg;
374 struct RegIdxOp RegIdx;
375 struct ImmOp Imm;
376 struct MemOp Mem;
377 };
378
379 SMLoc StartLoc, EndLoc;
380
381 /// Internal constructor for register kinds
382 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
383 const MCRegisterInfo *RegInfo,
384 SMLoc S, SMLoc E,
385 MipsAsmParser &Parser) {
386 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
387 Op->RegIdx.Index = Index;
388 Op->RegIdx.RegInfo = RegInfo;
389 Op->RegIdx.Kind = RegKind;
390 Op->StartLoc = S;
391 Op->EndLoc = E;
392 return Op;
393 }
394
395public:
396 /// Coerce the register to GPR32 and return the real register for the current
397 /// target.
398 unsigned getGPR32Reg() const {
399 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
400 AsmParser.WarnIfAssemblerTemporary(RegIdx.Index, StartLoc);
401 unsigned ClassID = Mips::GPR32RegClassID;
402 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
403 }
404
405 /// Coerce the register to GPR64 and return the real register for the current
406 /// target.
407 unsigned getGPR64Reg() const {
408 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
409 unsigned ClassID = Mips::GPR64RegClassID;
410 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
411 }
412
413private:
414 /// Coerce the register to AFGR64 and return the real register for the current
415 /// target.
416 unsigned getAFGR64Reg() const {
417 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
418 if (RegIdx.Index % 2 != 0)
419 AsmParser.Warning(StartLoc, "Float register should be even.");
420 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
421 .getRegister(RegIdx.Index / 2);
422 }
423
424 /// Coerce the register to FGR64 and return the real register for the current
425 /// target.
426 unsigned getFGR64Reg() const {
427 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
428 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
429 .getRegister(RegIdx.Index);
430 }
431
432 /// Coerce the register to FGR32 and return the real register for the current
433 /// target.
434 unsigned getFGR32Reg() const {
435 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
436 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
437 .getRegister(RegIdx.Index);
438 }
439
440 /// Coerce the register to FGRH32 and return the real register for the current
441 /// target.
442 unsigned getFGRH32Reg() const {
443 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
444 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
445 .getRegister(RegIdx.Index);
446 }
447
448 /// Coerce the register to FCC and return the real register for the current
449 /// target.
450 unsigned getFCCReg() const {
451 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
452 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
453 .getRegister(RegIdx.Index);
454 }
455
456 /// Coerce the register to MSA128 and return the real register for the current
457 /// target.
458 unsigned getMSA128Reg() const {
459 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
460 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
461 // identical
462 unsigned ClassID = Mips::MSA128BRegClassID;
463 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
464 }
465
466 /// Coerce the register to MSACtrl and return the real register for the
467 /// current target.
468 unsigned getMSACtrlReg() const {
469 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
470 unsigned ClassID = Mips::MSACtrlRegClassID;
471 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
472 }
473
474 /// Coerce the register to COP2 and return the real register for the
475 /// current target.
476 unsigned getCOP2Reg() const {
477 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
478 unsigned ClassID = Mips::COP2RegClassID;
479 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
480 }
481
482 /// Coerce the register to COP3 and return the real register for the
483 /// current target.
484 unsigned getCOP3Reg() const {
485 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
486 unsigned ClassID = Mips::COP3RegClassID;
487 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
488 }
489
490 /// Coerce the register to ACC64DSP and return the real register for the
491 /// current target.
492 unsigned getACC64DSPReg() const {
493 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
494 unsigned ClassID = Mips::ACC64DSPRegClassID;
495 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
496 }
497
498 /// Coerce the register to HI32DSP and return the real register for the
499 /// current target.
500 unsigned getHI32DSPReg() const {
501 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
502 unsigned ClassID = Mips::HI32DSPRegClassID;
503 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
504 }
505
506 /// Coerce the register to LO32DSP and return the real register for the
507 /// current target.
508 unsigned getLO32DSPReg() const {
509 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
510 unsigned ClassID = Mips::LO32DSPRegClassID;
511 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
512 }
513
514 /// Coerce the register to CCR and return the real register for the
515 /// current target.
516 unsigned getCCRReg() const {
517 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
518 unsigned ClassID = Mips::CCRRegClassID;
519 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
520 }
521
522 /// Coerce the register to HWRegs and return the real register for the
523 /// current target.
524 unsigned getHWRegsReg() const {
525 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
526 unsigned ClassID = Mips::HWRegsRegClassID;
527 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
528 }
529
530public:
531 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
532 // Add as immediate when possible. Null MCExpr = 0.
533 if (!Expr)
534 Inst.addOperand(MCOperand::CreateImm(0));
535 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
536 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
537 else
538 Inst.addOperand(MCOperand::CreateExpr(Expr));
539 }
540
541 void addRegOperands(MCInst &Inst, unsigned N) const {
542 llvm_unreachable("Use a custom parser instead");
543 }
544
545 /// Render the operand to an MCInst as a GPR32
546 /// Asserts if the wrong number of operands are requested, or the operand
547 /// is not a k_RegisterIndex compatible with RegKind_GPR
548 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
549 assert(N == 1 && "Invalid number of operands!");
550 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
551 }
552
553 /// Render the operand to an MCInst as a GPR64
554 /// Asserts if the wrong number of operands are requested, or the operand
555 /// is not a k_RegisterIndex compatible with RegKind_GPR
556 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
557 assert(N == 1 && "Invalid number of operands!");
558 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
559 }
560
561 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
562 assert(N == 1 && "Invalid number of operands!");
563 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
564 }
565
566 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
567 assert(N == 1 && "Invalid number of operands!");
568 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
569 }
570
571 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
572 assert(N == 1 && "Invalid number of operands!");
573 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
574 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
575 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
576 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
577 "registers");
578 }
579
580 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
581 assert(N == 1 && "Invalid number of operands!");
582 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
583 }
584
585 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
586 assert(N == 1 && "Invalid number of operands!");
587 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
588 }
589
590 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
591 assert(N == 1 && "Invalid number of operands!");
592 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
593 }
594
595 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
596 assert(N == 1 && "Invalid number of operands!");
597 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
598 }
599
600 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
601 assert(N == 1 && "Invalid number of operands!");
602 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
603 }
604
605 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
606 assert(N == 1 && "Invalid number of operands!");
607 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
608 }
609
610 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
611 assert(N == 1 && "Invalid number of operands!");
612 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
613 }
614
615 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
616 assert(N == 1 && "Invalid number of operands!");
617 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
618 }
619
620 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
621 assert(N == 1 && "Invalid number of operands!");
622 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
623 }
624
625 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
626 assert(N == 1 && "Invalid number of operands!");
627 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
628 }
629
630 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
631 assert(N == 1 && "Invalid number of operands!");
632 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
633 }
634
635 void addImmOperands(MCInst &Inst, unsigned N) const {
636 assert(N == 1 && "Invalid number of operands!");
637 const MCExpr *Expr = getImm();
638 addExpr(Inst, Expr);
639 }
640
641 void addMemOperands(MCInst &Inst, unsigned N) const {
642 assert(N == 2 && "Invalid number of operands!");
643
644 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
645
646 const MCExpr *Expr = getMemOff();
647 addExpr(Inst, Expr);
648 }
649
650 bool isReg() const override {
651 // As a special case until we sort out the definition of div/divu, pretend
652 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
653 if (isGPRAsmReg() && RegIdx.Index == 0)
654 return true;
655
656 return Kind == k_PhysRegister;
657 }
658 bool isRegIdx() const { return Kind == k_RegisterIndex; }
659 bool isImm() const override { return Kind == k_Immediate; }
660 bool isConstantImm() const {
661 return isImm() && dyn_cast<MCConstantExpr>(getImm());
662 }
663 bool isToken() const override {
664 // Note: It's not possible to pretend that other operand kinds are tokens.
665 // The matcher emitter checks tokens first.
666 return Kind == k_Token;
667 }
668 bool isMem() const override { return Kind == k_Memory; }
669 bool isConstantMemOff() const {
670 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
671 }
672 template <unsigned Bits> bool isMemWithSimmOffset() const {
673 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
674 }
675 bool isInvNum() const { return Kind == k_Immediate; }
676 bool isLSAImm() const {
677 if (!isConstantImm())
678 return false;
679 int64_t Val = getConstantImm();
680 return 1 <= Val && Val <= 4;
681 }
682
683 StringRef getToken() const {
684 assert(Kind == k_Token && "Invalid access!");
685 return StringRef(Tok.Data, Tok.Length);
686 }
687
688 unsigned getReg() const override {
689 // As a special case until we sort out the definition of div/divu, pretend
690 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
691 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
692 RegIdx.Kind & RegKind_GPR)
693 return getGPR32Reg(); // FIXME: GPR64 too
694
695 assert(Kind == k_PhysRegister && "Invalid access!");
696 return PhysReg.Num;
697 }
698
699 const MCExpr *getImm() const {
700 assert((Kind == k_Immediate) && "Invalid access!");
701 return Imm.Val;
702 }
703
704 int64_t getConstantImm() const {
705 const MCExpr *Val = getImm();
706 return static_cast<const MCConstantExpr *>(Val)->getValue();
707 }
708
709 MipsOperand *getMemBase() const {
710 assert((Kind == k_Memory) && "Invalid access!");
711 return Mem.Base;
712 }
713
714 const MCExpr *getMemOff() const {
715 assert((Kind == k_Memory) && "Invalid access!");
716 return Mem.Off;
717 }
718
719 int64_t getConstantMemOff() const {
720 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
721 }
722
723 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
724 MipsAsmParser &Parser) {
725 auto Op = make_unique<MipsOperand>(k_Token, Parser);
726 Op->Tok.Data = Str.data();
727 Op->Tok.Length = Str.size();
728 Op->StartLoc = S;
729 Op->EndLoc = S;
730 return Op;
731 }
732
733 /// Create a numeric register (e.g. $1). The exact register remains
734 /// unresolved until an instruction successfully matches
735 static std::unique_ptr<MipsOperand>
736 CreateNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
737 SMLoc E, MipsAsmParser &Parser) {
738 DEBUG(dbgs() << "CreateNumericReg(" << Index << ", ...)\n");
739 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
740 }
741
742 /// Create a register that is definitely a GPR.
743 /// This is typically only used for named registers such as $gp.
744 static std::unique_ptr<MipsOperand>
745 CreateGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
746 MipsAsmParser &Parser) {
747 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
748 }
749
750 /// Create a register that is definitely a FGR.
751 /// This is typically only used for named registers such as $f0.
752 static std::unique_ptr<MipsOperand>
753 CreateFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
754 MipsAsmParser &Parser) {
755 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
756 }
757
758 /// Create a register that is definitely an FCC.
759 /// This is typically only used for named registers such as $fcc0.
760 static std::unique_ptr<MipsOperand>
761 CreateFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
762 MipsAsmParser &Parser) {
763 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
764 }
765
766 /// Create a register that is definitely an ACC.
767 /// This is typically only used for named registers such as $ac0.
768 static std::unique_ptr<MipsOperand>
769 CreateACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
770 MipsAsmParser &Parser) {
771 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
772 }
773
774 /// Create a register that is definitely an MSA128.
775 /// This is typically only used for named registers such as $w0.
776 static std::unique_ptr<MipsOperand>
777 CreateMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
778 SMLoc E, MipsAsmParser &Parser) {
779 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
780 }
781
782 /// Create a register that is definitely an MSACtrl.
783 /// This is typically only used for named registers such as $msaaccess.
784 static std::unique_ptr<MipsOperand>
785 CreateMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
786 SMLoc E, MipsAsmParser &Parser) {
787 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
788 }
789
790 static std::unique_ptr<MipsOperand>
791 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
792 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
793 Op->Imm.Val = Val;
794 Op->StartLoc = S;
795 Op->EndLoc = E;
796 return Op;
797 }
798
799 static std::unique_ptr<MipsOperand>
800 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
801 SMLoc E, MipsAsmParser &Parser) {
802 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
803 Op->Mem.Base = Base.release();
804 Op->Mem.Off = Off;
805 Op->StartLoc = S;
806 Op->EndLoc = E;
807 return Op;
808 }
809
810 bool isGPRAsmReg() const {
811 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
812 }
813 bool isFGRAsmReg() const {
814 // AFGR64 is $0-$15 but we handle this in getAFGR64()
815 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
816 }
817 bool isHWRegsAsmReg() const {
818 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
819 }
820 bool isCCRAsmReg() const {
821 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
822 }
823 bool isFCCAsmReg() const {
824 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
825 return false;
826 if (!AsmParser.hasEightFccRegisters())
827 return RegIdx.Index == 0;
828 return RegIdx.Index <= 7;
829 }
830 bool isACCAsmReg() const {
831 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
832 }
833 bool isCOP2AsmReg() const {
834 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
835 }
836 bool isCOP3AsmReg() const {
837 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
838 }
839 bool isMSA128AsmReg() const {
840 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
841 }
842 bool isMSACtrlAsmReg() const {
843 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
844 }
845
846 /// getStartLoc - Get the location of the first token of this operand.
847 SMLoc getStartLoc() const override { return StartLoc; }
848 /// getEndLoc - Get the location of the last token of this operand.
849 SMLoc getEndLoc() const override { return EndLoc; }
850
851 virtual ~MipsOperand() {
852 switch (Kind) {
853 case k_Immediate:
854 break;
855 case k_Memory:
856 delete Mem.Base;
857 break;
858 case k_PhysRegister:
859 case k_RegisterIndex:
860 case k_Token:
861 break;
862 }
863 }
864
865 void print(raw_ostream &OS) const override {
866 switch (Kind) {
867 case k_Immediate:
868 OS << "Imm<";
869 Imm.Val->print(OS);
870 OS << ">";
871 break;
872 case k_Memory:
873 OS << "Mem<";
874 Mem.Base->print(OS);
875 OS << ", ";
876 Mem.Off->print(OS);
877 OS << ">";
878 break;
879 case k_PhysRegister:
880 OS << "PhysReg<" << PhysReg.Num << ">";
881 break;
882 case k_RegisterIndex:
883 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
884 break;
885 case k_Token:
886 OS << Tok.Data;
887 break;
888 }
889 }
890}; // class MipsOperand
891} // namespace
892
893namespace llvm {
894extern const MCInstrDesc MipsInsts[];
895}
896static const MCInstrDesc &getInstDesc(unsigned Opcode) {
897 return MipsInsts[Opcode];
898}
899
900bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
901 SmallVectorImpl<MCInst> &Instructions) {
902 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
903
904 Inst.setLoc(IDLoc);
905
906 if (MCID.isBranch() || MCID.isCall()) {
907 const unsigned Opcode = Inst.getOpcode();
908 MCOperand Offset;
909
910 switch (Opcode) {
911 default:
912 break;
913 case Mips::BEQ:
914 case Mips::BNE:
915 case Mips::BEQ_MM:
916 case Mips::BNE_MM:
917 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
918 Offset = Inst.getOperand(2);
919 if (!Offset.isImm())
920 break; // We'll deal with this situation later on when applying fixups.
921 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
922 return Error(IDLoc, "branch target out of range");
923 if (OffsetToAlignment(Offset.getImm(),
924 1LL << (inMicroMipsMode() ? 1 : 2)))
925 return Error(IDLoc, "branch to misaligned address");
926 break;
927 case Mips::BGEZ:
928 case Mips::BGTZ:
929 case Mips::BLEZ:
930 case Mips::BLTZ:
931 case Mips::BGEZAL:
932 case Mips::BLTZAL:
933 case Mips::BC1F:
934 case Mips::BC1T:
935 case Mips::BGEZ_MM:
936 case Mips::BGTZ_MM:
937 case Mips::BLEZ_MM:
938 case Mips::BLTZ_MM:
939 case Mips::BGEZAL_MM:
940 case Mips::BLTZAL_MM:
941 case Mips::BC1F_MM:
942 case Mips::BC1T_MM:
943 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
944 Offset = Inst.getOperand(1);
945 if (!Offset.isImm())
946 break; // We'll deal with this situation later on when applying fixups.
947 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
948 return Error(IDLoc, "branch target out of range");
949 if (OffsetToAlignment(Offset.getImm(),
950 1LL << (inMicroMipsMode() ? 1 : 2)))
951 return Error(IDLoc, "branch to misaligned address");
952 break;
953 }
954 }
955
956 // SSNOP is deprecated on MIPS32r6/MIPS64r6
957 // We still accept it but it is a normal nop.
958 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
959 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
960 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
961 "nop instruction");
962 }
963
964 if (MCID.hasDelaySlot() && Options.isReorder()) {
965 // If this instruction has a delay slot and .set reorder is active,
966 // emit a NOP after it.
967 Instructions.push_back(Inst);
968 MCInst NopInst;
969 NopInst.setOpcode(Mips::SLL);
970 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
971 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
972 NopInst.addOperand(MCOperand::CreateImm(0));
973 Instructions.push_back(NopInst);
974 return false;
975 }
976
977 if (MCID.mayLoad() || MCID.mayStore()) {
978 // Check the offset of memory operand, if it is a symbol
979 // reference or immediate we may have to expand instructions.
980 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
981 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
982 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
983 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
984 MCOperand &Op = Inst.getOperand(i);
985 if (Op.isImm()) {
986 int MemOffset = Op.getImm();
987 if (MemOffset < -32768 || MemOffset > 32767) {
988 // Offset can't exceed 16bit value.
989 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
990 return false;
991 }
992 } else if (Op.isExpr()) {
993 const MCExpr *Expr = Op.getExpr();
994 if (Expr->getKind() == MCExpr::SymbolRef) {
995 const MCSymbolRefExpr *SR =
996 static_cast<const MCSymbolRefExpr *>(Expr);
997 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
998 // Expand symbol.
999 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
1000 return false;
1001 }
1002 } else if (!isEvaluated(Expr)) {
1003 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
1004 return false;
1005 }
1006 }
1007 }
1008 } // for
1009 } // if load/store
1010
1011 if (needsExpansion(Inst))
1012 return expandInstruction(Inst, IDLoc, Instructions);
1013 else
1014 Instructions.push_back(Inst);
1015
1016 return false;
1017}
1018
1019bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1020
1021 switch (Inst.getOpcode()) {
1022 case Mips::LoadImm32Reg:
1023 case Mips::LoadAddr32Imm:
1024 case Mips::LoadAddr32Reg:
1025 case Mips::LoadImm64Reg:
1026 return true;
1027 default:
1028 return false;
1029 }
1030}
1031
1032bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
1033 SmallVectorImpl<MCInst> &Instructions) {
1034 switch (Inst.getOpcode()) {
1035 default:
1036 assert(0 && "unimplemented expansion");
1037 return true;
1038 case Mips::LoadImm32Reg:
1039 return expandLoadImm(Inst, IDLoc, Instructions);
1040 case Mips::LoadImm64Reg:
1041 if (!isGP64bit()) {
1042 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1043 return true;
1044 }
1045 return expandLoadImm(Inst, IDLoc, Instructions);
1046 case Mips::LoadAddr32Imm:
1047 return expandLoadAddressImm(Inst, IDLoc, Instructions);
1048 case Mips::LoadAddr32Reg:
1049 return expandLoadAddressReg(Inst, IDLoc, Instructions);
1050 }
1051}
1052
1053namespace {
1054template <int Shift, bool PerformShift>
1055void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1056 SmallVectorImpl<MCInst> &Instructions) {
1057 MCInst tmpInst;
1058 if (PerformShift) {
1059 tmpInst.setOpcode(Mips::DSLL);
1060 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1061 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1062 tmpInst.addOperand(MCOperand::CreateImm(16));
1063 tmpInst.setLoc(IDLoc);
1064 Instructions.push_back(tmpInst);
1065 tmpInst.clear();
1066 }
1067 tmpInst.setOpcode(Mips::ORi);
1068 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1069 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1070 tmpInst.addOperand(
1071 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)));
1072 tmpInst.setLoc(IDLoc);
1073 Instructions.push_back(tmpInst);
1074}
1075}
1076
1077bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
1078 SmallVectorImpl<MCInst> &Instructions) {
1079 MCInst tmpInst;
1080 const MCOperand &ImmOp = Inst.getOperand(1);
1081 assert(ImmOp.isImm() && "expected immediate operand kind");
1082 const MCOperand &RegOp = Inst.getOperand(0);
1083 assert(RegOp.isReg() && "expected register operand kind");
1084
1085 int64_t ImmValue = ImmOp.getImm();
1086 tmpInst.setLoc(IDLoc);
1087 // FIXME: gas has a special case for values that are 000...1111, which
1088 // becomes a li -1 and then a dsrl
1089 if (0 <= ImmValue && ImmValue <= 65535) {
1090 // For 0 <= j <= 65535.
1091 // li d,j => ori d,$zero,j
1092 tmpInst.setOpcode(Mips::ORi);
1093 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1094 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1095 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1096 Instructions.push_back(tmpInst);
1097 } else if (ImmValue < 0 && ImmValue >= -32768) {
1098 // For -32768 <= j < 0.
1099 // li d,j => addiu d,$zero,j
1100 tmpInst.setOpcode(Mips::ADDiu);
1101 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1102 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1103 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1104 Instructions.push_back(tmpInst);
1105 } else if ((ImmValue & 0xffffffff) == ImmValue) {
1106 // For any value of j that is representable as a 32-bit integer, create
1107 // a sequence of:
1108 // li d,j => lui d,hi16(j)
1109 // ori d,d,lo16(j)
1110 tmpInst.setOpcode(Mips::LUi);
1111 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1112 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1113 Instructions.push_back(tmpInst);
1114 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1115 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
1116 if (!isGP64bit()) {
1117 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1118 return true;
1119 }
1120
1121 // <------- lo32 ------>
1122 // <------- hi32 ------>
1123 // <- hi16 -> <- lo16 ->
1124 // _________________________________
1125 // | | | |
1126 // | 16-bytes | 16-bytes | 16-bytes |
1127 // |__________|__________|__________|
1128 //
1129 // For any value of j that is representable as a 48-bit integer, create
1130 // a sequence of:
1131 // li d,j => lui d,hi16(j)
1132 // ori d,d,hi16(lo32(j))
1133 // dsll d,d,16
1134 // ori d,d,lo16(lo32(j))
1135 tmpInst.setOpcode(Mips::LUi);
1136 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1137 tmpInst.addOperand(
1138 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
1139 Instructions.push_back(tmpInst);
1140 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1141 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1142 } else {
1143 if (!isGP64bit()) {
1144 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1145 return true;
1146 }
1147
1148 // <------- hi32 ------> <------- lo32 ------>
1149 // <- hi16 -> <- lo16 ->
1150 // ___________________________________________
1151 // | | | | |
1152 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1153 // |__________|__________|__________|__________|
1154 //
1155 // For any value of j that isn't representable as a 48-bit integer.
1156 // li d,j => lui d,hi16(j)
1157 // ori d,d,lo16(hi32(j))
1158 // dsll d,d,16
1159 // ori d,d,hi16(lo32(j))
1160 // dsll d,d,16
1161 // ori d,d,lo16(lo32(j))
1162 tmpInst.setOpcode(Mips::LUi);
1163 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1164 tmpInst.addOperand(
1165 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1166 Instructions.push_back(tmpInst);
1167 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1168 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1169 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1170 }
1171 return false;
1172}
1173
1174bool
1175MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1176 SmallVectorImpl<MCInst> &Instructions) {
1177 MCInst tmpInst;
1178 const MCOperand &ImmOp = Inst.getOperand(2);
1179 assert(ImmOp.isImm() && "expected immediate operand kind");
1180 const MCOperand &SrcRegOp = Inst.getOperand(1);
1181 assert(SrcRegOp.isReg() && "expected register operand kind");
1182 const MCOperand &DstRegOp = Inst.getOperand(0);
1183 assert(DstRegOp.isReg() && "expected register operand kind");
1184 int ImmValue = ImmOp.getImm();
1185 if (-32768 <= ImmValue && ImmValue <= 65535) {
1186 // For -32768 <= j <= 65535.
1187 // la d,j(s) => addiu d,s,j
1188 tmpInst.setOpcode(Mips::ADDiu);
1189 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1190 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1191 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1192 Instructions.push_back(tmpInst);
1193 } else {
1194 // For any other value of j that is representable as a 32-bit integer.
1195 // la d,j(s) => lui d,hi16(j)
1196 // ori d,d,lo16(j)
1197 // addu d,d,s
1198 tmpInst.setOpcode(Mips::LUi);
1199 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1200 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1201 Instructions.push_back(tmpInst);
1202 tmpInst.clear();
1203 tmpInst.setOpcode(Mips::ORi);
1204 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1205 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1206 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1207 Instructions.push_back(tmpInst);
1208 tmpInst.clear();
1209 tmpInst.setOpcode(Mips::ADDu);
1210 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1211 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1212 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1213 Instructions.push_back(tmpInst);
1214 }
1215 return false;
1216}
1217
1218bool
1219MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1220 SmallVectorImpl<MCInst> &Instructions) {
1221 MCInst tmpInst;
1222 const MCOperand &ImmOp = Inst.getOperand(1);
1223 assert(ImmOp.isImm() && "expected immediate operand kind");
1224 const MCOperand &RegOp = Inst.getOperand(0);
1225 assert(RegOp.isReg() && "expected register operand kind");
1226 int ImmValue = ImmOp.getImm();
1227 if (-32768 <= ImmValue && ImmValue <= 65535) {
1228 // For -32768 <= j <= 65535.
1229 // la d,j => addiu d,$zero,j
1230 tmpInst.setOpcode(Mips::ADDiu);
1231 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1232 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1233 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1234 Instructions.push_back(tmpInst);
1235 } else {
1236 // For any other value of j that is representable as a 32-bit integer.
1237 // la d,j => lui d,hi16(j)
1238 // ori d,d,lo16(j)
1239 tmpInst.setOpcode(Mips::LUi);
1240 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1241 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1242 Instructions.push_back(tmpInst);
1243 tmpInst.clear();
1244 tmpInst.setOpcode(Mips::ORi);
1245 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1246 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1247 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1248 Instructions.push_back(tmpInst);
1249 }
1250 return false;
1251}
1252
1253void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
1254 SmallVectorImpl<MCInst> &Instructions,
1255 bool isLoad, bool isImmOpnd) {
1256 const MCSymbolRefExpr *SR;
1257 MCInst TempInst;
1258 unsigned ImmOffset, HiOffset, LoOffset;
1259 const MCExpr *ExprOffset;
1260 unsigned TmpRegNum;
1261 // 1st operand is either the source or destination register.
1262 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1263 unsigned RegOpNum = Inst.getOperand(0).getReg();
1264 // 2nd operand is the base register.
1265 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1266 unsigned BaseRegNum = Inst.getOperand(1).getReg();
1267 // 3rd operand is either an immediate or expression.
1268 if (isImmOpnd) {
1269 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1270 ImmOffset = Inst.getOperand(2).getImm();
1271 LoOffset = ImmOffset & 0x0000ffff;
1272 HiOffset = (ImmOffset & 0xffff0000) >> 16;
1273 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
1274 if (LoOffset & 0x8000)
1275 HiOffset++;
1276 } else
1277 ExprOffset = Inst.getOperand(2).getExpr();
1278 // All instructions will have the same location.
1279 TempInst.setLoc(IDLoc);
1280 // These are some of the types of expansions we perform here:
1281 // 1) lw $8, sym => lui $8, %hi(sym)
1282 // lw $8, %lo(sym)($8)
1283 // 2) lw $8, offset($9) => lui $8, %hi(offset)
1284 // add $8, $8, $9
1285 // lw $8, %lo(offset)($9)
1286 // 3) lw $8, offset($8) => lui $at, %hi(offset)
1287 // add $at, $at, $8
1288 // lw $8, %lo(offset)($at)
1289 // 4) sw $8, sym => lui $at, %hi(sym)
1290 // sw $8, %lo(sym)($at)
1291 // 5) sw $8, offset($8) => lui $at, %hi(offset)
1292 // add $at, $at, $8
1293 // sw $8, %lo(offset)($at)
1294 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
1295 // ldc1 $f0, %lo(sym)($at)
1296 //
1297 // For load instructions we can use the destination register as a temporary
1298 // if base and dst are different (examples 1 and 2) and if the base register
1299 // is general purpose otherwise we must use $at (example 6) and error if it's
1300 // not available. For stores we must use $at (examples 4 and 5) because we
1301 // must not clobber the source register setting up the offset.
1302 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
1303 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
1304 unsigned RegClassIDOp0 =
1305 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
1306 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
1307 (RegClassIDOp0 == Mips::GPR64RegClassID);
1308 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
1309 TmpRegNum = RegOpNum;
1310 else {
1311 int AT = getATReg(IDLoc);
1312 // At this point we need AT to perform the expansions and we exit if it is
1313 // not available.
1314 if (!AT)
1315 return;
1316 TmpRegNum = getReg(
1317 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
1318 }
1319
1320 TempInst.setOpcode(Mips::LUi);
1321 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1322 if (isImmOpnd)
1323 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1324 else {
1325 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
1326 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
1327 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1328 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1329 getContext());
1330 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
1331 } else {
1332 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
1333 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
1334 }
1335 }
1336 // Add the instruction to the list.
1337 Instructions.push_back(TempInst);
1338 // Prepare TempInst for next instruction.
1339 TempInst.clear();
1340 // Add temp register to base.
1341 TempInst.setOpcode(Mips::ADDu);
1342 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1343 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1344 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1345 Instructions.push_back(TempInst);
1346 TempInst.clear();
1347 // And finally, create original instruction with low part
1348 // of offset and new base.
1349 TempInst.setOpcode(Inst.getOpcode());
1350 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1351 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1352 if (isImmOpnd)
1353 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1354 else {
1355 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
1356 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1357 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1358 getContext());
1359 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
1360 } else {
1361 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
1362 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
1363 }
1364 }
1365 Instructions.push_back(TempInst);
1366 TempInst.clear();
1367}
1368
1369unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1370 // As described by the Mips32r2 spec, the registers Rd and Rs for
1371 // jalr.hb must be different.
1372 unsigned Opcode = Inst.getOpcode();
1373
1374 if (Opcode == Mips::JALR_HB &&
1375 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
1376 return Match_RequiresDifferentSrcAndDst;
1377
1378 return Match_Success;
1379}
1380
1381bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1382 OperandVector &Operands,
1383 MCStreamer &Out,
1384 unsigned &ErrorInfo,
1385 bool MatchingInlineAsm) {
1386
1387 MCInst Inst;
1388 SmallVector<MCInst, 8> Instructions;
1389 unsigned MatchResult =
1390 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
1391
1392 switch (MatchResult) {
1393 default:
1394 break;
1395 case Match_Success: {
1396 if (processInstruction(Inst, IDLoc, Instructions))
1397 return true;
1398 for (unsigned i = 0; i < Instructions.size(); i++)
1399 Out.EmitInstruction(Instructions[i], STI);
1400 return false;
1401 }
1402 case Match_MissingFeature:
1403 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1404 return true;
1405 case Match_InvalidOperand: {
1406 SMLoc ErrorLoc = IDLoc;
1407 if (ErrorInfo != ~0U) {
1408 if (ErrorInfo >= Operands.size())
1409 return Error(IDLoc, "too few operands for instruction");
1410
1411 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
1412 if (ErrorLoc == SMLoc())
1413 ErrorLoc = IDLoc;
1414 }
1415
1416 return Error(ErrorLoc, "invalid operand for instruction");
1417 }
1418 case Match_MnemonicFail:
1419 return Error(IDLoc, "invalid instruction");
1420 case Match_RequiresDifferentSrcAndDst:
1421 return Error(IDLoc, "source and destination must be different");
1422 }
1423 return true;
1424}
1425
1426void MipsAsmParser::WarnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
1427 if ((RegIndex != 0) && ((int)Options.getATRegNum() == RegIndex)) {
1428 if (RegIndex == 1)
1429 Warning(Loc, "Used $at without \".set noat\"");
1430 else
1431 Warning(Loc, Twine("Used $") + Twine(RegIndex) + " with \".set at=$" +
1432 Twine(RegIndex) + "\"");
1433 }
1434}
1435
1436int MipsAsmParser::matchCPURegisterName(StringRef Name) {
1437 int CC;
1438
1439 CC = StringSwitch<unsigned>(Name)
1440 .Case("zero", 0)
1441 .Case("at", 1)
1442 .Case("a0", 4)
1443 .Case("a1", 5)
1444 .Case("a2", 6)
1445 .Case("a3", 7)
1446 .Case("v0", 2)
1447 .Case("v1", 3)
1448 .Case("s0", 16)
1449 .Case("s1", 17)
1450 .Case("s2", 18)
1451 .Case("s3", 19)
1452 .Case("s4", 20)
1453 .Case("s5", 21)
1454 .Case("s6", 22)
1455 .Case("s7", 23)
1456 .Case("k0", 26)
1457 .Case("k1", 27)
1458 .Case("gp", 28)
1459 .Case("sp", 29)
1460 .Case("fp", 30)
1461 .Case("s8", 30)
1462 .Case("ra", 31)
1463 .Case("t0", 8)
1464 .Case("t1", 9)
1465 .Case("t2", 10)
1466 .Case("t3", 11)
1467 .Case("t4", 12)
1468 .Case("t5", 13)
1469 .Case("t6", 14)
1470 .Case("t7", 15)
1471 .Case("t8", 24)
1472 .Case("t9", 25)
1473 .Default(-1);
1474
1475 if (isABI_N32() || isABI_N64()) {
1476 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1477 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1478 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1479 if (8 <= CC && CC <= 11)
1480 CC += 4;
1481
1482 if (CC == -1)
1483 CC = StringSwitch<unsigned>(Name)
1484 .Case("a4", 8)
1485 .Case("a5", 9)
1486 .Case("a6", 10)
1487 .Case("a7", 11)
1488 .Case("kt0", 26)
1489 .Case("kt1", 27)
1490 .Default(-1);
1491 }
1492
1493 return CC;
1494}
1495
1496int MipsAsmParser::matchFPURegisterName(StringRef Name) {
1497
1498 if (Name[0] == 'f') {
1499 StringRef NumString = Name.substr(1);
1500 unsigned IntVal;
1501 if (NumString.getAsInteger(10, IntVal))
1502 return -1; // This is not an integer.
1503 if (IntVal > 31) // Maximum index for fpu register.
1504 return -1;
1505 return IntVal;
1506 }
1507 return -1;
1508}
1509
1510int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
1511
1512 if (Name.startswith("fcc")) {
1513 StringRef NumString = Name.substr(3);
1514 unsigned IntVal;
1515 if (NumString.getAsInteger(10, IntVal))
1516 return -1; // This is not an integer.
1517 if (IntVal > 7) // There are only 8 fcc registers.
1518 return -1;
1519 return IntVal;
1520 }
1521 return -1;
1522}
1523
1524int MipsAsmParser::matchACRegisterName(StringRef Name) {
1525
1526 if (Name.startswith("ac")) {
1527 StringRef NumString = Name.substr(2);
1528 unsigned IntVal;
1529 if (NumString.getAsInteger(10, IntVal))
1530 return -1; // This is not an integer.
1531 if (IntVal > 3) // There are only 3 acc registers.
1532 return -1;
1533 return IntVal;
1534 }
1535 return -1;
1536}
1537
1538int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
1539 unsigned IntVal;
1540
1541 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
1542 return -1;
1543
1544 if (IntVal > 31)
1545 return -1;
1546
1547 return IntVal;
1548}
1549
1550int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
1551 int CC;
1552
1553 CC = StringSwitch<unsigned>(Name)
1554 .Case("msair", 0)
1555 .Case("msacsr", 1)
1556 .Case("msaaccess", 2)
1557 .Case("msasave", 3)
1558 .Case("msamodify", 4)
1559 .Case("msarequest", 5)
1560 .Case("msamap", 6)
1561 .Case("msaunmap", 7)
1562 .Default(-1);
1563
1564 return CC;
1565}
1566
1567bool MipsAssemblerOptions::setATReg(unsigned Reg) {
1568 if (Reg > 31)
1569 return false;
1570
1571 aTReg = Reg;
1572 return true;
1573}
1574
1575int MipsAsmParser::getATReg(SMLoc Loc) {
1576 int AT = Options.getATRegNum();
1577 if (AT == 0)
1578 reportParseError(Loc,
1579 "Pseudo instruction requires $at, which is not available");
1580 return AT;
1581}
1582
1583unsigned MipsAsmParser::getReg(int RC, int RegNo) {
1584 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
1585}
1586
1587unsigned MipsAsmParser::getGPR(int RegNo) {
1588 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
1589 RegNo);
1590}
1591
1592int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
1593 if (RegNum >
1594 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
1595 return -1;
1596
1597 return getReg(RegClass, RegNum);
1598}
1599
1600bool MipsAsmParser::ParseOperand(OperandVector &Operands, StringRef Mnemonic) {
1601 DEBUG(dbgs() << "ParseOperand\n");
1602
1603 // Check if the current operand has a custom associated parser, if so, try to
1604 // custom parse the operand, or fallback to the general approach.
1605 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1606 if (ResTy == MatchOperand_Success)
1607 return false;
1608 // If there wasn't a custom match, try the generic matcher below. Otherwise,
1609 // there was a match, but an error occurred, in which case, just return that
1610 // the operand parsing failed.
1611 if (ResTy == MatchOperand_ParseFail)
1612 return true;
1613
1614 DEBUG(dbgs() << ".. Generic Parser\n");
1615
1616 switch (getLexer().getKind()) {
1617 default:
1618 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1619 return true;
1620 case AsmToken::Dollar: {
1621 // Parse the register.
1622 SMLoc S = Parser.getTok().getLoc();
1623
1624 // Almost all registers have been parsed by custom parsers. There is only
1625 // one exception to this. $zero (and it's alias $0) will reach this point
1626 // for div, divu, and similar instructions because it is not an operand
1627 // to the instruction definition but an explicit register. Special case
1628 // this situation for now.
1629 if (ParseAnyRegister(Operands) != MatchOperand_NoMatch)
1630 return false;
1631
1632 // Maybe it is a symbol reference.
1633 StringRef Identifier;
1634 if (Parser.parseIdentifier(Identifier))
1635 return true;
1636
1637 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1638 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
1639 // Otherwise create a symbol reference.
1640 const MCExpr *Res =
1641 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
1642
1643 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
1644 return false;
1645 }
1646 // Else drop to expression parsing.
1647 case AsmToken::LParen:
1648 case AsmToken::Minus:
1649 case AsmToken::Plus:
1650 case AsmToken::Integer:
1651 case AsmToken::Tilde:
1652 case AsmToken::String: {
1653 DEBUG(dbgs() << ".. generic integer\n");
1654 OperandMatchResultTy ResTy = ParseImm(Operands);
1655 return ResTy != MatchOperand_Success;
1656 }
1657 case AsmToken::Percent: {
1658 // It is a symbol reference or constant expression.
1659 const MCExpr *IdVal;
1660 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
1661 if (parseRelocOperand(IdVal))
1662 return true;
1663
1664 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1665
1666 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
1667 return false;
1668 } // case AsmToken::Percent
1669 } // switch(getLexer().getKind())
1670 return true;
1671}
1672
1673const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
1674 StringRef RelocStr) {
1675 const MCExpr *Res;
1676 // Check the type of the expression.
1677 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
1678 // It's a constant, evaluate reloc value.
1679 int16_t Val;
1680 switch (getVariantKind(RelocStr)) {
1681 case MCSymbolRefExpr::VK_Mips_ABS_LO:
1682 // Get the 1st 16-bits.
1683 Val = MCE->getValue() & 0xffff;
1684 break;
1685 case MCSymbolRefExpr::VK_Mips_ABS_HI:
1686 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
1687 // 16 bits being negative.
1688 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
1689 break;
1690 case MCSymbolRefExpr::VK_Mips_HIGHER:
1691 // Get the 3rd 16-bits.
1692 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
1693 break;
1694 case MCSymbolRefExpr::VK_Mips_HIGHEST:
1695 // Get the 4th 16-bits.
1696 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
1697 break;
1698 default:
1699 report_fatal_error("Unsupported reloc value!");
1700 }
1701 return MCConstantExpr::Create(Val, getContext());
1702 }
1703
1704 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
1705 // It's a symbol, create a symbolic expression from the symbol.
1706 StringRef Symbol = MSRE->getSymbol().getName();
1707 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
1708 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
1709 return Res;
1710 }
1711
1712 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1713 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
1714
1715 // Try to create target expression.
1716 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
1717 return MipsMCExpr::Create(VK, Expr, getContext());
1718
1719 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1720 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
1721 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1722 return Res;
1723 }
1724
1725 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
1726 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1727 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1728 return Res;
1729 }
1730 // Just return the original expression.
1731 return Expr;
1732}
1733
1734bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1735
1736 switch (Expr->getKind()) {
1737 case MCExpr::Constant:
1738 return true;
1739 case MCExpr::SymbolRef:
1740 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1741 case MCExpr::Binary:
1742 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1743 if (!isEvaluated(BE->getLHS()))
1744 return false;
1745 return isEvaluated(BE->getRHS());
1746 }
1747 case MCExpr::Unary:
1748 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
1749 case MCExpr::Target:
1750 return true;
1751 }
1752 return false;
1753}
1754
1755bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
1756 Parser.Lex(); // Eat the % token.
1757 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
1758 if (Tok.isNot(AsmToken::Identifier))
1759 return true;
1760
1761 std::string Str = Tok.getIdentifier().str();
1762
1763 Parser.Lex(); // Eat the identifier.
1764 // Now make an expression from the rest of the operand.
1765 const MCExpr *IdVal;
1766 SMLoc EndLoc;
1767
1768 if (getLexer().getKind() == AsmToken::LParen) {
1769 while (1) {
1770 Parser.Lex(); // Eat the '(' token.
1771 if (getLexer().getKind() == AsmToken::Percent) {
1772 Parser.Lex(); // Eat the % token.
1773 const AsmToken &nextTok = Parser.getTok();
1774 if (nextTok.isNot(AsmToken::Identifier))
1775 return true;
1776 Str += "(%";
1777 Str += nextTok.getIdentifier();
1778 Parser.Lex(); // Eat the identifier.
1779 if (getLexer().getKind() != AsmToken::LParen)
1780 return true;
1781 } else
1782 break;
1783 }
1784 if (getParser().parseParenExpression(IdVal, EndLoc))
1785 return true;
1786
1787 while (getLexer().getKind() == AsmToken::RParen)
1788 Parser.Lex(); // Eat the ')' token.
1789
1790 } else
1791 return true; // Parenthesis must follow the relocation operand.
1792
1793 Res = evaluateRelocExpr(IdVal, Str);
1794 return false;
1795}
1796
1797bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1798 SMLoc &EndLoc) {
1799 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
1800 OperandMatchResultTy ResTy = ParseAnyRegister(Operands);
1801 if (ResTy == MatchOperand_Success) {
1802 assert(Operands.size() == 1);
1803 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
1804 StartLoc = Operand.getStartLoc();
1805 EndLoc = Operand.getEndLoc();
1806
1807 // AFAIK, we only support numeric registers and named GPR's in CFI
1808 // directives.
1809 // Don't worry about eating tokens before failing. Using an unrecognised
1810 // register is a parse error.
1811 if (Operand.isGPRAsmReg()) {
1812 // Resolve to GPR32 or GPR64 appropriately.
1813 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
1814 }
1815
1816 return (RegNo == (unsigned)-1);
1817 }
1818
1819 assert(Operands.size() == 0);
1820 return (RegNo == (unsigned)-1);
1821}
1822
1823bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
1824 SMLoc S;
1825 bool Result = true;
1826
1827 while (getLexer().getKind() == AsmToken::LParen)
1828 Parser.Lex();
1829
1830 switch (getLexer().getKind()) {
1831 default:
1832 return true;
1833 case AsmToken::Identifier:
1834 case AsmToken::LParen:
1835 case AsmToken::Integer:
1836 case AsmToken::Minus:
1837 case AsmToken::Plus:
1838 if (isParenExpr)
1839 Result = getParser().parseParenExpression(Res, S);
1840 else
1841 Result = (getParser().parseExpression(Res));
1842 while (getLexer().getKind() == AsmToken::RParen)
1843 Parser.Lex();
1844 break;
1845 case AsmToken::Percent:
1846 Result = parseRelocOperand(Res);
1847 }
1848 return Result;
1849}
1850
1851MipsAsmParser::OperandMatchResultTy
1852MipsAsmParser::parseMemOperand(OperandVector &Operands) {
1853 DEBUG(dbgs() << "parseMemOperand\n");
1854 const MCExpr *IdVal = nullptr;
1855 SMLoc S;
1856 bool isParenExpr = false;
1857 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
1858 // First operand is the offset.
1859 S = Parser.getTok().getLoc();
1860
1861 if (getLexer().getKind() == AsmToken::LParen) {
1862 Parser.Lex();
1863 isParenExpr = true;
1864 }
1865
1866 if (getLexer().getKind() != AsmToken::Dollar) {
1867 if (parseMemOffset(IdVal, isParenExpr))
1868 return MatchOperand_ParseFail;
1869
1870 const AsmToken &Tok = Parser.getTok(); // Get the next token.
1871 if (Tok.isNot(AsmToken::LParen)) {
1872 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
1873 if (Mnemonic.getToken() == "la") {
1874 SMLoc E =
1875 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1876 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
1877 return MatchOperand_Success;
1878 }
1879 if (Tok.is(AsmToken::EndOfStatement)) {
1880 SMLoc E =
1881 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1882
1883 // Zero register assumed, add a memory operand with ZERO as its base.
1884 // "Base" will be managed by k_Memory.
1885 auto Base = MipsOperand::CreateGPRReg(0, getContext().getRegisterInfo(),
1886 S, E, *this);
1887 Operands.push_back(
1888 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
1889 return MatchOperand_Success;
1890 }
1891 Error(Parser.getTok().getLoc(), "'(' expected");
1892 return MatchOperand_ParseFail;
1893 }
1894
1895 Parser.Lex(); // Eat the '(' token.
1896 }
1897
1898 Res = ParseAnyRegister(Operands);
1899 if (Res != MatchOperand_Success)
1900 return Res;
1901
1902 if (Parser.getTok().isNot(AsmToken::RParen)) {
1903 Error(Parser.getTok().getLoc(), "')' expected");
1904 return MatchOperand_ParseFail;
1905 }
1906
1907 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1908
1909 Parser.Lex(); // Eat the ')' token.
1910
1911 if (!IdVal)
1912 IdVal = MCConstantExpr::Create(0, getContext());
1913
1914 // Replace the register operand with the memory operand.
1915 std::unique_ptr<MipsOperand> op(
1916 static_cast<MipsOperand *>(Operands.back().release()));
1917 // Remove the register from the operands.
1918 // "op" will be managed by k_Memory.
1919 Operands.pop_back();
1920 // Add the memory operand.
1921 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
1922 int64_t Imm;
1923 if (IdVal->EvaluateAsAbsolute(Imm))
1924 IdVal = MCConstantExpr::Create(Imm, getContext());
1925 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
1926 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
1927 getContext());
1928 }
1929
1930 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
1931 return MatchOperand_Success;
1932}
1933
1934bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
1935
1936 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
1937 if (Sym) {
1938 SMLoc S = Parser.getTok().getLoc();
1939 const MCExpr *Expr;
1940 if (Sym->isVariable())
1941 Expr = Sym->getVariableValue();
1942 else
1943 return false;
1944 if (Expr->getKind() == MCExpr::SymbolRef) {
1945 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
1946 const StringRef DefSymbol = Ref->getSymbol().getName();
1947 if (DefSymbol.startswith("$")) {
1948 OperandMatchResultTy ResTy =
1949 MatchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
1950 if (ResTy == MatchOperand_Success) {
1951 Parser.Lex();
1952 return true;
1953 } else if (ResTy == MatchOperand_ParseFail)
1954 llvm_unreachable("Should never ParseFail");
1955 return false;
1956 }
1957 } else if (Expr->getKind() == MCExpr::Constant) {
1958 Parser.Lex();
1959 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
1960 Operands.push_back(
1961 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
1962 return true;
1963 }
1964 }
1965 return false;
1966}
1967
1968MipsAsmParser::OperandMatchResultTy
1969MipsAsmParser::MatchAnyRegisterNameWithoutDollar(OperandVector &Operands,
1970 StringRef Identifier,
1971 SMLoc S) {
1972 int Index = matchCPURegisterName(Identifier);
1973 if (Index != -1) {
1974 Operands.push_back(MipsOperand::CreateGPRReg(
1975 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1976 return MatchOperand_Success;
1977 }
1978
1979 Index = matchFPURegisterName(Identifier);
1980 if (Index != -1) {
1981 Operands.push_back(MipsOperand::CreateFGRReg(
1982 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1983 return MatchOperand_Success;
1984 }
1985
1986 Index = matchFCCRegisterName(Identifier);
1987 if (Index != -1) {
1988 Operands.push_back(MipsOperand::CreateFCCReg(
1989 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1990 return MatchOperand_Success;
1991 }
1992
1993 Index = matchACRegisterName(Identifier);
1994 if (Index != -1) {
1995 Operands.push_back(MipsOperand::CreateACCReg(
1996 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1997 return MatchOperand_Success;
1998 }
1999
2000 Index = matchMSA128RegisterName(Identifier);
2001 if (Index != -1) {
2002 Operands.push_back(MipsOperand::CreateMSA128Reg(
2003 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2004 return MatchOperand_Success;
2005 }
2006
2007 Index = matchMSA128CtrlRegisterName(Identifier);
2008 if (Index != -1) {
2009 Operands.push_back(MipsOperand::CreateMSACtrlReg(
2010 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2011 return MatchOperand_Success;
2012 }
2013
2014 return MatchOperand_NoMatch;
2015}
2016
2017MipsAsmParser::OperandMatchResultTy
2018MipsAsmParser::MatchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
2019 auto Token = Parser.getLexer().peekTok(false);
2020
2021 if (Token.is(AsmToken::Identifier)) {
2022 DEBUG(dbgs() << ".. identifier\n");
2023 StringRef Identifier = Token.getIdentifier();
2024 OperandMatchResultTy ResTy =
2025 MatchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
2026 return ResTy;
2027 } else if (Token.is(AsmToken::Integer)) {
2028 DEBUG(dbgs() << ".. integer\n");
2029 Operands.push_back(MipsOperand::CreateNumericReg(
2030 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2031 *this));
2032 return MatchOperand_Success;
2033 }
2034
2035 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2036
2037 return MatchOperand_NoMatch;
2038}
2039
2040MipsAsmParser::OperandMatchResultTy
2041MipsAsmParser::ParseAnyRegister(OperandVector &Operands) {
2042 DEBUG(dbgs() << "ParseAnyRegister\n");
2043
2044 auto Token = Parser.getTok();
2045
2046 SMLoc S = Token.getLoc();
2047
2048 if (Token.isNot(AsmToken::Dollar)) {
2049 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2050 if (Token.is(AsmToken::Identifier)) {
2051 if (searchSymbolAlias(Operands))
2052 return MatchOperand_Success;
2053 }
2054 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2055 return MatchOperand_NoMatch;
2056 }
2057 DEBUG(dbgs() << ".. $\n");
2058
2059 OperandMatchResultTy ResTy = MatchAnyRegisterWithoutDollar(Operands, S);
2060 if (ResTy == MatchOperand_Success) {
2061 Parser.Lex(); // $
2062 Parser.Lex(); // identifier
2063 }
2064 return ResTy;
2065}
2066
2067MipsAsmParser::OperandMatchResultTy
2068MipsAsmParser::ParseImm(OperandVector &Operands) {
2069 switch (getLexer().getKind()) {
2070 default:
2071 return MatchOperand_NoMatch;
2072 case AsmToken::LParen:
2073 case AsmToken::Minus:
2074 case AsmToken::Plus:
2075 case AsmToken::Integer:
2076 case AsmToken::Tilde:
2077 case AsmToken::String:
2078 break;
2079 }
2080
2081 const MCExpr *IdVal;
2082 SMLoc S = Parser.getTok().getLoc();
2083 if (getParser().parseExpression(IdVal))
2084 return MatchOperand_ParseFail;
2085
2086 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2087 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2088 return MatchOperand_Success;
2089}
2090
2091MipsAsmParser::OperandMatchResultTy
2092MipsAsmParser::ParseJumpTarget(OperandVector &Operands) {
2093 DEBUG(dbgs() << "ParseJumpTarget\n");
2094
2095 SMLoc S = getLexer().getLoc();
2096
2097 // Integers and expressions are acceptable
2098 OperandMatchResultTy ResTy = ParseImm(Operands);
2099 if (ResTy != MatchOperand_NoMatch)
2100 return ResTy;
2101
2102 // Registers are a valid target and have priority over symbols.
2103 ResTy = ParseAnyRegister(Operands);
2104 if (ResTy != MatchOperand_NoMatch)
2105 return ResTy;
2106
2107 const MCExpr *Expr = nullptr;
2108 if (Parser.parseExpression(Expr)) {
2109 // We have no way of knowing if a symbol was consumed so we must ParseFail
2110 return MatchOperand_ParseFail;
2111 }
2112 Operands.push_back(
2113 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
2114 return MatchOperand_Success;
2115}
2116
2117MipsAsmParser::OperandMatchResultTy
2118MipsAsmParser::parseInvNum(OperandVector &Operands) {
2119 const MCExpr *IdVal;
2120 // If the first token is '$' we may have register operand.
2121 if (Parser.getTok().is(AsmToken::Dollar))
2122 return MatchOperand_NoMatch;
2123 SMLoc S = Parser.getTok().getLoc();
2124 if (getParser().parseExpression(IdVal))
2125 return MatchOperand_ParseFail;
2126 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
2127 assert(MCE && "Unexpected MCExpr type.");
2128 int64_t Val = MCE->getValue();
2129 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2130 Operands.push_back(MipsOperand::CreateImm(
2131 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
2132 return MatchOperand_Success;
2133}
2134
2135MipsAsmParser::OperandMatchResultTy
2136MipsAsmParser::ParseLSAImm(OperandVector &Operands) {
2137 switch (getLexer().getKind()) {
2138 default:
2139 return MatchOperand_NoMatch;
2140 case AsmToken::LParen:
2141 case AsmToken::Plus:
2142 case AsmToken::Minus:
2143 case AsmToken::Integer:
2144 break;
2145 }
2146
2147 const MCExpr *Expr;
2148 SMLoc S = Parser.getTok().getLoc();
2149
2150 if (getParser().parseExpression(Expr))
2151 return MatchOperand_ParseFail;
2152
2153 int64_t Val;
2154 if (!Expr->EvaluateAsAbsolute(Val)) {
2155 Error(S, "expected immediate value");
2156 return MatchOperand_ParseFail;
2157 }
2158
2159 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2160 // and because the CPU always adds one to the immediate field, the allowed
2161 // range becomes 1..4. We'll only check the range here and will deal
2162 // with the addition/subtraction when actually decoding/encoding
2163 // the instruction.
2164 if (Val < 1 || Val > 4) {
2165 Error(S, "immediate not in range (1..4)");
2166 return MatchOperand_ParseFail;
2167 }
2168
2169 Operands.push_back(
2170 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
2171 return MatchOperand_Success;
2172}
2173
2174MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2175
2176 MCSymbolRefExpr::VariantKind VK =
2177 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2178 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2179 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2180 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2181 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2182 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2183 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2184 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2185 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2186 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2187 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2188 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2189 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2190 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2191 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2192 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2193 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2194 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
2195 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2196 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2197 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2198 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2199 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2200 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
2201 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2202 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
2203 .Default(MCSymbolRefExpr::VK_None);
2204
2205 assert(VK != MCSymbolRefExpr::VK_None);
2206
2207 return VK;
2208}
2209
2210/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2211/// either this.
2212/// ::= '(', register, ')'
2213/// handle it before we iterate so we don't get tripped up by the lack of
2214/// a comma.
2215bool MipsAsmParser::ParseParenSuffix(StringRef Name, OperandVector &Operands) {
2216 if (getLexer().is(AsmToken::LParen)) {
2217 Operands.push_back(
2218 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2219 Parser.Lex();
2220 if (ParseOperand(Operands, Name)) {
2221 SMLoc Loc = getLexer().getLoc();
2222 Parser.eatToEndOfStatement();
2223 return Error(Loc, "unexpected token in argument list");
2224 }
2225 if (Parser.getTok().isNot(AsmToken::RParen)) {
2226 SMLoc Loc = getLexer().getLoc();
2227 Parser.eatToEndOfStatement();
2228 return Error(Loc, "unexpected token, expected ')'");
2229 }
2230 Operands.push_back(
2231 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2232 Parser.Lex();
2233 }
2234 return false;
2235}
2236
2237/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2238/// either one of these.
2239/// ::= '[', register, ']'
2240/// ::= '[', integer, ']'
2241/// handle it before we iterate so we don't get tripped up by the lack of
2242/// a comma.
2243bool MipsAsmParser::ParseBracketSuffix(StringRef Name,
2244 OperandVector &Operands) {
2245 if (getLexer().is(AsmToken::LBrac)) {
2246 Operands.push_back(
2247 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2248 Parser.Lex();
2249 if (ParseOperand(Operands, Name)) {
2250 SMLoc Loc = getLexer().getLoc();
2251 Parser.eatToEndOfStatement();
2252 return Error(Loc, "unexpected token in argument list");
2253 }
2254 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2255 SMLoc Loc = getLexer().getLoc();
2256 Parser.eatToEndOfStatement();
2257 return Error(Loc, "unexpected token, expected ']'");
2258 }
2259 Operands.push_back(
2260 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2261 Parser.Lex();
2262 }
2263 return false;
2264}
2265
2266bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2267 SMLoc NameLoc, OperandVector &Operands) {
2268 DEBUG(dbgs() << "ParseInstruction\n");
2269 // We have reached first instruction, module directive after
2270 // this is forbidden.
2271 getTargetStreamer().setCanHaveModuleDir(false);
2272 // Check if we have valid mnemonic
2273 if (!mnemonicIsValid(Name, 0)) {
2274 Parser.eatToEndOfStatement();
2275 return Error(NameLoc, "Unknown instruction");
2276 }
2277 // First operand in MCInst is instruction mnemonic.
2278 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
2279
2280 // Read the remaining operands.
2281 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2282 // Read the first operand.
2283 if (ParseOperand(Operands, Name)) {
2284 SMLoc Loc = getLexer().getLoc();
2285 Parser.eatToEndOfStatement();
2286 return Error(Loc, "unexpected token in argument list");
2287 }
2288 if (getLexer().is(AsmToken::LBrac) && ParseBracketSuffix(Name, Operands))
2289 return true;
2290 // AFAIK, parenthesis suffixes are never on the first operand
2291
2292 while (getLexer().is(AsmToken::Comma)) {
2293 Parser.Lex(); // Eat the comma.
2294 // Parse and remember the operand.
2295 if (ParseOperand(Operands, Name)) {
2296 SMLoc Loc = getLexer().getLoc();
2297 Parser.eatToEndOfStatement();
2298 return Error(Loc, "unexpected token in argument list");
2299 }
2300 // Parse bracket and parenthesis suffixes before we iterate
2301 if (getLexer().is(AsmToken::LBrac)) {
2302 if (ParseBracketSuffix(Name, Operands))
2303 return true;
2304 } else if (getLexer().is(AsmToken::LParen) &&
2305 ParseParenSuffix(Name, Operands))
2306 return true;
2307 }
2308 }
2309 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2310 SMLoc Loc = getLexer().getLoc();
2311 Parser.eatToEndOfStatement();
2312 return Error(Loc, "unexpected token in argument list");
2313 }
2314 Parser.Lex(); // Consume the EndOfStatement.
2315 return false;
2316}
2317
2318bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
2319 SMLoc Loc = getLexer().getLoc();
2320 Parser.eatToEndOfStatement();
2321 return Error(Loc, ErrorMsg);
2322}
2323
2324bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
2325 return Error(Loc, ErrorMsg);
2326}
2327
2328bool MipsAsmParser::parseSetNoAtDirective() {
2329 // Line should look like: ".set noat".
2330 // set at reg to 0.
2331 Options.setATReg(0);
2332 // eat noat
2333 Parser.Lex();
2334 // If this is not the end of the statement, report an error.
2335 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2336 reportParseError("unexpected token in statement");
2337 return false;
2338 }
2339 Parser.Lex(); // Consume the EndOfStatement.
2340 return false;
2341}
2342
2343bool MipsAsmParser::parseSetAtDirective() {
2344 // Line can be .set at - defaults to $1
2345 // or .set at=$reg
2346 int AtRegNo;
2347 getParser().Lex();
2348 if (getLexer().is(AsmToken::EndOfStatement)) {
2349 Options.setATReg(1);
2350 Parser.Lex(); // Consume the EndOfStatement.
2351 return false;
2352 } else if (getLexer().is(AsmToken::Equal)) {
2353 getParser().Lex(); // Eat the '='.
2354 if (getLexer().isNot(AsmToken::Dollar)) {
2355 reportParseError("unexpected token in statement");
2356 return false;
2357 }
2358 Parser.Lex(); // Eat the '$'.
2359 const AsmToken &Reg = Parser.getTok();
2360 if (Reg.is(AsmToken::Identifier)) {
2361 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2362 } else if (Reg.is(AsmToken::Integer)) {
2363 AtRegNo = Reg.getIntVal();
2364 } else {
2365 reportParseError("unexpected token in statement");
2366 return false;
2367 }
2368
2369 if (AtRegNo < 0 || AtRegNo > 31) {
2370 reportParseError("unexpected token in statement");
2371 return false;
2372 }
2373
2374 if (!Options.setATReg(AtRegNo)) {
2375 reportParseError("unexpected token in statement");
2376 return false;
2377 }
2378 getParser().Lex(); // Eat the register.
2379
2380 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2381 reportParseError("unexpected token in statement");
2382 return false;
2383 }
2384 Parser.Lex(); // Consume the EndOfStatement.
2385 return false;
2386 } else {
2387 reportParseError("unexpected token in statement");
2388 return false;
2389 }
2390}
2391
2392bool MipsAsmParser::parseSetReorderDirective() {
2393 Parser.Lex();
2394 // If this is not the end of the statement, report an error.
2395 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2396 reportParseError("unexpected token in statement");
2397 return false;
2398 }
2399 Options.setReorder();
2400 getTargetStreamer().emitDirectiveSetReorder();
2401 Parser.Lex(); // Consume the EndOfStatement.
2402 return false;
2403}
2404
2405bool MipsAsmParser::parseSetNoReorderDirective() {
2406 Parser.Lex();
2407 // If this is not the end of the statement, report an error.
2408 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2409 reportParseError("unexpected token in statement");
2410 return false;
2411 }
2412 Options.setNoreorder();
2413 getTargetStreamer().emitDirectiveSetNoReorder();
2414 Parser.Lex(); // Consume the EndOfStatement.
2415 return false;
2416}
2417
2418bool MipsAsmParser::parseSetMacroDirective() {
2419 Parser.Lex();
2420 // If this is not the end of the statement, report an error.
2421 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2422 reportParseError("unexpected token in statement");
2423 return false;
2424 }
2425 Options.setMacro();
2426 Parser.Lex(); // Consume the EndOfStatement.
2427 return false;
2428}
2429
2430bool MipsAsmParser::parseSetNoMacroDirective() {
2431 Parser.Lex();
2432 // If this is not the end of the statement, report an error.
2433 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2434 reportParseError("`noreorder' must be set before `nomacro'");
2435 return false;
2436 }
2437 if (Options.isReorder()) {
2438 reportParseError("`noreorder' must be set before `nomacro'");
2439 return false;
2440 }
2441 Options.setNomacro();
2442 Parser.Lex(); // Consume the EndOfStatement.
2443 return false;
2444}
2445
2446bool MipsAsmParser::parseSetNoMips16Directive() {
2447 Parser.Lex();
2448 // If this is not the end of the statement, report an error.
2449 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2450 reportParseError("unexpected token in statement");
2451 return false;
2452 }
2453 // For now do nothing.
2454 Parser.Lex(); // Consume the EndOfStatement.
2455 return false;
2456}
2457
2458bool MipsAsmParser::parseSetFpDirective() {
2459 MipsABIFlagsSection::FpABIKind FpAbiVal;
2460 // Line can be: .set fp=32
2461 // .set fp=xx
2462 // .set fp=64
2463 Parser.Lex(); // Eat fp token
2464 AsmToken Tok = Parser.getTok();
2465 if (Tok.isNot(AsmToken::Equal)) {
2466 reportParseError("unexpected token in statement");
2467 return false;
2468 }
2469 Parser.Lex(); // Eat '=' token.
2470 Tok = Parser.getTok();
2471
2472 if (!parseFpABIValue(FpAbiVal, ".set"))
2473 return false;
2474
2475 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2476 reportParseError("unexpected token in statement");
2477 return false;
2478 }
2479 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
2480 Parser.Lex(); // Consume the EndOfStatement.
2481 return false;
2482}
2483
2484bool MipsAsmParser::parseSetAssignment() {
2485 StringRef Name;
2486 const MCExpr *Value;
2487
2488 if (Parser.parseIdentifier(Name))
2489 reportParseError("expected identifier after .set");
2490
2491 if (getLexer().isNot(AsmToken::Comma))
2492 return reportParseError("unexpected token in .set directive");
2493 Lex(); // Eat comma
2494
2495 if (Parser.parseExpression(Value))
2496 return reportParseError("expected valid expression after comma");
2497
2498 // Check if the Name already exists as a symbol.
2499 MCSymbol *Sym = getContext().LookupSymbol(Name);
2500 if (Sym)
2501 return reportParseError("symbol already defined");
2502 Sym = getContext().GetOrCreateSymbol(Name);
2503 Sym->setVariableValue(Value);
2504
2505 return false;
2506}
2507
2508bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
2509 Parser.Lex();
2510 if (getLexer().isNot(AsmToken::EndOfStatement))
2511 return reportParseError("unexpected token in .set directive");
2512
2513 switch (Feature) {
2514 default:
2515 llvm_unreachable("Unimplemented feature");
2516 case Mips::FeatureDSP:
2517 setFeatureBits(Mips::FeatureDSP, "dsp");
2518 getTargetStreamer().emitDirectiveSetDsp();
2519 break;
2520 case Mips::FeatureMicroMips:
2521 getTargetStreamer().emitDirectiveSetMicroMips();
2522 break;
2523 case Mips::FeatureMips16:
2524 getTargetStreamer().emitDirectiveSetMips16();
2525 break;
2526 case Mips::FeatureMips32r2:
2527 setFeatureBits(Mips::FeatureMips32r2, "mips32r2");
2528 getTargetStreamer().emitDirectiveSetMips32R2();
2529 break;
2530 case Mips::FeatureMips64:
2531 setFeatureBits(Mips::FeatureMips64, "mips64");
2532 getTargetStreamer().emitDirectiveSetMips64();
2533 break;
2534 case Mips::FeatureMips64r2:
2535 setFeatureBits(Mips::FeatureMips64r2, "mips64r2");
2536 getTargetStreamer().emitDirectiveSetMips64R2();
2537 break;
2538 }
2539 return false;
2540}
2541
2542bool MipsAsmParser::eatComma(StringRef ErrorStr) {
2543 if (getLexer().isNot(AsmToken::Comma)) {
2544 SMLoc Loc = getLexer().getLoc();
2545 Parser.eatToEndOfStatement();
2546 return Error(Loc, ErrorStr);
2547 }
2548
2549 Parser.Lex(); // Eat the comma.
2550 return true;
2551}
2552
2553bool MipsAsmParser::parseDirectiveCPLoad(SMLoc Loc) {
2554 if (Options.isReorder())
2555 Warning(Loc, ".cpload in reorder section");
2556
2557 // FIXME: Warn if cpload is used in Mips16 mode.
2558
2559 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
2560 OperandMatchResultTy ResTy = ParseAnyRegister(Reg);
2561 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
2562 reportParseError("expected register containing function address");
2563 return false;
2564 }
2565
2566 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
2567 if (!RegOpnd.isGPRAsmReg()) {
2568 reportParseError(RegOpnd.getStartLoc(), "invalid register");
2569 return false;
2570 }
2571
2572 getTargetStreamer().emitDirectiveCpload(RegOpnd.getGPR32Reg());
2573 return false;
2574}
2575
2576bool MipsAsmParser::parseDirectiveCPSetup() {
2577 unsigned FuncReg;
2578 unsigned Save;
2579 bool SaveIsReg = true;
2580
2581 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
2582 OperandMatchResultTy ResTy = ParseAnyRegister(TmpReg);
2583 if (ResTy == MatchOperand_NoMatch) {
2584 reportParseError("expected register containing function address");
2585 Parser.eatToEndOfStatement();
2586 return false;
2587 }
2588
2589 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
2590 if (!FuncRegOpnd.isGPRAsmReg()) {
2591 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
2592 Parser.eatToEndOfStatement();
2593 return false;
2594 }
2595
2596 FuncReg = FuncRegOpnd.getGPR32Reg();
2597 TmpReg.clear();
2598
2599 if (!eatComma("expected comma parsing directive"))
2600 return true;
2601
2602 ResTy = ParseAnyRegister(TmpReg);
2603 if (ResTy == MatchOperand_NoMatch) {
2604 const AsmToken &Tok = Parser.getTok();
2605 if (Tok.is(AsmToken::Integer)) {
2606 Save = Tok.getIntVal();
2607 SaveIsReg = false;
2608 Parser.Lex();
2609 } else {
2610 reportParseError("expected save register or stack offset");
2611 Parser.eatToEndOfStatement();
2612 return false;
2613 }
2614 } else {
2615 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
2616 if (!SaveOpnd.isGPRAsmReg()) {
2617 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
2618 Parser.eatToEndOfStatement();
2619 return false;
2620 }
2621 Save = SaveOpnd.getGPR32Reg();
2622 }
2623
2624 if (!eatComma("expected comma parsing directive"))
2625 return true;
2626
2627 StringRef Name;
2628 if (Parser.parseIdentifier(Name))
2629 reportParseError("expected identifier");
2630 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
2631
2632 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
2633 return false;
2634}
2635
2636bool MipsAsmParser::parseDirectiveNaN() {
2637 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2638 const AsmToken &Tok = Parser.getTok();
2639
2640 if (Tok.getString() == "2008") {
2641 Parser.Lex();
2642 getTargetStreamer().emitDirectiveNaN2008();
2643 return false;
2644 } else if (Tok.getString() == "legacy") {
2645 Parser.Lex();
2646 getTargetStreamer().emitDirectiveNaNLegacy();
2647 return false;
2648 }
2649 }
2650 // If we don't recognize the option passed to the .nan
2651 // directive (e.g. no option or unknown option), emit an error.
2652 reportParseError("invalid option in .nan directive");
2653 return false;
2654}
2655
2656bool MipsAsmParser::parseDirectiveSet() {
2657
2658 // Get the next token.
2659 const AsmToken &Tok = Parser.getTok();
2660
2661 if (Tok.getString() == "noat") {
2662 return parseSetNoAtDirective();
2663 } else if (Tok.getString() == "at") {
2664 return parseSetAtDirective();
2665 } else if (Tok.getString() == "fp") {
2666 return parseSetFpDirective();
2667 } else if (Tok.getString() == "reorder") {
2668 return parseSetReorderDirective();
2669 } else if (Tok.getString() == "noreorder") {
2670 return parseSetNoReorderDirective();
2671 } else if (Tok.getString() == "macro") {
2672 return parseSetMacroDirective();
2673 } else if (Tok.getString() == "nomacro") {
2674 return parseSetNoMacroDirective();
2675 } else if (Tok.getString() == "mips16") {
2676 return parseSetFeature(Mips::FeatureMips16);
2677 } else if (Tok.getString() == "nomips16") {
2678 return parseSetNoMips16Directive();
2679 } else if (Tok.getString() == "nomicromips") {
2680 getTargetStreamer().emitDirectiveSetNoMicroMips();
2681 Parser.eatToEndOfStatement();
2682 return false;
2683 } else if (Tok.getString() == "micromips") {
2684 return parseSetFeature(Mips::FeatureMicroMips);
2685 } else if (Tok.getString() == "mips32r2") {
2686 return parseSetFeature(Mips::FeatureMips32r2);
2687 } else if (Tok.getString() == "mips64") {
2688 return parseSetFeature(Mips::FeatureMips64);
2689 } else if (Tok.getString() == "mips64r2") {
2690 return parseSetFeature(Mips::FeatureMips64r2);
2691 } else if (Tok.getString() == "dsp") {
2692 return parseSetFeature(Mips::FeatureDSP);
2693 } else {
2694 // It is just an identifier, look for an assignment.
2695 parseSetAssignment();
2696 return false;
2697 }
2698
2699 return true;
2700}
2701
2702/// parseDataDirective
2703/// ::= .word [ expression (, expression)* ]
2704bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
2705 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2706 for (;;) {
2707 const MCExpr *Value;
2708 if (getParser().parseExpression(Value))
2709 return true;
2710
2711 getParser().getStreamer().EmitValue(Value, Size);
2712
2713 if (getLexer().is(AsmToken::EndOfStatement))
2714 break;
2715
2716 // FIXME: Improve diagnostic.
2717 if (getLexer().isNot(AsmToken::Comma))
2718 return Error(L, "unexpected token in directive");
2719 Parser.Lex();
2720 }
2721 }
2722
2723 Parser.Lex();
2724 return false;
2725}
2726
2727/// parseDirectiveGpWord
2728/// ::= .gpword local_sym
2729bool MipsAsmParser::parseDirectiveGpWord() {
2730 const MCExpr *Value;
2731 // EmitGPRel32Value requires an expression, so we are using base class
2732 // method to evaluate the expression.
2733 if (getParser().parseExpression(Value))
2734 return true;
2735 getParser().getStreamer().EmitGPRel32Value(Value);
2736
2737 if (getLexer().isNot(AsmToken::EndOfStatement))
2738 return Error(getLexer().getLoc(), "unexpected token in directive");
2739 Parser.Lex(); // Eat EndOfStatement token.
2740 return false;
2741}
2742
2743/// parseDirectiveGpDWord
2744/// ::= .gpdword local_sym
2745bool MipsAsmParser::parseDirectiveGpDWord() {
2746 const MCExpr *Value;
2747 // EmitGPRel64Value requires an expression, so we are using base class
2748 // method to evaluate the expression.
2749 if (getParser().parseExpression(Value))
2750 return true;
2751 getParser().getStreamer().EmitGPRel64Value(Value);
2752
2753 if (getLexer().isNot(AsmToken::EndOfStatement))
2754 return Error(getLexer().getLoc(), "unexpected token in directive");
2755 Parser.Lex(); // Eat EndOfStatement token.
2756 return false;
2757}
2758
2759bool MipsAsmParser::parseDirectiveOption() {
2760 // Get the option token.
2761 AsmToken Tok = Parser.getTok();
2762 // At the moment only identifiers are supported.
2763 if (Tok.isNot(AsmToken::Identifier)) {
2764 Error(Parser.getTok().getLoc(), "unexpected token in .option directive");
2765 Parser.eatToEndOfStatement();
2766 return false;
2767 }
2768
2769 StringRef Option = Tok.getIdentifier();
2770
2771 if (Option == "pic0") {
2772 getTargetStreamer().emitDirectiveOptionPic0();
2773 Parser.Lex();
2774 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2775 Error(Parser.getTok().getLoc(),
2776 "unexpected token in .option pic0 directive");
2777 Parser.eatToEndOfStatement();
2778 }
2779 return false;
2780 }
2781
2782 if (Option == "pic2") {
2783 getTargetStreamer().emitDirectiveOptionPic2();
2784 Parser.Lex();
2785 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2786 Error(Parser.getTok().getLoc(),
2787 "unexpected token in .option pic2 directive");
2788 Parser.eatToEndOfStatement();
2789 }
2790 return false;
2791 }
2792
2793 // Unknown option.
2794 Warning(Parser.getTok().getLoc(), "unknown option in .option directive");
2795 Parser.eatToEndOfStatement();
2796 return false;
2797}
2798
2799/// parseDirectiveModule
2800/// ::= .module oddspreg
2801/// ::= .module nooddspreg
2802/// ::= .module fp=value
2803bool MipsAsmParser::parseDirectiveModule() {
2804 MCAsmLexer &Lexer = getLexer();
2805 SMLoc L = Lexer.getLoc();
2806
2807 if (!getTargetStreamer().getCanHaveModuleDir()) {
2808 // TODO : get a better message.
2809 reportParseError(".module directive must appear before any code");
2810 return false;
2811 }
2812
2813 if (Lexer.is(AsmToken::Identifier)) {
2814 StringRef Option = Parser.getTok().getString();
2815 Parser.Lex();
2816
2817 if (Option == "oddspreg") {
2818 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
2819 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
2820
2821 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2822 reportParseError("Expected end of statement");
2823 return false;
2824 }
2825
2826 return false;
2827 } else if (Option == "nooddspreg") {
2828 if (!isABI_O32()) {
2829 Error(L, "'.module nooddspreg' requires the O32 ABI");
2830 return false;
2831 }
2832
2833 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
2834 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
2835
2836 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2837 reportParseError("Expected end of statement");
2838 return false;
2839 }
2840
2841 return false;
2842 } else if (Option == "fp") {
2843 return parseDirectiveModuleFP();
2844 }
2845
2846 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
2847 }
2848
2849 return false;
2850}
2851
2852/// parseDirectiveModuleFP
2853/// ::= =32
2854/// ::= =xx
2855/// ::= =64
2856bool MipsAsmParser::parseDirectiveModuleFP() {
2857 MCAsmLexer &Lexer = getLexer();
2858
2859 if (Lexer.isNot(AsmToken::Equal)) {
2860 reportParseError("unexpected token in statement");
2861 return false;
2862 }
2863 Parser.Lex(); // Eat '=' token.
2864
2865 MipsABIFlagsSection::FpABIKind FpABI;
2866 if (!parseFpABIValue(FpABI, ".module"))
2867 return false;
2868
2869 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2870 reportParseError("unexpected token in statement");
2871 return false;
2872 }
2873
2874 // Emit appropriate flags.
2875 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
2876 Parser.Lex(); // Consume the EndOfStatement.
2877 return false;
2878}
2879
2880bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
2881 StringRef Directive) {
2882 MCAsmLexer &Lexer = getLexer();
2883
2884 if (Lexer.is(AsmToken::Identifier)) {
2885 StringRef Value = Parser.getTok().getString();
2886 Parser.Lex();
2887
2888 if (Value != "xx") {
2889 reportParseError("unsupported value, expected 'xx', '32' or '64'");
2890 return false;
2891 }
2892
2893 if (!isABI_O32()) {
2894 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
2895 return false;
2896 }
2897
2898 FpABI = MipsABIFlagsSection::FpABIKind::XX;
2899 return true;
2900 }
2901
2902 if (Lexer.is(AsmToken::Integer)) {
2903 unsigned Value = Parser.getTok().getIntVal();
2904 Parser.Lex();
2905
2906 if (Value != 32 && Value != 64) {
2907 reportParseError("unsupported value, expected 'xx', '32' or '64'");
2908 return false;
2909 }
2910
2911 if (Value == 32) {
2912 if (!isABI_O32()) {
2913 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
2914 return false;
2915 }
2916
2917 FpABI = MipsABIFlagsSection::FpABIKind::S32;
2918 } else
2919 FpABI = MipsABIFlagsSection::FpABIKind::S64;
2920
2921 return true;
2922 }
2923
2924 return false;
2925}
2926
2927bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
2928 StringRef IDVal = DirectiveID.getString();
2929
2930 if (IDVal == ".cpload")
2931 return parseDirectiveCPLoad(DirectiveID.getLoc());
2932 if (IDVal == ".dword") {
2933 parseDataDirective(8, DirectiveID.getLoc());
2934 return false;
2935 }
2936
2937 if (IDVal == ".ent") {
2938 // Ignore this directive for now.
2939 Parser.Lex();
2940 return false;
2941 }
2942
2943 if (IDVal == ".end") {
2944 // Ignore this directive for now.
2945 Parser.Lex();
2946 return false;
2947 }
2948
2949 if (IDVal == ".frame") {
2950 // Ignore this directive for now.
2951 Parser.eatToEndOfStatement();
2952 return false;
2953 }
2954
2955 if (IDVal == ".set") {
2956 return parseDirectiveSet();
2957 }
2958
2959 if (IDVal == ".fmask") {
2960 // Ignore this directive for now.
2961 Parser.eatToEndOfStatement();
2962 return false;
2963 }
2964
2965 if (IDVal == ".mask") {
2966 // Ignore this directive for now.
2967 Parser.eatToEndOfStatement();
2968 return false;
2969 }
2970
2971 if (IDVal == ".nan")
2972 return parseDirectiveNaN();
2973
2974 if (IDVal == ".gpword") {
2975 parseDirectiveGpWord();
2976 return false;
2977 }
2978
2979 if (IDVal == ".gpdword") {
2980 parseDirectiveGpDWord();
2981 return false;
2982 }
2983
2984 if (IDVal == ".word") {
2985 parseDataDirective(4, DirectiveID.getLoc());
2986 return false;
2987 }
2988
2989 if (IDVal == ".option")
2990 return parseDirectiveOption();
2991
2992 if (IDVal == ".abicalls") {
2993 getTargetStreamer().emitDirectiveAbiCalls();
2994 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2995 Error(Parser.getTok().getLoc(), "unexpected token in directive");
2996 // Clear line
2997 Parser.eatToEndOfStatement();
2998 }
2999 return false;
3000 }
3001
3002 if (IDVal == ".cpsetup")
3003 return parseDirectiveCPSetup();
3004
3005 if (IDVal == ".module")
3006 return parseDirectiveModule();
3007
3008 return true;
3009}
3010
3011extern "C" void LLVMInitializeMipsAsmParser() {
3012 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
3013 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
3014 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
3015 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
3016}
3017
3018#define GET_REGISTER_MATCHER
3019#define GET_MATCHER_IMPLEMENTATION
3020#include "MipsGenAsmMatcher.inc"