blob: f0829a67871e2d99f71b4b19d5141e5667b18eb6 [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-01-11 03:56:41 +00002//
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
Eric Christophera5762812015-01-26 17:33:46 +000010#include "MCTargetDesc/MipsABIInfo.h"
Petar Jovanovica5da5882014-02-04 18:41:57 +000011#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000012#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000013#include "MipsRegisterInfo.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000014#include "MipsTargetStreamer.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000015#include "llvm/ADT/APInt.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000016#include "llvm/ADT/SmallVector.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000017#include "llvm/ADT/StringSwitch.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000018#include "llvm/MC/MCContext.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000021#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000022#include "llvm/MC/MCParser/MCAsmLexer.h"
23#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000024#include "llvm/MC/MCStreamer.h"
25#include "llvm/MC/MCSubtargetInfo.h"
26#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000027#include "llvm/MC/MCTargetAsmParser.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000028#include "llvm/Support/Debug.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000029#include "llvm/Support/MathExtras.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000030#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000031#include "llvm/Support/TargetRegistry.h"
Benjamin Kramer799003b2015-03-23 19:32:43 +000032#include "llvm/Support/raw_ostream.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000033#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000034
35using namespace llvm;
36
Chandler Carruthe96dd892014-04-21 22:55:11 +000037#define DEBUG_TYPE "mips-asm-parser"
38
Joey Gouly0e76fa72013-09-12 10:28:05 +000039namespace llvm {
40class MCInstrInfo;
41}
42
Rafael Espindola870c4e92012-01-11 03:56:41 +000043namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000044class MipsAssemblerOptions {
45public:
Toma Tabacu9db22db2014-09-09 10:15:38 +000046 MipsAssemblerOptions(uint64_t Features_) :
47 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000048
Toma Tabacu9db22db2014-09-09 10:15:38 +000049 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000050 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000051 Reorder = Opts->isReorder();
52 Macro = Opts->isMacro();
53 Features = Opts->getFeatures();
54 }
55
Toma Tabacub19cf202015-04-27 13:12:59 +000056 unsigned getATRegIndex() const { return ATReg; }
57 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000058 if (Reg > 31)
59 return false;
60
61 ATReg = Reg;
62 return true;
63 }
Jack Carter0b744b32012-10-04 02:29:46 +000064
Toma Tabacu9db22db2014-09-09 10:15:38 +000065 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000066 void setReorder() { Reorder = true; }
67 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000068
Toma Tabacu9db22db2014-09-09 10:15:38 +000069 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000070 void setMacro() { Macro = true; }
71 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000072
Toma Tabacu9db22db2014-09-09 10:15:38 +000073 uint64_t getFeatures() const { return Features; }
74 void setFeatures(uint64_t Features_) { Features = Features_; }
75
Daniel Sandersf0df2212014-08-04 12:20:00 +000076 // Set of features that are either architecture features or referenced
77 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
78 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
79 // The reason we need this mask is explained in the selectArch function.
80 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kuperstein29704e72015-03-24 12:56:59 +000081 static const uint64_t AllArchRelatedMask =
82 Mips::FeatureMips1 | Mips::FeatureMips2 | Mips::FeatureMips3 |
83 Mips::FeatureMips3_32 | Mips::FeatureMips3_32r2 | Mips::FeatureMips4 |
84 Mips::FeatureMips4_32 | Mips::FeatureMips4_32r2 | Mips::FeatureMips5 |
85 Mips::FeatureMips5_32r2 | Mips::FeatureMips32 | Mips::FeatureMips32r2 |
86 Mips::FeatureMips32r3 | Mips::FeatureMips32r5 | Mips::FeatureMips32r6 |
87 Mips::FeatureMips64 | Mips::FeatureMips64r2 | Mips::FeatureMips64r3 |
88 Mips::FeatureMips64r5 | Mips::FeatureMips64r6 | Mips::FeatureCnMips |
89 Mips::FeatureFP64Bit | Mips::FeatureGP64Bit | Mips::FeatureNaN2008;
Daniel Sandersf0df2212014-08-04 12:20:00 +000090
Jack Carter0b744b32012-10-04 02:29:46 +000091private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000092 unsigned ATReg;
93 bool Reorder;
94 bool Macro;
Toma Tabacu9db22db2014-09-09 10:15:38 +000095 uint64_t Features;
Jack Carter0b744b32012-10-04 02:29:46 +000096};
97}
98
99namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +0000100class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000101 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000102 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000103 return static_cast<MipsTargetStreamer &>(TS);
104 }
105
Jack Carterb4dbc172012-09-05 23:34:03 +0000106 MCSubtargetInfo &STI;
Eric Christophera5762812015-01-26 17:33:46 +0000107 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000108 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000109 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
110 // nullptr, which indicates that no function is currently
111 // selected. This usually happens after an '.end func'
112 // directive.
Jack Carter0b744b32012-10-04 02:29:46 +0000113
Daniel Sandersef638fe2014-10-03 15:37:37 +0000114 // Print a warning along with its fix-it message at the given range.
115 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
116 SMRange Range, bool ShowColors = true);
117
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000118#define GET_ASSEMBLER_HEADER
119#include "MipsGenAsmMatcher.inc"
120
Matheus Almeida595fcab2014-06-11 15:05:56 +0000121 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
122
Chad Rosier49963552012-10-13 00:26:04 +0000123 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000124 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000125 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000126 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000127
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000128 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000129 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000130
Toma Tabacu13964452014-09-04 13:23:44 +0000131 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000132
Toma Tabacu13964452014-09-04 13:23:44 +0000133 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000134
David Blaikie960ea3f2014-06-08 16:18:35 +0000135 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
136 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000137
Craig Topper56c590a2014-04-29 07:58:02 +0000138 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000139
David Blaikie960ea3f2014-06-08 16:18:35 +0000140 MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000141
142 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000143 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000144 StringRef Identifier, SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000145
Jack Carter873c7242013-01-12 01:03:14 +0000146 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000147 matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
Jack Carter873c7242013-01-12 01:03:14 +0000148
Toma Tabacu13964452014-09-04 13:23:44 +0000149 MipsAsmParser::OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000150
Toma Tabacu13964452014-09-04 13:23:44 +0000151 MipsAsmParser::OperandMatchResultTy parseImm(OperandVector &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000152
Toma Tabacu13964452014-09-04 13:23:44 +0000153 MipsAsmParser::OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000154
David Blaikie960ea3f2014-06-08 16:18:35 +0000155 MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000156
Toma Tabacu13964452014-09-04 13:23:44 +0000157 MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000158
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000159 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000160 parseRegisterPair (OperandVector &Operands);
161
162 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +0000163 parseMovePRegPair(OperandVector &Operands);
164
165 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000166 parseRegisterList (OperandVector &Operands);
167
David Blaikie960ea3f2014-06-08 16:18:35 +0000168 bool searchSymbolAlias(OperandVector &Operands);
169
Toma Tabacu13964452014-09-04 13:23:44 +0000170 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000171
Jack Carter30a59822012-10-04 04:03:53 +0000172 bool needsExpansion(MCInst &Inst);
173
Matheus Almeida3813d572014-06-19 14:39:14 +0000174 // Expands assembly pseudo instructions.
175 // Returns false on success, true otherwise.
176 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000177 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000178
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000179 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
180 SmallVectorImpl<MCInst> &Instructions);
181
Matheus Almeida3813d572014-06-19 14:39:14 +0000182 bool expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000183 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000184
185 bool expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000186 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000187
188 bool expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000189 SmallVectorImpl<MCInst> &Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000190 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
191 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000192
Toma Tabacu0d64b202014-08-14 10:29:17 +0000193 void expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
194 SmallVectorImpl<MCInst> &Instructions);
195
Jack Carter9e65aa32013-03-22 00:05:30 +0000196 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000197 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
198 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000199
200 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
201 SmallVectorImpl<MCInst> &Instructions);
202
Toma Tabacu234482a2015-03-16 12:03:39 +0000203 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
204 SmallVectorImpl<MCInst> &Instructions);
205
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000206 bool reportParseError(Twine ErrorMsg);
207 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000208
Jack Carterb5cf5902013-04-17 00:18:04 +0000209 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000210 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000211
Vladimir Medic4c299852013-11-06 11:27:05 +0000212 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000213
214 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000215 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000216 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000217 bool parseSetFeature(uint64_t Feature);
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000218 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000219 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000220 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000221 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000222 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000223 bool parseInsnDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000224
225 bool parseSetAtDirective();
226 bool parseSetNoAtDirective();
227 bool parseSetMacroDirective();
228 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000229 bool parseSetMsaDirective();
230 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000231 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000232 bool parseSetReorderDirective();
233 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000234 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000235 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000236 bool parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000237 bool parseSetPopDirective();
238 bool parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000239
Jack Carterd76b2372013-03-21 21:44:16 +0000240 bool parseSetAssignment();
241
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000242 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000243 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000244 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000245 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000246 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000247 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
248 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000249
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000250 bool parseInternalDirectiveReallowModule();
251
Jack Carterdc1e35d2012-09-06 20:00:02 +0000252 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000253
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000254 bool eatComma(StringRef ErrorStr);
255
Jack Carter1ac53222013-02-20 23:11:17 +0000256 int matchCPURegisterName(StringRef Symbol);
257
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000258 int matchHWRegsRegisterName(StringRef Symbol);
259
Jack Carter873c7242013-01-12 01:03:14 +0000260 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000261
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000262 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000263
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000264 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000265
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000266 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000267
Jack Carter5dc8ac92013-09-25 23:50:44 +0000268 int matchMSA128RegisterName(StringRef Name);
269
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000270 int matchMSA128CtrlRegisterName(StringRef Name);
271
Jack Carterd0bd6422013-04-18 00:41:53 +0000272 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000273
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000274 unsigned getGPR(int RegNo);
275
Toma Tabacu89a712b2015-04-15 10:48:56 +0000276 /// Returns the internal register number for the current AT. Also checks if
277 /// the current AT is unavailable (set to $0) and gives an error if it is.
278 /// This should be used in pseudo-instruction expansions which need AT.
279 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000280
281 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000282 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000283
284 // Helper function that checks if the value of a vector index is within the
285 // boundaries of accepted values for each RegisterKind
286 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
287 bool validateMSAIndex(int Val, int RegKind);
288
Daniel Sandersf0df2212014-08-04 12:20:00 +0000289 // Selects a new architecture by updating the FeatureBits with the necessary
290 // info including implied dependencies.
291 // Internally, it clears all the feature bits related to *any* architecture
292 // and selects the new one using the ToggleFeature functionality of the
293 // MCSubtargetInfo object that handles implied dependencies. The reason we
294 // clear all the arch related bits manually is because ToggleFeature only
295 // clears the features that imply the feature being cleared and not the
296 // features implied by the feature being cleared. This is easier to see
297 // with an example:
298 // --------------------------------------------------
299 // | Feature | Implies |
300 // | -------------------------------------------------|
301 // | FeatureMips1 | None |
302 // | FeatureMips2 | FeatureMips1 |
303 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
304 // | FeatureMips4 | FeatureMips3 |
305 // | ... | |
306 // --------------------------------------------------
307 //
308 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
309 // FeatureMipsGP64 | FeatureMips1)
310 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
311 void selectArch(StringRef ArchFeature) {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000312 uint64_t FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000313 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
314 STI.setFeatureBits(FeatureBits);
315 setAvailableFeatures(
316 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000317 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000318 }
319
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000320 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000321 if (!(STI.getFeatureBits() & Feature)) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000322 setAvailableFeatures(
323 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000324 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000325 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000326 }
327
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000328 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000329 if (STI.getFeatureBits() & Feature) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000330 setAvailableFeatures(
331 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000332 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000333 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000334 }
335
Rafael Espindola870c4e92012-01-11 03:56:41 +0000336public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000337 enum MipsMatchResultTy {
338 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
339#define GET_OPERAND_DIAGNOSTIC_TYPES
340#include "MipsGenAsmMatcher.inc"
341#undef GET_OPERAND_DIAGNOSTIC_TYPES
342
343 };
344
Joey Gouly0e76fa72013-09-12 10:28:05 +0000345 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000346 const MCInstrInfo &MII, const MCTargetOptions &Options)
Eric Christophera5762812015-01-26 17:33:46 +0000347 : MCTargetAsmParser(), STI(sti),
348 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
349 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000350 MCAsmParserExtension::Initialize(parser);
351
Toma Tabacu11e14a92015-04-21 11:50:52 +0000352 parser.addAliasForDirective(".asciiz", ".asciz");
353
Jack Carterb4dbc172012-09-05 23:34:03 +0000354 // Initialize the set of available features.
355 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000356
357 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000358 AssemblerOptions.push_back(
359 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000360
361 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000362 AssemblerOptions.push_back(
363 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000364
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000365 getTargetStreamer().updateABIInfo(*this);
366
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000367 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000368 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000369
370 CurrentFn = nullptr;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000371 }
372
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000373 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
374 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
375
Michael Kuperstein29704e72015-03-24 12:56:59 +0000376 bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; }
377 bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; }
Eric Christophera5762812015-01-26 17:33:46 +0000378 const MipsABIInfo &getABI() const { return ABI; }
379 bool isABI_N32() const { return ABI.IsN32(); }
380 bool isABI_N64() const { return ABI.IsN64(); }
381 bool isABI_O32() const { return ABI.IsO32(); }
Michael Kuperstein29704e72015-03-24 12:56:59 +0000382 bool isABI_FPXX() const { return STI.getFeatureBits() & Mips::FeatureFPXX; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000383
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000384 bool useOddSPReg() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000385 return !(STI.getFeatureBits() & Mips::FeatureNoOddSPReg);
Daniel Sanders7e527422014-07-10 13:38:23 +0000386 }
387
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000388 bool inMicroMipsMode() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000389 return STI.getFeatureBits() & Mips::FeatureMicroMips;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000390 }
Michael Kuperstein29704e72015-03-24 12:56:59 +0000391 bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; }
392 bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; }
393 bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; }
394 bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
395 bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000396 bool hasMips32() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000397 return (STI.getFeatureBits() & Mips::FeatureMips32);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000398 }
399 bool hasMips64() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000400 return (STI.getFeatureBits() & Mips::FeatureMips64);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000401 }
402 bool hasMips32r2() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000403 return (STI.getFeatureBits() & Mips::FeatureMips32r2);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000404 }
405 bool hasMips64r2() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000406 return (STI.getFeatureBits() & Mips::FeatureMips64r2);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000407 }
Daniel Sanders17793142015-02-18 16:24:50 +0000408 bool hasMips32r3() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000409 return (STI.getFeatureBits() & Mips::FeatureMips32r3);
Daniel Sanders17793142015-02-18 16:24:50 +0000410 }
411 bool hasMips64r3() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000412 return (STI.getFeatureBits() & Mips::FeatureMips64r3);
Daniel Sanders17793142015-02-18 16:24:50 +0000413 }
414 bool hasMips32r5() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000415 return (STI.getFeatureBits() & Mips::FeatureMips32r5);
Daniel Sanders17793142015-02-18 16:24:50 +0000416 }
417 bool hasMips64r5() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000418 return (STI.getFeatureBits() & Mips::FeatureMips64r5);
Daniel Sanders17793142015-02-18 16:24:50 +0000419 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000420 bool hasMips32r6() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000421 return (STI.getFeatureBits() & Mips::FeatureMips32r6);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000422 }
423 bool hasMips64r6() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000424 return (STI.getFeatureBits() & Mips::FeatureMips64r6);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000425 }
Kai Nackee0245392015-01-27 19:11:28 +0000426 bool hasCnMips() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000427 return (STI.getFeatureBits() & Mips::FeatureCnMips);
Kai Nackee0245392015-01-27 19:11:28 +0000428 }
Michael Kuperstein29704e72015-03-24 12:56:59 +0000429 bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
430 bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
431 bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000432
433 bool inMips16Mode() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000434 return STI.getFeatureBits() & Mips::FeatureMips16;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000435 }
436 // TODO: see how can we get this info.
Eric Christopher7394e232014-07-18 00:08:50 +0000437 bool abiUsesSoftFloat() const { return false; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000438
Toma Tabacud9d344b2015-04-27 14:05:04 +0000439 /// Warn if RegIndex is the same as the current AT.
440 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000441};
442}
443
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000444namespace {
445
446/// MipsOperand - Instances of this class represent a parsed Mips machine
447/// instruction.
448class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000449public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000450 /// Broad categories of register classes
451 /// The exact class is finalized by the render method.
452 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000453 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000454 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000455 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000456 RegKind_FCC = 4, /// FCC
457 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
458 RegKind_MSACtrl = 16, /// MSA control registers
459 RegKind_COP2 = 32, /// COP2
460 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
461 /// context).
462 RegKind_CCR = 128, /// CCR
463 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000464 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000465
466 /// Potentially any (e.g. $1)
467 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
468 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000469 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000470 };
471
472private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000473 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000474 k_Immediate, /// An immediate (possibly involving symbol references)
475 k_Memory, /// Base + Offset Memory Address
476 k_PhysRegister, /// A physical register from the Mips namespace
477 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000478 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000479 k_RegList, /// A physical register list
480 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000481 } Kind;
482
David Blaikie960ea3f2014-06-08 16:18:35 +0000483public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000484 MipsOperand(KindTy K, MipsAsmParser &Parser)
485 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
486
David Blaikie960ea3f2014-06-08 16:18:35 +0000487private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000488 /// For diagnostics, and checking the assembler temporary
489 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000490
Eric Christopher8996c5d2013-03-15 00:42:55 +0000491 struct Token {
492 const char *Data;
493 unsigned Length;
494 };
495
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000496 struct PhysRegOp {
497 unsigned Num; /// Register Number
498 };
499
500 struct RegIdxOp {
501 unsigned Index; /// Index into the register class
502 RegKind Kind; /// Bitfield of the kinds it could possibly be
503 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000504 };
505
506 struct ImmOp {
507 const MCExpr *Val;
508 };
509
510 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000511 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000512 const MCExpr *Off;
513 };
514
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000515 struct RegListOp {
516 SmallVector<unsigned, 10> *List;
517 };
518
Jack Carterb4dbc172012-09-05 23:34:03 +0000519 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000520 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000521 struct PhysRegOp PhysReg;
522 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000523 struct ImmOp Imm;
524 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000525 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000526 };
527
528 SMLoc StartLoc, EndLoc;
529
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000530 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000531 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
532 const MCRegisterInfo *RegInfo,
533 SMLoc S, SMLoc E,
534 MipsAsmParser &Parser) {
535 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000536 Op->RegIdx.Index = Index;
537 Op->RegIdx.RegInfo = RegInfo;
538 Op->RegIdx.Kind = RegKind;
539 Op->StartLoc = S;
540 Op->EndLoc = E;
541 return Op;
542 }
543
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000544public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000545 /// Coerce the register to GPR32 and return the real register for the current
546 /// target.
547 unsigned getGPR32Reg() const {
548 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000549 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000550 unsigned ClassID = Mips::GPR32RegClassID;
551 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000552 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000553
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000554 /// Coerce the register to GPR32 and return the real register for the current
555 /// target.
556 unsigned getGPRMM16Reg() const {
557 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
558 unsigned ClassID = Mips::GPR32RegClassID;
559 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
560 }
561
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000562 /// Coerce the register to GPR64 and return the real register for the current
563 /// target.
564 unsigned getGPR64Reg() const {
565 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
566 unsigned ClassID = Mips::GPR64RegClassID;
567 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000568 }
569
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000570private:
571 /// Coerce the register to AFGR64 and return the real register for the current
572 /// target.
573 unsigned getAFGR64Reg() const {
574 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
575 if (RegIdx.Index % 2 != 0)
576 AsmParser.Warning(StartLoc, "Float register should be even.");
577 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
578 .getRegister(RegIdx.Index / 2);
579 }
580
581 /// Coerce the register to FGR64 and return the real register for the current
582 /// target.
583 unsigned getFGR64Reg() const {
584 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
585 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
586 .getRegister(RegIdx.Index);
587 }
588
589 /// Coerce the register to FGR32 and return the real register for the current
590 /// target.
591 unsigned getFGR32Reg() const {
592 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
593 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
594 .getRegister(RegIdx.Index);
595 }
596
597 /// Coerce the register to FGRH32 and return the real register for the current
598 /// target.
599 unsigned getFGRH32Reg() const {
600 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
601 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
602 .getRegister(RegIdx.Index);
603 }
604
605 /// Coerce the register to FCC and return the real register for the current
606 /// target.
607 unsigned getFCCReg() const {
608 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
609 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
610 .getRegister(RegIdx.Index);
611 }
612
613 /// Coerce the register to MSA128 and return the real register for the current
614 /// target.
615 unsigned getMSA128Reg() const {
616 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
617 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
618 // identical
619 unsigned ClassID = Mips::MSA128BRegClassID;
620 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
621 }
622
623 /// Coerce the register to MSACtrl and return the real register for the
624 /// current target.
625 unsigned getMSACtrlReg() const {
626 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
627 unsigned ClassID = Mips::MSACtrlRegClassID;
628 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
629 }
630
631 /// Coerce the register to COP2 and return the real register for the
632 /// current target.
633 unsigned getCOP2Reg() const {
634 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
635 unsigned ClassID = Mips::COP2RegClassID;
636 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
637 }
638
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000639 /// Coerce the register to COP3 and return the real register for the
640 /// current target.
641 unsigned getCOP3Reg() const {
642 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
643 unsigned ClassID = Mips::COP3RegClassID;
644 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
645 }
646
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000647 /// Coerce the register to ACC64DSP and return the real register for the
648 /// current target.
649 unsigned getACC64DSPReg() const {
650 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
651 unsigned ClassID = Mips::ACC64DSPRegClassID;
652 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
653 }
654
655 /// Coerce the register to HI32DSP and return the real register for the
656 /// current target.
657 unsigned getHI32DSPReg() const {
658 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
659 unsigned ClassID = Mips::HI32DSPRegClassID;
660 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
661 }
662
663 /// Coerce the register to LO32DSP and return the real register for the
664 /// current target.
665 unsigned getLO32DSPReg() const {
666 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
667 unsigned ClassID = Mips::LO32DSPRegClassID;
668 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
669 }
670
671 /// Coerce the register to CCR and return the real register for the
672 /// current target.
673 unsigned getCCRReg() const {
674 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
675 unsigned ClassID = Mips::CCRRegClassID;
676 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
677 }
678
679 /// Coerce the register to HWRegs and return the real register for the
680 /// current target.
681 unsigned getHWRegsReg() const {
682 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
683 unsigned ClassID = Mips::HWRegsRegClassID;
684 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
685 }
686
687public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000688 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000689 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000690 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000691 Inst.addOperand(MCOperand::CreateImm(0));
692 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
693 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
694 else
695 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000696 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000697
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000698 void addRegOperands(MCInst &Inst, unsigned N) const {
699 llvm_unreachable("Use a custom parser instead");
700 }
701
Daniel Sanders21bce302014-04-01 12:35:23 +0000702 /// Render the operand to an MCInst as a GPR32
703 /// Asserts if the wrong number of operands are requested, or the operand
704 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000705 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
706 assert(N == 1 && "Invalid number of operands!");
707 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
708 }
709
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000710 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
711 assert(N == 1 && "Invalid number of operands!");
712 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
713 }
714
Jozef Kolek1904fa22014-11-24 14:25:53 +0000715 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
716 assert(N == 1 && "Invalid number of operands!");
717 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
718 }
719
Zoran Jovanovic41688672015-02-10 16:36:20 +0000720 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
721 assert(N == 1 && "Invalid number of operands!");
722 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
723 }
724
Daniel Sanders21bce302014-04-01 12:35:23 +0000725 /// Render the operand to an MCInst as a GPR64
726 /// Asserts if the wrong number of operands are requested, or the operand
727 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000728 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
729 assert(N == 1 && "Invalid number of operands!");
730 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
731 }
732
733 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
734 assert(N == 1 && "Invalid number of operands!");
735 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
736 }
737
738 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
739 assert(N == 1 && "Invalid number of operands!");
740 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
741 }
742
743 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
744 assert(N == 1 && "Invalid number of operands!");
745 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000746 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000747 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000748 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
749 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000750 }
751
752 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
753 assert(N == 1 && "Invalid number of operands!");
754 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
755 }
756
757 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
758 assert(N == 1 && "Invalid number of operands!");
759 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
760 }
761
762 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
763 assert(N == 1 && "Invalid number of operands!");
764 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
765 }
766
767 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
768 assert(N == 1 && "Invalid number of operands!");
769 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
770 }
771
772 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
773 assert(N == 1 && "Invalid number of operands!");
774 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
775 }
776
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000777 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
778 assert(N == 1 && "Invalid number of operands!");
779 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
780 }
781
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000782 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
783 assert(N == 1 && "Invalid number of operands!");
784 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
785 }
786
787 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
788 assert(N == 1 && "Invalid number of operands!");
789 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
790 }
791
792 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
793 assert(N == 1 && "Invalid number of operands!");
794 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
795 }
796
797 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
798 assert(N == 1 && "Invalid number of operands!");
799 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
800 }
801
802 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
803 assert(N == 1 && "Invalid number of operands!");
804 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
805 }
806
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000807 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000808 assert(N == 1 && "Invalid number of operands!");
809 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000810 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000811 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000812
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000813 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000814 assert(N == 2 && "Invalid number of operands!");
815
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000816 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000817
818 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000819 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000820 }
821
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000822 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
823 assert(N == 2 && "Invalid number of operands!");
824
825 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPRMM16Reg()));
826
827 const MCExpr *Expr = getMemOff();
828 addExpr(Inst, Expr);
829 }
830
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000831 void addRegListOperands(MCInst &Inst, unsigned N) const {
832 assert(N == 1 && "Invalid number of operands!");
833
834 for (auto RegNo : getRegList())
835 Inst.addOperand(MCOperand::CreateReg(RegNo));
836 }
837
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000838 void addRegPairOperands(MCInst &Inst, unsigned N) const {
839 assert(N == 2 && "Invalid number of operands!");
840 unsigned RegNo = getRegPair();
841 Inst.addOperand(MCOperand::CreateReg(RegNo++));
842 Inst.addOperand(MCOperand::CreateReg(RegNo));
843 }
844
Zoran Jovanovic41688672015-02-10 16:36:20 +0000845 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
846 assert(N == 2 && "Invalid number of operands!");
847 for (auto RegNo : getRegList())
848 Inst.addOperand(MCOperand::CreateReg(RegNo));
849 }
850
Craig Topper56c590a2014-04-29 07:58:02 +0000851 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000852 // As a special case until we sort out the definition of div/divu, pretend
853 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
854 if (isGPRAsmReg() && RegIdx.Index == 0)
855 return true;
856
857 return Kind == k_PhysRegister;
858 }
859 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000860 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000861 bool isConstantImm() const {
862 return isImm() && dyn_cast<MCConstantExpr>(getImm());
863 }
Craig Topper56c590a2014-04-29 07:58:02 +0000864 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000865 // Note: It's not possible to pretend that other operand kinds are tokens.
866 // The matcher emitter checks tokens first.
867 return Kind == k_Token;
868 }
Craig Topper56c590a2014-04-29 07:58:02 +0000869 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000870 bool isConstantMemOff() const {
871 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
872 }
873 template <unsigned Bits> bool isMemWithSimmOffset() const {
874 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
875 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000876 bool isMemWithGRPMM16Base() const {
877 return isMem() && getMemBase()->isMM16AsmReg();
878 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000879 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
880 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
881 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
882 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000883 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
884 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
885 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
886 && (getMemBase()->getGPR32Reg() == Mips::SP);
887 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000888 bool isRegList16() const {
889 if (!isRegList())
890 return false;
891
892 int Size = RegList.List->size();
893 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
894 RegList.List->back() != Mips::RA)
895 return false;
896
897 int PrevReg = *RegList.List->begin();
898 for (int i = 1; i < Size - 1; i++) {
899 int Reg = (*(RegList.List))[i];
900 if ( Reg != PrevReg + 1)
901 return false;
902 PrevReg = Reg;
903 }
904
905 return true;
906 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000907 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000908 bool isLSAImm() const {
909 if (!isConstantImm())
910 return false;
911 int64_t Val = getConstantImm();
912 return 1 <= Val && Val <= 4;
913 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000914 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +0000915 bool isMovePRegPair() const {
916 if (Kind != k_RegList || RegList.List->size() != 2)
917 return false;
918
919 unsigned R0 = RegList.List->front();
920 unsigned R1 = RegList.List->back();
921
922 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
923 (R0 == Mips::A1 && R1 == Mips::A3) ||
924 (R0 == Mips::A2 && R1 == Mips::A3) ||
925 (R0 == Mips::A0 && R1 == Mips::S5) ||
926 (R0 == Mips::A0 && R1 == Mips::S6) ||
927 (R0 == Mips::A0 && R1 == Mips::A1) ||
928 (R0 == Mips::A0 && R1 == Mips::A2) ||
929 (R0 == Mips::A0 && R1 == Mips::A3))
930 return true;
931
932 return false;
933 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000934
935 StringRef getToken() const {
936 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000937 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000938 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000939 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000940
Craig Topper56c590a2014-04-29 07:58:02 +0000941 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000942 // As a special case until we sort out the definition of div/divu, pretend
943 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
944 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
945 RegIdx.Kind & RegKind_GPR)
946 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000947
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000948 assert(Kind == k_PhysRegister && "Invalid access!");
949 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000950 }
951
Jack Carterb4dbc172012-09-05 23:34:03 +0000952 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000953 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000954 return Imm.Val;
955 }
956
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000957 int64_t getConstantImm() const {
958 const MCExpr *Val = getImm();
959 return static_cast<const MCConstantExpr *>(Val)->getValue();
960 }
961
962 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000963 assert((Kind == k_Memory) && "Invalid access!");
964 return Mem.Base;
965 }
966
967 const MCExpr *getMemOff() const {
968 assert((Kind == k_Memory) && "Invalid access!");
969 return Mem.Off;
970 }
971
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000972 int64_t getConstantMemOff() const {
973 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
974 }
975
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000976 const SmallVectorImpl<unsigned> &getRegList() const {
977 assert((Kind == k_RegList) && "Invalid access!");
978 return *(RegList.List);
979 }
980
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000981 unsigned getRegPair() const {
982 assert((Kind == k_RegPair) && "Invalid access!");
983 return RegIdx.Index;
984 }
985
David Blaikie960ea3f2014-06-08 16:18:35 +0000986 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
987 MipsAsmParser &Parser) {
988 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000989 Op->Tok.Data = Str.data();
990 Op->Tok.Length = Str.size();
991 Op->StartLoc = S;
992 Op->EndLoc = S;
993 return Op;
994 }
995
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000996 /// Create a numeric register (e.g. $1). The exact register remains
997 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +0000998 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000999 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001000 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001001 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001002 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001003 }
1004
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001005 /// Create a register that is definitely a GPR.
1006 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001007 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001008 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001009 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001010 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001011 }
1012
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001013 /// Create a register that is definitely a FGR.
1014 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001015 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001016 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001017 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001018 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1019 }
1020
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001021 /// Create a register that is definitely a HWReg.
1022 /// This is typically only used for named registers such as $hwr_cpunum.
1023 static std::unique_ptr<MipsOperand>
1024 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1025 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1026 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1027 }
1028
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001029 /// Create a register that is definitely an FCC.
1030 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001031 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001032 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001033 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001034 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1035 }
1036
1037 /// Create a register that is definitely an ACC.
1038 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001039 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001040 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001041 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001042 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1043 }
1044
1045 /// Create a register that is definitely an MSA128.
1046 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001047 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001048 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001049 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001050 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1051 }
1052
1053 /// Create a register that is definitely an MSACtrl.
1054 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001055 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001056 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001057 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001058 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1059 }
1060
David Blaikie960ea3f2014-06-08 16:18:35 +00001061 static std::unique_ptr<MipsOperand>
1062 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1063 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001064 Op->Imm.Val = Val;
1065 Op->StartLoc = S;
1066 Op->EndLoc = E;
1067 return Op;
1068 }
1069
David Blaikie960ea3f2014-06-08 16:18:35 +00001070 static std::unique_ptr<MipsOperand>
1071 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1072 SMLoc E, MipsAsmParser &Parser) {
1073 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1074 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001075 Op->Mem.Off = Off;
1076 Op->StartLoc = S;
1077 Op->EndLoc = E;
1078 return Op;
1079 }
1080
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001081 static std::unique_ptr<MipsOperand>
1082 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1083 MipsAsmParser &Parser) {
1084 assert (Regs.size() > 0 && "Empty list not allowed");
1085
1086 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001087 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001088 Op->StartLoc = StartLoc;
1089 Op->EndLoc = EndLoc;
1090 return Op;
1091 }
1092
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001093 static std::unique_ptr<MipsOperand>
1094 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1095 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1096 Op->RegIdx.Index = RegNo;
1097 Op->StartLoc = S;
1098 Op->EndLoc = E;
1099 return Op;
1100 }
1101
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001102 bool isGPRAsmReg() const {
1103 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001104 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001105 bool isMM16AsmReg() const {
1106 if (!(isRegIdx() && RegIdx.Kind))
1107 return false;
1108 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1109 || RegIdx.Index == 16 || RegIdx.Index == 17);
1110 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001111 bool isMM16AsmRegZero() const {
1112 if (!(isRegIdx() && RegIdx.Kind))
1113 return false;
1114 return (RegIdx.Index == 0 ||
1115 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1116 RegIdx.Index == 17);
1117 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001118 bool isMM16AsmRegMoveP() const {
1119 if (!(isRegIdx() && RegIdx.Kind))
1120 return false;
1121 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1122 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1123 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001124 bool isFGRAsmReg() const {
1125 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1126 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001127 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001128 bool isHWRegsAsmReg() const {
1129 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001130 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001131 bool isCCRAsmReg() const {
1132 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001133 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001134 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001135 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1136 return false;
1137 if (!AsmParser.hasEightFccRegisters())
1138 return RegIdx.Index == 0;
1139 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001140 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001141 bool isACCAsmReg() const {
1142 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001143 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001144 bool isCOP2AsmReg() const {
1145 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001146 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001147 bool isCOP3AsmReg() const {
1148 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1149 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001150 bool isMSA128AsmReg() const {
1151 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001152 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001153 bool isMSACtrlAsmReg() const {
1154 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001155 }
1156
Jack Carterb4dbc172012-09-05 23:34:03 +00001157 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001158 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001159 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001160 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001161
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001162 virtual ~MipsOperand() {
1163 switch (Kind) {
1164 case k_Immediate:
1165 break;
1166 case k_Memory:
1167 delete Mem.Base;
1168 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001169 case k_RegList:
1170 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001171 case k_PhysRegister:
1172 case k_RegisterIndex:
1173 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001174 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001175 break;
1176 }
1177 }
1178
Craig Topper56c590a2014-04-29 07:58:02 +00001179 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001180 switch (Kind) {
1181 case k_Immediate:
1182 OS << "Imm<";
1183 Imm.Val->print(OS);
1184 OS << ">";
1185 break;
1186 case k_Memory:
1187 OS << "Mem<";
1188 Mem.Base->print(OS);
1189 OS << ", ";
1190 Mem.Off->print(OS);
1191 OS << ">";
1192 break;
1193 case k_PhysRegister:
1194 OS << "PhysReg<" << PhysReg.Num << ">";
1195 break;
1196 case k_RegisterIndex:
1197 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1198 break;
1199 case k_Token:
1200 OS << Tok.Data;
1201 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001202 case k_RegList:
1203 OS << "RegList< ";
1204 for (auto Reg : (*RegList.List))
1205 OS << Reg << " ";
1206 OS << ">";
1207 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001208 case k_RegPair:
1209 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1210 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001211 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001212 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001213}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001214} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001215
Jack Carter9e65aa32013-03-22 00:05:30 +00001216namespace llvm {
1217extern const MCInstrDesc MipsInsts[];
1218}
1219static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1220 return MipsInsts[Opcode];
1221}
1222
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001223static bool hasShortDelaySlot(unsigned Opcode) {
1224 switch (Opcode) {
1225 case Mips::JALS_MM:
1226 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001227 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001228 case Mips::BGEZALS_MM:
1229 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001230 return true;
1231 default:
1232 return false;
1233 }
1234}
1235
Jack Carter9e65aa32013-03-22 00:05:30 +00001236bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001237 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001238 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001239
Jack Carter9e65aa32013-03-22 00:05:30 +00001240 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001241
1242 if (MCID.isBranch() || MCID.isCall()) {
1243 const unsigned Opcode = Inst.getOpcode();
1244 MCOperand Offset;
1245
1246 switch (Opcode) {
1247 default:
1248 break;
Kai Nackee0245392015-01-27 19:11:28 +00001249 case Mips::BBIT0:
1250 case Mips::BBIT032:
1251 case Mips::BBIT1:
1252 case Mips::BBIT132:
1253 assert(hasCnMips() && "instruction only valid for octeon cpus");
1254 // Fall through
1255
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001256 case Mips::BEQ:
1257 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001258 case Mips::BEQ_MM:
1259 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001260 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001261 Offset = Inst.getOperand(2);
1262 if (!Offset.isImm())
1263 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001264 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001265 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001266 if (OffsetToAlignment(Offset.getImm(),
1267 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001268 return Error(IDLoc, "branch to misaligned address");
1269 break;
1270 case Mips::BGEZ:
1271 case Mips::BGTZ:
1272 case Mips::BLEZ:
1273 case Mips::BLTZ:
1274 case Mips::BGEZAL:
1275 case Mips::BLTZAL:
1276 case Mips::BC1F:
1277 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001278 case Mips::BGEZ_MM:
1279 case Mips::BGTZ_MM:
1280 case Mips::BLEZ_MM:
1281 case Mips::BLTZ_MM:
1282 case Mips::BGEZAL_MM:
1283 case Mips::BLTZAL_MM:
1284 case Mips::BC1F_MM:
1285 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001286 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001287 Offset = Inst.getOperand(1);
1288 if (!Offset.isImm())
1289 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001290 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001291 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001292 if (OffsetToAlignment(Offset.getImm(),
1293 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001294 return Error(IDLoc, "branch to misaligned address");
1295 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001296 case Mips::BEQZ16_MM:
1297 case Mips::BNEZ16_MM:
1298 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1299 Offset = Inst.getOperand(1);
1300 if (!Offset.isImm())
1301 break; // We'll deal with this situation later on when applying fixups.
1302 if (!isIntN(8, Offset.getImm()))
1303 return Error(IDLoc, "branch target out of range");
1304 if (OffsetToAlignment(Offset.getImm(), 2LL))
1305 return Error(IDLoc, "branch to misaligned address");
1306 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001307 }
1308 }
1309
Daniel Sandersa84989a2014-06-16 13:25:35 +00001310 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1311 // We still accept it but it is a normal nop.
1312 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1313 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1314 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1315 "nop instruction");
1316 }
1317
Kai Nackee0245392015-01-27 19:11:28 +00001318 if (hasCnMips()) {
1319 const unsigned Opcode = Inst.getOpcode();
1320 MCOperand Opnd;
1321 int Imm;
1322
1323 switch (Opcode) {
1324 default:
1325 break;
1326
1327 case Mips::BBIT0:
1328 case Mips::BBIT032:
1329 case Mips::BBIT1:
1330 case Mips::BBIT132:
1331 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1332 // The offset is handled above
1333 Opnd = Inst.getOperand(1);
1334 if (!Opnd.isImm())
1335 return Error(IDLoc, "expected immediate operand kind");
1336 Imm = Opnd.getImm();
1337 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1338 Opcode == Mips::BBIT1 ? 63 : 31))
1339 return Error(IDLoc, "immediate operand value out of range");
1340 if (Imm > 31) {
1341 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1342 : Mips::BBIT132);
1343 Inst.getOperand(1).setImm(Imm - 32);
1344 }
1345 break;
1346
1347 case Mips::CINS:
1348 case Mips::CINS32:
1349 case Mips::EXTS:
1350 case Mips::EXTS32:
1351 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1352 // Check length
1353 Opnd = Inst.getOperand(3);
1354 if (!Opnd.isImm())
1355 return Error(IDLoc, "expected immediate operand kind");
1356 Imm = Opnd.getImm();
1357 if (Imm < 0 || Imm > 31)
1358 return Error(IDLoc, "immediate operand value out of range");
1359 // Check position
1360 Opnd = Inst.getOperand(2);
1361 if (!Opnd.isImm())
1362 return Error(IDLoc, "expected immediate operand kind");
1363 Imm = Opnd.getImm();
1364 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1365 Opcode == Mips::EXTS ? 63 : 31))
1366 return Error(IDLoc, "immediate operand value out of range");
1367 if (Imm > 31) {
1368 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1369 Inst.getOperand(2).setImm(Imm - 32);
1370 }
1371 break;
1372
1373 case Mips::SEQi:
1374 case Mips::SNEi:
1375 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1376 Opnd = Inst.getOperand(2);
1377 if (!Opnd.isImm())
1378 return Error(IDLoc, "expected immediate operand kind");
1379 Imm = Opnd.getImm();
1380 if (!isInt<10>(Imm))
1381 return Error(IDLoc, "immediate operand value out of range");
1382 break;
1383 }
1384 }
1385
Jack Carter9e65aa32013-03-22 00:05:30 +00001386 if (MCID.mayLoad() || MCID.mayStore()) {
1387 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001388 // reference or immediate we may have to expand instructions.
1389 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001390 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001391 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1392 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001393 MCOperand &Op = Inst.getOperand(i);
1394 if (Op.isImm()) {
1395 int MemOffset = Op.getImm();
1396 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001397 // Offset can't exceed 16bit value.
1398 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001399 return false;
1400 }
1401 } else if (Op.isExpr()) {
1402 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001403 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001404 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001405 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001406 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001407 // Expand symbol.
1408 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001409 return false;
1410 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001411 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001412 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001413 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001414 }
1415 }
1416 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001417 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001418 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001419
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001420 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001421 if (MCID.mayLoad()) {
1422 // Try to create 16-bit GP relative load instruction.
1423 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1424 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1425 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1426 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1427 MCOperand &Op = Inst.getOperand(i);
1428 if (Op.isImm()) {
1429 int MemOffset = Op.getImm();
1430 MCOperand &DstReg = Inst.getOperand(0);
1431 MCOperand &BaseReg = Inst.getOperand(1);
1432 if (isIntN(9, MemOffset) && (MemOffset % 4 == 0) &&
1433 getContext().getRegisterInfo()->getRegClass(
1434 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
1435 BaseReg.getReg() == Mips::GP) {
1436 MCInst TmpInst;
1437 TmpInst.setLoc(IDLoc);
1438 TmpInst.setOpcode(Mips::LWGP_MM);
1439 TmpInst.addOperand(MCOperand::CreateReg(DstReg.getReg()));
1440 TmpInst.addOperand(MCOperand::CreateReg(Mips::GP));
1441 TmpInst.addOperand(MCOperand::CreateImm(MemOffset));
1442 Instructions.push_back(TmpInst);
1443 return false;
1444 }
1445 }
1446 }
1447 } // for
1448 } // if load
1449
1450 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1451
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001452 MCOperand Opnd;
1453 int Imm;
1454
1455 switch (Inst.getOpcode()) {
1456 default:
1457 break;
1458 case Mips::ADDIUS5_MM:
1459 Opnd = Inst.getOperand(2);
1460 if (!Opnd.isImm())
1461 return Error(IDLoc, "expected immediate operand kind");
1462 Imm = Opnd.getImm();
1463 if (Imm < -8 || Imm > 7)
1464 return Error(IDLoc, "immediate operand value out of range");
1465 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001466 case Mips::ADDIUSP_MM:
1467 Opnd = Inst.getOperand(0);
1468 if (!Opnd.isImm())
1469 return Error(IDLoc, "expected immediate operand kind");
1470 Imm = Opnd.getImm();
1471 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1472 Imm % 4 != 0)
1473 return Error(IDLoc, "immediate operand value out of range");
1474 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001475 case Mips::SLL16_MM:
1476 case Mips::SRL16_MM:
1477 Opnd = Inst.getOperand(2);
1478 if (!Opnd.isImm())
1479 return Error(IDLoc, "expected immediate operand kind");
1480 Imm = Opnd.getImm();
1481 if (Imm < 1 || Imm > 8)
1482 return Error(IDLoc, "immediate operand value out of range");
1483 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001484 case Mips::LI16_MM:
1485 Opnd = Inst.getOperand(1);
1486 if (!Opnd.isImm())
1487 return Error(IDLoc, "expected immediate operand kind");
1488 Imm = Opnd.getImm();
1489 if (Imm < -1 || Imm > 126)
1490 return Error(IDLoc, "immediate operand value out of range");
1491 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001492 case Mips::ADDIUR2_MM:
1493 Opnd = Inst.getOperand(2);
1494 if (!Opnd.isImm())
1495 return Error(IDLoc, "expected immediate operand kind");
1496 Imm = Opnd.getImm();
1497 if (!(Imm == 1 || Imm == -1 ||
1498 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1499 return Error(IDLoc, "immediate operand value out of range");
1500 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001501 case Mips::ADDIUR1SP_MM:
1502 Opnd = Inst.getOperand(1);
1503 if (!Opnd.isImm())
1504 return Error(IDLoc, "expected immediate operand kind");
1505 Imm = Opnd.getImm();
1506 if (OffsetToAlignment(Imm, 4LL))
1507 return Error(IDLoc, "misaligned immediate operand value");
1508 if (Imm < 0 || Imm > 255)
1509 return Error(IDLoc, "immediate operand value out of range");
1510 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001511 case Mips::ANDI16_MM:
1512 Opnd = Inst.getOperand(2);
1513 if (!Opnd.isImm())
1514 return Error(IDLoc, "expected immediate operand kind");
1515 Imm = Opnd.getImm();
1516 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1517 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1518 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1519 return Error(IDLoc, "immediate operand value out of range");
1520 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001521 case Mips::LBU16_MM:
1522 Opnd = Inst.getOperand(2);
1523 if (!Opnd.isImm())
1524 return Error(IDLoc, "expected immediate operand kind");
1525 Imm = Opnd.getImm();
1526 if (Imm < -1 || Imm > 14)
1527 return Error(IDLoc, "immediate operand value out of range");
1528 break;
1529 case Mips::SB16_MM:
1530 Opnd = Inst.getOperand(2);
1531 if (!Opnd.isImm())
1532 return Error(IDLoc, "expected immediate operand kind");
1533 Imm = Opnd.getImm();
1534 if (Imm < 0 || Imm > 15)
1535 return Error(IDLoc, "immediate operand value out of range");
1536 break;
1537 case Mips::LHU16_MM:
1538 case Mips::SH16_MM:
1539 Opnd = Inst.getOperand(2);
1540 if (!Opnd.isImm())
1541 return Error(IDLoc, "expected immediate operand kind");
1542 Imm = Opnd.getImm();
1543 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1544 return Error(IDLoc, "immediate operand value out of range");
1545 break;
1546 case Mips::LW16_MM:
1547 case Mips::SW16_MM:
1548 Opnd = Inst.getOperand(2);
1549 if (!Opnd.isImm())
1550 return Error(IDLoc, "expected immediate operand kind");
1551 Imm = Opnd.getImm();
1552 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1553 return Error(IDLoc, "immediate operand value out of range");
1554 break;
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001555 case Mips::CACHE:
1556 case Mips::PREF:
1557 Opnd = Inst.getOperand(2);
1558 if (!Opnd.isImm())
1559 return Error(IDLoc, "expected immediate operand kind");
1560 Imm = Opnd.getImm();
1561 if (!isUInt<5>(Imm))
1562 return Error(IDLoc, "immediate operand value out of range");
1563 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001564 case Mips::ADDIUPC_MM:
1565 MCOperand Opnd = Inst.getOperand(1);
1566 if (!Opnd.isImm())
1567 return Error(IDLoc, "expected immediate operand kind");
1568 int Imm = Opnd.getImm();
1569 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1570 return Error(IDLoc, "immediate operand value out of range");
1571 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001572 }
1573 }
1574
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001575 if (needsExpansion(Inst)) {
1576 if (expandInstruction(Inst, IDLoc, Instructions))
1577 return true;
1578 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001579 Instructions.push_back(Inst);
1580
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001581 // If this instruction has a delay slot and .set reorder is active,
1582 // emit a NOP after it.
1583 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1584 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1585
Jack Carter9e65aa32013-03-22 00:05:30 +00001586 return false;
1587}
1588
Jack Carter30a59822012-10-04 04:03:53 +00001589bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1590
Jack Carterd0bd6422013-04-18 00:41:53 +00001591 switch (Inst.getOpcode()) {
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001592 case Mips::LoadImm32:
1593 case Mips::LoadImm64:
1594 case Mips::LoadAddrImm32:
1595 case Mips::LoadAddrReg32:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001596 case Mips::B_MM_Pseudo:
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001597 case Mips::LWM_MM:
1598 case Mips::SWM_MM:
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001599 case Mips::JalOneReg:
1600 case Mips::JalTwoReg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001601 return true;
1602 default:
1603 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001604 }
1605}
Jack Carter92995f12012-10-06 00:53:28 +00001606
Matheus Almeida3813d572014-06-19 14:39:14 +00001607bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001608 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001609 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001610 default: llvm_unreachable("unimplemented expansion");
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001611 case Mips::LoadImm32:
Jack Carterd0bd6422013-04-18 00:41:53 +00001612 return expandLoadImm(Inst, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001613 case Mips::LoadImm64:
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001614 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001615 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001616 return true;
1617 }
1618 return expandLoadImm(Inst, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001619 case Mips::LoadAddrImm32:
Jack Carterd0bd6422013-04-18 00:41:53 +00001620 return expandLoadAddressImm(Inst, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001621 case Mips::LoadAddrReg32:
Jack Carterd0bd6422013-04-18 00:41:53 +00001622 return expandLoadAddressReg(Inst, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001623 case Mips::B_MM_Pseudo:
1624 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001625 case Mips::SWM_MM:
1626 case Mips::LWM_MM:
1627 return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001628 case Mips::JalOneReg:
1629 case Mips::JalTwoReg:
1630 return expandJalWithRegs(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001631 }
Jack Carter30a59822012-10-04 04:03:53 +00001632}
Jack Carter92995f12012-10-06 00:53:28 +00001633
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001634namespace {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001635template <bool PerformShift>
1636void createShiftOr(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001637 SmallVectorImpl<MCInst> &Instructions) {
1638 MCInst tmpInst;
1639 if (PerformShift) {
1640 tmpInst.setOpcode(Mips::DSLL);
1641 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1642 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1643 tmpInst.addOperand(MCOperand::CreateImm(16));
1644 tmpInst.setLoc(IDLoc);
1645 Instructions.push_back(tmpInst);
1646 tmpInst.clear();
1647 }
1648 tmpInst.setOpcode(Mips::ORi);
1649 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1650 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001651 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001652 tmpInst.setLoc(IDLoc);
1653 Instructions.push_back(tmpInst);
1654}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001655
1656template <int Shift, bool PerformShift>
1657void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1658 SmallVectorImpl<MCInst> &Instructions) {
1659 createShiftOr<PerformShift>(
1660 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)), RegNo,
1661 IDLoc, Instructions);
1662}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001663}
1664
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001665bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
1666 SmallVectorImpl<MCInst> &Instructions) {
1667 // Create a JALR instruction which is going to replace the pseudo-JAL.
1668 MCInst JalrInst;
1669 JalrInst.setLoc(IDLoc);
1670 const MCOperand FirstRegOp = Inst.getOperand(0);
1671 const unsigned Opcode = Inst.getOpcode();
1672
1673 if (Opcode == Mips::JalOneReg) {
1674 // jal $rs => jalr $rs
1675 if (inMicroMipsMode()) {
1676 JalrInst.setOpcode(Mips::JALR16_MM);
1677 JalrInst.addOperand(FirstRegOp);
1678 } else {
1679 JalrInst.setOpcode(Mips::JALR);
1680 JalrInst.addOperand(MCOperand::CreateReg(Mips::RA));
1681 JalrInst.addOperand(FirstRegOp);
1682 }
1683 } else if (Opcode == Mips::JalTwoReg) {
1684 // jal $rd, $rs => jalr $rd, $rs
1685 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
1686 JalrInst.addOperand(FirstRegOp);
1687 const MCOperand SecondRegOp = Inst.getOperand(1);
1688 JalrInst.addOperand(SecondRegOp);
1689 }
1690 Instructions.push_back(JalrInst);
1691
1692 // If .set reorder is active, emit a NOP after it.
1693 if (AssemblerOptions.back()->isReorder()) {
1694 // This is a 32-bit NOP because these 2 pseudo-instructions
1695 // do not have a short delay slot.
1696 MCInst NopInst;
1697 NopInst.setOpcode(Mips::SLL);
1698 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1699 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1700 NopInst.addOperand(MCOperand::CreateImm(0));
1701 Instructions.push_back(NopInst);
1702 }
1703
1704 return false;
1705}
1706
Matheus Almeida3813d572014-06-19 14:39:14 +00001707bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001708 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001709 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001710 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001711 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001712 const MCOperand &RegOp = Inst.getOperand(0);
1713 assert(RegOp.isReg() && "expected register operand kind");
1714
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001715 int64_t ImmValue = ImmOp.getImm();
Toma Tabacu137d90a2015-04-28 12:04:53 +00001716 unsigned Reg = RegOp.getReg();
Jack Carter92995f12012-10-06 00:53:28 +00001717 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001718 // FIXME: gas has a special case for values that are 000...1111, which
1719 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001720 if (0 <= ImmValue && ImmValue <= 65535) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001721 // For unsigned and positive signed 16-bit values (0 <= j <= 65535):
Jack Carter30a59822012-10-04 04:03:53 +00001722 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001723 tmpInst.setOpcode(Mips::ORi);
Toma Tabacu137d90a2015-04-28 12:04:53 +00001724 tmpInst.addOperand(MCOperand::CreateReg(Reg));
Jack Carterd0bd6422013-04-18 00:41:53 +00001725 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001726 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001727 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001728 } else if (ImmValue < 0 && ImmValue >= -32768) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001729 // For negative signed 16-bit values (-32768 <= j < 0):
Jack Carter30a59822012-10-04 04:03:53 +00001730 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001731 tmpInst.setOpcode(Mips::ADDiu);
Toma Tabacu137d90a2015-04-28 12:04:53 +00001732 tmpInst.addOperand(MCOperand::CreateReg(Reg));
Jack Carterd0bd6422013-04-18 00:41:53 +00001733 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001734 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001735 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001736 } else if ((ImmValue & 0xffffffff) == ImmValue) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001737 // For all other values which are representable as a 32-bit integer:
Jack Carter30a59822012-10-04 04:03:53 +00001738 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001739 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001740 tmpInst.setOpcode(Mips::LUi);
Toma Tabacu137d90a2015-04-28 12:04:53 +00001741 tmpInst.addOperand(MCOperand::CreateReg(Reg));
Jack Carter92995f12012-10-06 00:53:28 +00001742 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001743 Instructions.push_back(tmpInst);
Toma Tabacu137d90a2015-04-28 12:04:53 +00001744 createShiftOr<0, false>(ImmValue, Reg, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001745 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001746 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001747 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001748 return true;
1749 }
1750
1751 // <------- lo32 ------>
1752 // <------- hi32 ------>
1753 // <- hi16 -> <- lo16 ->
1754 // _________________________________
1755 // | | | |
Toma Tabacubda745f2015-04-27 15:21:38 +00001756 // | 16-bits | 16-bits | 16-bits |
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001757 // |__________|__________|__________|
1758 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001759 // For any 64-bit value that is representable as a 48-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001760 // li d,j => lui d,hi16(j)
1761 // ori d,d,hi16(lo32(j))
1762 // dsll d,d,16
1763 // ori d,d,lo16(lo32(j))
1764 tmpInst.setOpcode(Mips::LUi);
Toma Tabacu137d90a2015-04-28 12:04:53 +00001765 tmpInst.addOperand(MCOperand::CreateReg(Reg));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001766 tmpInst.addOperand(
1767 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001768 Instructions.push_back(tmpInst);
Toma Tabacu137d90a2015-04-28 12:04:53 +00001769 createShiftOr<16, false>(ImmValue, Reg, IDLoc, Instructions);
1770 createShiftOr<0, true>(ImmValue, Reg, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001771 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001772 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001773 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001774 return true;
1775 }
1776
1777 // <------- hi32 ------> <------- lo32 ------>
1778 // <- hi16 -> <- lo16 ->
1779 // ___________________________________________
1780 // | | | | |
Toma Tabacubda745f2015-04-27 15:21:38 +00001781 // | 16-bits | 16-bits | 16-bits | 16-bits |
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001782 // |__________|__________|__________|__________|
1783 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001784 // For all other values which are representable as a 64-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001785 // li d,j => lui d,hi16(j)
1786 // ori d,d,lo16(hi32(j))
1787 // dsll d,d,16
1788 // ori d,d,hi16(lo32(j))
1789 // dsll d,d,16
1790 // ori d,d,lo16(lo32(j))
1791 tmpInst.setOpcode(Mips::LUi);
Toma Tabacu137d90a2015-04-28 12:04:53 +00001792 tmpInst.addOperand(MCOperand::CreateReg(Reg));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001793 tmpInst.addOperand(
1794 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1795 Instructions.push_back(tmpInst);
Toma Tabacu137d90a2015-04-28 12:04:53 +00001796 createShiftOr<32, false>(ImmValue, Reg, IDLoc, Instructions);
1797 createShiftOr<16, true>(ImmValue, Reg, IDLoc, Instructions);
1798 createShiftOr<0, true>(ImmValue, Reg, IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001799 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001800 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001801}
Jack Carter92995f12012-10-06 00:53:28 +00001802
Matheus Almeida3813d572014-06-19 14:39:14 +00001803bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001804MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1805 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001806 MCInst tmpInst;
1807 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001808 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1809 "expected immediate operand kind");
1810 if (!ImmOp.isImm()) {
1811 expandLoadAddressSym(Inst, IDLoc, Instructions);
1812 return false;
1813 }
Jack Carter543fdf82012-10-09 23:29:45 +00001814 const MCOperand &SrcRegOp = Inst.getOperand(1);
1815 assert(SrcRegOp.isReg() && "expected register operand kind");
1816 const MCOperand &DstRegOp = Inst.getOperand(0);
1817 assert(DstRegOp.isReg() && "expected register operand kind");
1818 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001819 if (-32768 <= ImmValue && ImmValue <= 65535) {
1820 // For -32768 <= j <= 65535.
1821 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001822 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001823 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1824 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1825 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1826 Instructions.push_back(tmpInst);
1827 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001828 // For any other value of j that is representable as a 32-bit integer.
1829 // la d,j(s) => lui d,hi16(j)
1830 // ori d,d,lo16(j)
1831 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001832 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001833 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1834 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1835 Instructions.push_back(tmpInst);
1836 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001837 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001838 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1839 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1840 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1841 Instructions.push_back(tmpInst);
1842 tmpInst.clear();
1843 tmpInst.setOpcode(Mips::ADDu);
1844 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1845 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1846 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1847 Instructions.push_back(tmpInst);
1848 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001849 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001850}
1851
Matheus Almeida3813d572014-06-19 14:39:14 +00001852bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001853MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1854 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001855 MCInst tmpInst;
1856 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001857 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1858 "expected immediate operand kind");
1859 if (!ImmOp.isImm()) {
1860 expandLoadAddressSym(Inst, IDLoc, Instructions);
1861 return false;
1862 }
Jack Carter543fdf82012-10-09 23:29:45 +00001863 const MCOperand &RegOp = Inst.getOperand(0);
1864 assert(RegOp.isReg() && "expected register operand kind");
1865 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001866 if (-32768 <= ImmValue && ImmValue <= 65535) {
1867 // For -32768 <= j <= 65535.
1868 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001869 tmpInst.setOpcode(Mips::ADDiu);
1870 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001871 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001872 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1873 Instructions.push_back(tmpInst);
1874 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001875 // For any other value of j that is representable as a 32-bit integer.
1876 // la d,j => lui d,hi16(j)
1877 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001878 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001879 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1880 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1881 Instructions.push_back(tmpInst);
1882 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001883 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001884 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1885 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1886 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1887 Instructions.push_back(tmpInst);
1888 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001889 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001890}
1891
Toma Tabacu0d64b202014-08-14 10:29:17 +00001892void
1893MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1894 SmallVectorImpl<MCInst> &Instructions) {
1895 // FIXME: If we do have a valid at register to use, we should generate a
1896 // slightly shorter sequence here.
1897 MCInst tmpInst;
1898 int ExprOperandNo = 1;
1899 // Sometimes the assembly parser will get the immediate expression as
1900 // a $zero + an immediate.
1901 if (Inst.getNumOperands() == 3) {
1902 assert(Inst.getOperand(1).getReg() ==
1903 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1904 ExprOperandNo = 2;
1905 }
1906 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1907 assert(SymOp.isExpr() && "expected symbol operand kind");
1908 const MCOperand &RegOp = Inst.getOperand(0);
1909 unsigned RegNo = RegOp.getReg();
1910 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1911 const MCSymbolRefExpr *HiExpr =
1912 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1913 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1914 const MCSymbolRefExpr *LoExpr =
1915 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1916 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1917 if (isGP64bit()) {
1918 // If it's a 64-bit architecture, expand to:
1919 // la d,sym => lui d,highest(sym)
1920 // ori d,d,higher(sym)
1921 // dsll d,d,16
1922 // ori d,d,hi16(sym)
1923 // dsll d,d,16
1924 // ori d,d,lo16(sym)
1925 const MCSymbolRefExpr *HighestExpr =
1926 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1927 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1928 const MCSymbolRefExpr *HigherExpr =
1929 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1930 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1931
1932 tmpInst.setOpcode(Mips::LUi);
1933 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1934 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1935 Instructions.push_back(tmpInst);
1936
1937 createShiftOr<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1938 Instructions);
1939 createShiftOr<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
1940 Instructions);
1941 createShiftOr<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1942 Instructions);
1943 } else {
1944 // Otherwise, expand to:
1945 // la d,sym => lui d,hi16(sym)
1946 // ori d,d,lo16(sym)
1947 tmpInst.setOpcode(Mips::LUi);
1948 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1949 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1950 Instructions.push_back(tmpInst);
1951
1952 createShiftOr<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1953 Instructions);
1954 }
1955}
1956
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00001957bool MipsAsmParser::expandUncondBranchMMPseudo(
1958 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00001959 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
1960 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001961
1962 MCOperand Offset = Inst.getOperand(0);
1963 if (Offset.isExpr()) {
1964 Inst.clear();
1965 Inst.setOpcode(Mips::BEQ_MM);
1966 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1967 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1968 Inst.addOperand(MCOperand::CreateExpr(Offset.getExpr()));
1969 } else {
1970 assert(Offset.isImm() && "expected immediate operand kind");
1971 if (isIntN(11, Offset.getImm())) {
1972 // If offset fits into 11 bits then this instruction becomes microMIPS
1973 // 16-bit unconditional branch instruction.
1974 Inst.setOpcode(Mips::B16_MM);
1975 } else {
1976 if (!isIntN(17, Offset.getImm()))
1977 Error(IDLoc, "branch target out of range");
1978 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
1979 Error(IDLoc, "branch to misaligned address");
1980 Inst.clear();
1981 Inst.setOpcode(Mips::BEQ_MM);
1982 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1983 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1984 Inst.addOperand(MCOperand::CreateImm(Offset.getImm()));
1985 }
1986 }
1987 Instructions.push_back(Inst);
1988
Toma Tabacu234482a2015-03-16 12:03:39 +00001989 // If .set reorder is active, emit a NOP after the branch instruction.
1990 if (AssemblerOptions.back()->isReorder())
1991 createNop(true, IDLoc, Instructions);
1992
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001993 return false;
1994}
1995
Jack Carter9e65aa32013-03-22 00:05:30 +00001996void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001997 SmallVectorImpl<MCInst> &Instructions,
1998 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001999 const MCSymbolRefExpr *SR;
2000 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00002001 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002002 const MCExpr *ExprOffset;
2003 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002004 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002005 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2006 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002007 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002008 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2009 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002010 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002011 if (isImmOpnd) {
2012 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2013 ImmOffset = Inst.getOperand(2).getImm();
2014 LoOffset = ImmOffset & 0x0000ffff;
2015 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002016 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002017 if (LoOffset & 0x8000)
2018 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002019 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002020 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002021 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002022 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002023 // These are some of the types of expansions we perform here:
2024 // 1) lw $8, sym => lui $8, %hi(sym)
2025 // lw $8, %lo(sym)($8)
2026 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2027 // add $8, $8, $9
2028 // lw $8, %lo(offset)($9)
2029 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2030 // add $at, $at, $8
2031 // lw $8, %lo(offset)($at)
2032 // 4) sw $8, sym => lui $at, %hi(sym)
2033 // sw $8, %lo(sym)($at)
2034 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2035 // add $at, $at, $8
2036 // sw $8, %lo(offset)($at)
2037 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2038 // ldc1 $f0, %lo(sym)($at)
2039 //
2040 // For load instructions we can use the destination register as a temporary
2041 // if base and dst are different (examples 1 and 2) and if the base register
2042 // is general purpose otherwise we must use $at (example 6) and error if it's
2043 // not available. For stores we must use $at (examples 4 and 5) because we
2044 // must not clobber the source register setting up the offset.
2045 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2046 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2047 unsigned RegClassIDOp0 =
2048 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2049 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2050 (RegClassIDOp0 == Mips::GPR64RegClassID);
2051 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002052 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002053 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002054 // At this point we need AT to perform the expansions and we exit if it is
2055 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002056 TmpRegNum = getATReg(IDLoc);
2057 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002058 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002059 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002060
Jack Carter9e65aa32013-03-22 00:05:30 +00002061 TempInst.setOpcode(Mips::LUi);
2062 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2063 if (isImmOpnd)
2064 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
2065 else {
2066 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002067 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00002068 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
2069 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
2070 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00002071 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002072 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002073 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00002074 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002075 }
2076 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002077 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002078 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002079 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002080 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002081 // Add temp register to base.
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002082 if (BaseRegNum != Mips::ZERO) {
2083 TempInst.setOpcode(Mips::ADDu);
2084 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2085 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2086 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
2087 Instructions.push_back(TempInst);
2088 TempInst.clear();
2089 }
Alp Tokercb402912014-01-24 17:20:08 +00002090 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002091 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002092 TempInst.setOpcode(Inst.getOpcode());
2093 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
2094 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2095 if (isImmOpnd)
2096 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
2097 else {
2098 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002099 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
2100 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
2101 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00002102 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002103 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002104 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00002105 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002106 }
2107 }
2108 Instructions.push_back(TempInst);
2109 TempInst.clear();
2110}
2111
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002112bool
2113MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2114 SmallVectorImpl<MCInst> &Instructions) {
2115 unsigned OpNum = Inst.getNumOperands();
2116 unsigned Opcode = Inst.getOpcode();
2117 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2118
2119 assert (Inst.getOperand(OpNum - 1).isImm() &&
2120 Inst.getOperand(OpNum - 2).isReg() &&
2121 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2122
2123 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2124 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2125 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2126 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2127 // It can be implemented as SWM16 or LWM16 instruction.
2128 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2129
2130 Inst.setOpcode(NewOpcode);
2131 Instructions.push_back(Inst);
2132 return false;
2133}
2134
Toma Tabacu234482a2015-03-16 12:03:39 +00002135void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
2136 SmallVectorImpl<MCInst> &Instructions) {
2137 MCInst NopInst;
2138 if (hasShortDelaySlot) {
2139 NopInst.setOpcode(Mips::MOVE16_MM);
2140 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2141 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2142 } else {
2143 NopInst.setOpcode(Mips::SLL);
2144 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2145 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2146 NopInst.addOperand(MCOperand::CreateImm(0));
2147 }
2148 Instructions.push_back(NopInst);
2149}
2150
Matheus Almeida595fcab2014-06-11 15:05:56 +00002151unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
2152 // As described by the Mips32r2 spec, the registers Rd and Rs for
2153 // jalr.hb must be different.
2154 unsigned Opcode = Inst.getOpcode();
2155
2156 if (Opcode == Mips::JALR_HB &&
2157 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
2158 return Match_RequiresDifferentSrcAndDst;
2159
2160 return Match_Success;
2161}
2162
David Blaikie960ea3f2014-06-08 16:18:35 +00002163bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
2164 OperandVector &Operands,
2165 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00002166 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00002167 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00002168
Jack Carterb4dbc172012-09-05 23:34:03 +00002169 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00002170 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00002171 unsigned MatchResult =
2172 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00002173
2174 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002175 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002176 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00002177 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00002178 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00002179 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00002180 return false;
2181 }
2182 case Match_MissingFeature:
2183 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
2184 return true;
2185 case Match_InvalidOperand: {
2186 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00002187 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002188 if (ErrorInfo >= Operands.size())
2189 return Error(IDLoc, "too few operands for instruction");
2190
David Blaikie960ea3f2014-06-08 16:18:35 +00002191 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00002192 if (ErrorLoc == SMLoc())
2193 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00002194 }
2195
2196 return Error(ErrorLoc, "invalid operand for instruction");
2197 }
2198 case Match_MnemonicFail:
2199 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00002200 case Match_RequiresDifferentSrcAndDst:
2201 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00002202 }
Craig Topper589ceee2015-01-03 08:16:34 +00002203
2204 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00002205}
2206
Toma Tabacud9d344b2015-04-27 14:05:04 +00002207void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
2208 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
2209 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
2210 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002211}
2212
Daniel Sandersef638fe2014-10-03 15:37:37 +00002213void
2214MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
2215 SMRange Range, bool ShowColors) {
2216 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00002217 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00002218 ShowColors);
2219}
2220
Jack Carter1ac53222013-02-20 23:11:17 +00002221int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002222 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002223
Vladimir Medic4c299852013-11-06 11:27:05 +00002224 CC = StringSwitch<unsigned>(Name)
2225 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002226 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00002227 .Case("a0", 4)
2228 .Case("a1", 5)
2229 .Case("a2", 6)
2230 .Case("a3", 7)
2231 .Case("v0", 2)
2232 .Case("v1", 3)
2233 .Case("s0", 16)
2234 .Case("s1", 17)
2235 .Case("s2", 18)
2236 .Case("s3", 19)
2237 .Case("s4", 20)
2238 .Case("s5", 21)
2239 .Case("s6", 22)
2240 .Case("s7", 23)
2241 .Case("k0", 26)
2242 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002243 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00002244 .Case("sp", 29)
2245 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002246 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00002247 .Case("ra", 31)
2248 .Case("t0", 8)
2249 .Case("t1", 9)
2250 .Case("t2", 10)
2251 .Case("t3", 11)
2252 .Case("t4", 12)
2253 .Case("t5", 13)
2254 .Case("t6", 14)
2255 .Case("t7", 15)
2256 .Case("t8", 24)
2257 .Case("t9", 25)
2258 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002259
Toma Tabacufda445c2014-09-15 15:33:01 +00002260 if (!(isABI_N32() || isABI_N64()))
2261 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002262
Daniel Sandersef638fe2014-10-03 15:37:37 +00002263 if (12 <= CC && CC <= 15) {
2264 // Name is one of t4-t7
2265 AsmToken RegTok = getLexer().peekTok();
2266 SMRange RegRange = RegTok.getLocRange();
2267
2268 StringRef FixedName = StringSwitch<StringRef>(Name)
2269 .Case("t4", "t0")
2270 .Case("t5", "t1")
2271 .Case("t6", "t2")
2272 .Case("t7", "t3")
2273 .Default("");
2274 assert(FixedName != "" && "Register name is not one of t4-t7.");
2275
2276 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
2277 "Did you mean $" + FixedName + "?", RegRange);
2278 }
2279
Toma Tabacufda445c2014-09-15 15:33:01 +00002280 // Although SGI documentation just cuts out t0-t3 for n32/n64,
2281 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
2282 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
2283 if (8 <= CC && CC <= 11)
2284 CC += 4;
2285
2286 if (CC == -1)
2287 CC = StringSwitch<unsigned>(Name)
2288 .Case("a4", 8)
2289 .Case("a5", 9)
2290 .Case("a6", 10)
2291 .Case("a7", 11)
2292 .Case("kt0", 26)
2293 .Case("kt1", 27)
2294 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002295
2296 return CC;
2297}
Jack Carterd0bd6422013-04-18 00:41:53 +00002298
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002299int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
2300 int CC;
2301
2302 CC = StringSwitch<unsigned>(Name)
2303 .Case("hwr_cpunum", 0)
2304 .Case("hwr_synci_step", 1)
2305 .Case("hwr_cc", 2)
2306 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00002307 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002308 .Default(-1);
2309
2310 return CC;
2311}
2312
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002313int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002314
Jack Cartera63b16a2012-09-07 00:23:42 +00002315 if (Name[0] == 'f') {
2316 StringRef NumString = Name.substr(1);
2317 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002318 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002319 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002320 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00002321 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002322 return IntVal;
2323 }
2324 return -1;
2325}
Jack Cartera63b16a2012-09-07 00:23:42 +00002326
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002327int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
2328
2329 if (Name.startswith("fcc")) {
2330 StringRef NumString = Name.substr(3);
2331 unsigned IntVal;
2332 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002333 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002334 if (IntVal > 7) // There are only 8 fcc registers.
2335 return -1;
2336 return IntVal;
2337 }
2338 return -1;
2339}
2340
2341int MipsAsmParser::matchACRegisterName(StringRef Name) {
2342
Akira Hatanaka274d24c2013-08-14 01:15:52 +00002343 if (Name.startswith("ac")) {
2344 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002345 unsigned IntVal;
2346 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002347 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002348 if (IntVal > 3) // There are only 3 acc registers.
2349 return -1;
2350 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00002351 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002352 return -1;
2353}
Jack Carterd0bd6422013-04-18 00:41:53 +00002354
Jack Carter5dc8ac92013-09-25 23:50:44 +00002355int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
2356 unsigned IntVal;
2357
2358 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2359 return -1;
2360
2361 if (IntVal > 31)
2362 return -1;
2363
2364 return IntVal;
2365}
2366
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002367int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
2368 int CC;
2369
2370 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00002371 .Case("msair", 0)
2372 .Case("msacsr", 1)
2373 .Case("msaaccess", 2)
2374 .Case("msasave", 3)
2375 .Case("msamodify", 4)
2376 .Case("msarequest", 5)
2377 .Case("msamap", 6)
2378 .Case("msaunmap", 7)
2379 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002380
2381 return CC;
2382}
2383
Toma Tabacu89a712b2015-04-15 10:48:56 +00002384unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00002385 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00002386 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002387 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00002388 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00002389 return 0;
2390 }
2391 unsigned AT = getReg(
2392 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00002393 return AT;
2394}
Jack Carter0b744b32012-10-04 02:29:46 +00002395
Jack Carterd0bd6422013-04-18 00:41:53 +00002396unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00002397 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00002398}
2399
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002400unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002401 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00002402 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002403}
2404
Jack Carter873c7242013-01-12 01:03:14 +00002405int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002406 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00002407 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00002408 return -1;
2409
Jack Carter873c7242013-01-12 01:03:14 +00002410 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00002411}
2412
Toma Tabacu13964452014-09-04 13:23:44 +00002413bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002414 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002415 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002416
Jack Carter30a59822012-10-04 04:03:53 +00002417 // Check if the current operand has a custom associated parser, if so, try to
2418 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00002419 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2420 if (ResTy == MatchOperand_Success)
2421 return false;
2422 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2423 // there was a match, but an error occurred, in which case, just return that
2424 // the operand parsing failed.
2425 if (ResTy == MatchOperand_ParseFail)
2426 return true;
2427
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002428 DEBUG(dbgs() << ".. Generic Parser\n");
2429
Jack Carterb4dbc172012-09-05 23:34:03 +00002430 switch (getLexer().getKind()) {
2431 default:
2432 Error(Parser.getTok().getLoc(), "unexpected token in operand");
2433 return true;
2434 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002435 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00002436 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00002437
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002438 // Almost all registers have been parsed by custom parsers. There is only
2439 // one exception to this. $zero (and it's alias $0) will reach this point
2440 // for div, divu, and similar instructions because it is not an operand
2441 // to the instruction definition but an explicit register. Special case
2442 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00002443 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00002444 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002445
Jack Carterd0bd6422013-04-18 00:41:53 +00002446 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00002447 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002448 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00002449 return true;
2450
Jack Carter873c7242013-01-12 01:03:14 +00002451 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00002452 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00002453 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00002454 const MCExpr *Res =
2455 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00002456
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002457 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002458 return false;
2459 }
Vladimir Medic4c299852013-11-06 11:27:05 +00002460 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00002461 case AsmToken::LParen:
2462 case AsmToken::Minus:
2463 case AsmToken::Plus:
2464 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002465 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00002466 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002467 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002468 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002469 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00002470 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00002471 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002472 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002473 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002474 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00002475 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00002476 return true;
2477
Jack Carter873c7242013-01-12 01:03:14 +00002478 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2479
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002480 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00002481 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002482 } // case AsmToken::Percent
2483 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00002484 return true;
2485}
2486
Vladimir Medic4c299852013-11-06 11:27:05 +00002487const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00002488 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00002489 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00002490 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002491 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00002492 // It's a constant, evaluate reloc value.
2493 int16_t Val;
2494 switch (getVariantKind(RelocStr)) {
2495 case MCSymbolRefExpr::VK_Mips_ABS_LO:
2496 // Get the 1st 16-bits.
2497 Val = MCE->getValue() & 0xffff;
2498 break;
2499 case MCSymbolRefExpr::VK_Mips_ABS_HI:
2500 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2501 // 16 bits being negative.
2502 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2503 break;
2504 case MCSymbolRefExpr::VK_Mips_HIGHER:
2505 // Get the 3rd 16-bits.
2506 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2507 break;
2508 case MCSymbolRefExpr::VK_Mips_HIGHEST:
2509 // Get the 4th 16-bits.
2510 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2511 break;
2512 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00002513 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00002514 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00002515 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002516 }
2517
Jack Carterb5cf5902013-04-17 00:18:04 +00002518 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002519 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00002520 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00002521 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00002522 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002523 return Res;
2524 }
2525
2526 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00002527 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2528
Sasa Stankovic06c47802014-04-03 10:37:45 +00002529 // Try to create target expression.
2530 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
2531 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002532
Jack Carterd0bd6422013-04-18 00:41:53 +00002533 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2534 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00002535 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
2536 return Res;
2537 }
2538
2539 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002540 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
2541 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
2542 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002543 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002544 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002545 return Expr;
2546}
2547
2548bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2549
2550 switch (Expr->getKind()) {
2551 case MCExpr::Constant:
2552 return true;
2553 case MCExpr::SymbolRef:
2554 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2555 case MCExpr::Binary:
2556 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2557 if (!isEvaluated(BE->getLHS()))
2558 return false;
2559 return isEvaluated(BE->getRHS());
2560 }
2561 case MCExpr::Unary:
2562 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002563 case MCExpr::Target:
2564 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002565 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002566 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002567}
Jack Carterd0bd6422013-04-18 00:41:53 +00002568
Jack Carterb5cf5902013-04-17 00:18:04 +00002569bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002570 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00002571 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002572 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002573 if (Tok.isNot(AsmToken::Identifier))
2574 return true;
2575
Yaron Keren075759a2015-03-30 15:42:36 +00002576 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00002577
Jack Carterd0bd6422013-04-18 00:41:53 +00002578 Parser.Lex(); // Eat the identifier.
2579 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002580 const MCExpr *IdVal;
2581 SMLoc EndLoc;
2582
2583 if (getLexer().getKind() == AsmToken::LParen) {
2584 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002585 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002586 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002587 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002588 const AsmToken &nextTok = Parser.getTok();
2589 if (nextTok.isNot(AsmToken::Identifier))
2590 return true;
2591 Str += "(%";
2592 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002593 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002594 if (getLexer().getKind() != AsmToken::LParen)
2595 return true;
2596 } else
2597 break;
2598 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002599 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002600 return true;
2601
2602 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002603 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002604
2605 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002606 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002607
Jack Carterd0bd6422013-04-18 00:41:53 +00002608 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002609 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002610}
2611
Jack Carterb4dbc172012-09-05 23:34:03 +00002612bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2613 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002614 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002615 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002616 if (ResTy == MatchOperand_Success) {
2617 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002618 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002619 StartLoc = Operand.getStartLoc();
2620 EndLoc = Operand.getEndLoc();
2621
2622 // AFAIK, we only support numeric registers and named GPR's in CFI
2623 // directives.
2624 // Don't worry about eating tokens before failing. Using an unrecognised
2625 // register is a parse error.
2626 if (Operand.isGPRAsmReg()) {
2627 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002628 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002629 }
2630
2631 return (RegNo == (unsigned)-1);
2632 }
2633
2634 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002635 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002636}
2637
Jack Carterb5cf5902013-04-17 00:18:04 +00002638bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002639 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00002640 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002641 bool Result = true;
2642
2643 while (getLexer().getKind() == AsmToken::LParen)
2644 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002645
Jack Carterd0bd6422013-04-18 00:41:53 +00002646 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002647 default:
2648 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002649 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002650 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002651 case AsmToken::Integer:
2652 case AsmToken::Minus:
2653 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002654 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002655 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002656 else
2657 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002658 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002659 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002660 break;
Jack Carter873c7242013-01-12 01:03:14 +00002661 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002662 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002663 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002664 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002665}
2666
David Blaikie960ea3f2014-06-08 16:18:35 +00002667MipsAsmParser::OperandMatchResultTy
2668MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002669 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002670 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002671 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002672 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002673 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002674 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002675 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002676 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002677
Jack Carterb5cf5902013-04-17 00:18:04 +00002678 if (getLexer().getKind() == AsmToken::LParen) {
2679 Parser.Lex();
2680 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002681 }
2682
Jack Carterb5cf5902013-04-17 00:18:04 +00002683 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002684 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002685 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002686
Jack Carterd0bd6422013-04-18 00:41:53 +00002687 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002688 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002689 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2690 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002691 SMLoc E =
2692 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002693 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002694 return MatchOperand_Success;
2695 }
2696 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002697 SMLoc E =
2698 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002699
Jack Carterd0bd6422013-04-18 00:41:53 +00002700 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002701 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002702 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002703 S, E, *this);
2704 Operands.push_back(
2705 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002706 return MatchOperand_Success;
2707 }
2708 Error(Parser.getTok().getLoc(), "'(' expected");
2709 return MatchOperand_ParseFail;
2710 }
2711
Jack Carterd0bd6422013-04-18 00:41:53 +00002712 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002713 }
2714
Toma Tabacu13964452014-09-04 13:23:44 +00002715 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002716 if (Res != MatchOperand_Success)
2717 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002718
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002719 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002720 Error(Parser.getTok().getLoc(), "')' expected");
2721 return MatchOperand_ParseFail;
2722 }
2723
Jack Carter873c7242013-01-12 01:03:14 +00002724 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2725
Jack Carterd0bd6422013-04-18 00:41:53 +00002726 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002727
Craig Topper062a2ba2014-04-25 05:30:21 +00002728 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002729 IdVal = MCConstantExpr::Create(0, getContext());
2730
Jack Carterd0bd6422013-04-18 00:41:53 +00002731 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002732 std::unique_ptr<MipsOperand> op(
2733 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002734 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002735 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002736 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002737 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002738 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2739 int64_t Imm;
2740 if (IdVal->EvaluateAsAbsolute(Imm))
2741 IdVal = MCConstantExpr::Create(Imm, getContext());
2742 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2743 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2744 getContext());
2745 }
2746
David Blaikie960ea3f2014-06-08 16:18:35 +00002747 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002748 return MatchOperand_Success;
2749}
2750
David Blaikie960ea3f2014-06-08 16:18:35 +00002751bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002752 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00002753 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2754 if (Sym) {
2755 SMLoc S = Parser.getTok().getLoc();
2756 const MCExpr *Expr;
2757 if (Sym->isVariable())
2758 Expr = Sym->getVariableValue();
2759 else
2760 return false;
2761 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002762 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002763 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002764 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002765 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002766 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002767 if (ResTy == MatchOperand_Success) {
2768 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002769 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002770 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002771 llvm_unreachable("Should never ParseFail");
2772 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002773 }
2774 } else if (Expr->getKind() == MCExpr::Constant) {
2775 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002776 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002777 Operands.push_back(
2778 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002779 return true;
2780 }
2781 }
2782 return false;
2783}
Jack Carterd0bd6422013-04-18 00:41:53 +00002784
Jack Carter873c7242013-01-12 01:03:14 +00002785MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002786MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002787 StringRef Identifier,
2788 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002789 int Index = matchCPURegisterName(Identifier);
2790 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002791 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002792 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2793 return MatchOperand_Success;
2794 }
2795
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002796 Index = matchHWRegsRegisterName(Identifier);
2797 if (Index != -1) {
2798 Operands.push_back(MipsOperand::createHWRegsReg(
2799 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2800 return MatchOperand_Success;
2801 }
2802
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002803 Index = matchFPURegisterName(Identifier);
2804 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002805 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002806 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2807 return MatchOperand_Success;
2808 }
2809
2810 Index = matchFCCRegisterName(Identifier);
2811 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002812 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002813 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2814 return MatchOperand_Success;
2815 }
2816
2817 Index = matchACRegisterName(Identifier);
2818 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002819 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002820 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2821 return MatchOperand_Success;
2822 }
2823
2824 Index = matchMSA128RegisterName(Identifier);
2825 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002826 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002827 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2828 return MatchOperand_Success;
2829 }
2830
2831 Index = matchMSA128CtrlRegisterName(Identifier);
2832 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002833 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002834 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2835 return MatchOperand_Success;
2836 }
2837
2838 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002839}
2840
2841MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002842MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002843 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00002844 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002845
2846 if (Token.is(AsmToken::Identifier)) {
2847 DEBUG(dbgs() << ".. identifier\n");
2848 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002849 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002850 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002851 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002852 } else if (Token.is(AsmToken::Integer)) {
2853 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002854 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002855 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2856 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002857 return MatchOperand_Success;
2858 }
2859
2860 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2861
2862 return MatchOperand_NoMatch;
2863}
2864
David Blaikie960ea3f2014-06-08 16:18:35 +00002865MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002866MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002867 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002868 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002869
2870 auto Token = Parser.getTok();
2871
2872 SMLoc S = Token.getLoc();
2873
2874 if (Token.isNot(AsmToken::Dollar)) {
2875 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2876 if (Token.is(AsmToken::Identifier)) {
2877 if (searchSymbolAlias(Operands))
2878 return MatchOperand_Success;
2879 }
2880 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2881 return MatchOperand_NoMatch;
2882 }
2883 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002884
Toma Tabacu13964452014-09-04 13:23:44 +00002885 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002886 if (ResTy == MatchOperand_Success) {
2887 Parser.Lex(); // $
2888 Parser.Lex(); // identifier
2889 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002890 return ResTy;
2891}
2892
2893MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002894MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002895 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002896 switch (getLexer().getKind()) {
2897 default:
2898 return MatchOperand_NoMatch;
2899 case AsmToken::LParen:
2900 case AsmToken::Minus:
2901 case AsmToken::Plus:
2902 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002903 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002904 case AsmToken::String:
2905 break;
2906 }
2907
2908 const MCExpr *IdVal;
2909 SMLoc S = Parser.getTok().getLoc();
2910 if (getParser().parseExpression(IdVal))
2911 return MatchOperand_ParseFail;
2912
2913 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2914 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2915 return MatchOperand_Success;
2916}
2917
David Blaikie960ea3f2014-06-08 16:18:35 +00002918MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002919MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002920 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002921 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002922
2923 SMLoc S = getLexer().getLoc();
2924
2925 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002926 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002927 if (ResTy != MatchOperand_NoMatch)
2928 return ResTy;
2929
Daniel Sanders315386c2014-04-01 10:40:14 +00002930 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002931 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002932 if (ResTy != MatchOperand_NoMatch)
2933 return ResTy;
2934
Daniel Sandersffd84362014-04-01 10:41:48 +00002935 const MCExpr *Expr = nullptr;
2936 if (Parser.parseExpression(Expr)) {
2937 // We have no way of knowing if a symbol was consumed so we must ParseFail
2938 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002939 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002940 Operands.push_back(
2941 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002942 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002943}
2944
Vladimir Medic2b953d02013-10-01 09:48:56 +00002945MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002946MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002947 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00002948 const MCExpr *IdVal;
2949 // If the first token is '$' we may have register operand.
2950 if (Parser.getTok().is(AsmToken::Dollar))
2951 return MatchOperand_NoMatch;
2952 SMLoc S = Parser.getTok().getLoc();
2953 if (getParser().parseExpression(IdVal))
2954 return MatchOperand_ParseFail;
2955 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002956 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002957 int64_t Val = MCE->getValue();
2958 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2959 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002960 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002961 return MatchOperand_Success;
2962}
2963
Matheus Almeida779c5932013-11-18 12:32:49 +00002964MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002965MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002966 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00002967 switch (getLexer().getKind()) {
2968 default:
2969 return MatchOperand_NoMatch;
2970 case AsmToken::LParen:
2971 case AsmToken::Plus:
2972 case AsmToken::Minus:
2973 case AsmToken::Integer:
2974 break;
2975 }
2976
2977 const MCExpr *Expr;
2978 SMLoc S = Parser.getTok().getLoc();
2979
2980 if (getParser().parseExpression(Expr))
2981 return MatchOperand_ParseFail;
2982
2983 int64_t Val;
2984 if (!Expr->EvaluateAsAbsolute(Val)) {
2985 Error(S, "expected immediate value");
2986 return MatchOperand_ParseFail;
2987 }
2988
2989 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2990 // and because the CPU always adds one to the immediate field, the allowed
2991 // range becomes 1..4. We'll only check the range here and will deal
2992 // with the addition/subtraction when actually decoding/encoding
2993 // the instruction.
2994 if (Val < 1 || Val > 4) {
2995 Error(S, "immediate not in range (1..4)");
2996 return MatchOperand_ParseFail;
2997 }
2998
Jack Carter3b2c96e2014-01-22 23:31:38 +00002999 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003000 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00003001 return MatchOperand_Success;
3002}
3003
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00003004MipsAsmParser::OperandMatchResultTy
3005MipsAsmParser::parseRegisterList(OperandVector &Operands) {
3006 MCAsmParser &Parser = getParser();
3007 SmallVector<unsigned, 10> Regs;
3008 unsigned RegNo;
3009 unsigned PrevReg = Mips::NoRegister;
3010 bool RegRange = false;
3011 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3012
3013 if (Parser.getTok().isNot(AsmToken::Dollar))
3014 return MatchOperand_ParseFail;
3015
3016 SMLoc S = Parser.getTok().getLoc();
3017 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
3018 SMLoc E = getLexer().getLoc();
3019 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
3020 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
3021 if (RegRange) {
3022 // Remove last register operand because registers from register range
3023 // should be inserted first.
3024 if (RegNo == Mips::RA) {
3025 Regs.push_back(RegNo);
3026 } else {
3027 unsigned TmpReg = PrevReg + 1;
3028 while (TmpReg <= RegNo) {
3029 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
3030 Error(E, "invalid register operand");
3031 return MatchOperand_ParseFail;
3032 }
3033
3034 PrevReg = TmpReg;
3035 Regs.push_back(TmpReg++);
3036 }
3037 }
3038
3039 RegRange = false;
3040 } else {
3041 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
3042 (RegNo != Mips::RA)) {
3043 Error(E, "$16 or $31 expected");
3044 return MatchOperand_ParseFail;
3045 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
3046 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3047 Error(E, "invalid register operand");
3048 return MatchOperand_ParseFail;
3049 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
3050 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3051 Error(E, "consecutive register numbers expected");
3052 return MatchOperand_ParseFail;
3053 }
3054
3055 Regs.push_back(RegNo);
3056 }
3057
3058 if (Parser.getTok().is(AsmToken::Minus))
3059 RegRange = true;
3060
3061 if (!Parser.getTok().isNot(AsmToken::Minus) &&
3062 !Parser.getTok().isNot(AsmToken::Comma)) {
3063 Error(E, "',' or '-' expected");
3064 return MatchOperand_ParseFail;
3065 }
3066
3067 Lex(); // Consume comma or minus
3068 if (Parser.getTok().isNot(AsmToken::Dollar))
3069 break;
3070
3071 PrevReg = RegNo;
3072 }
3073
3074 SMLoc E = Parser.getTok().getLoc();
3075 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3076 parseMemOperand(Operands);
3077 return MatchOperand_Success;
3078}
3079
Zoran Jovanovic2deca342014-12-16 14:59:10 +00003080MipsAsmParser::OperandMatchResultTy
3081MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
3082 MCAsmParser &Parser = getParser();
3083
3084 SMLoc S = Parser.getTok().getLoc();
3085 if (parseAnyRegister(Operands) != MatchOperand_Success)
3086 return MatchOperand_ParseFail;
3087
3088 SMLoc E = Parser.getTok().getLoc();
3089 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
3090 unsigned Reg = Op.getGPR32Reg();
3091 Operands.pop_back();
3092 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
3093 return MatchOperand_Success;
3094}
3095
Zoran Jovanovic41688672015-02-10 16:36:20 +00003096MipsAsmParser::OperandMatchResultTy
3097MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
3098 MCAsmParser &Parser = getParser();
3099 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3100 SmallVector<unsigned, 10> Regs;
3101
3102 if (Parser.getTok().isNot(AsmToken::Dollar))
3103 return MatchOperand_ParseFail;
3104
3105 SMLoc S = Parser.getTok().getLoc();
3106
3107 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3108 return MatchOperand_ParseFail;
3109
3110 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3111 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3112 Regs.push_back(RegNo);
3113
3114 SMLoc E = Parser.getTok().getLoc();
3115 if (Parser.getTok().isNot(AsmToken::Comma)) {
3116 Error(E, "',' expected");
3117 return MatchOperand_ParseFail;
3118 }
3119
3120 // Remove comma.
3121 Parser.Lex();
3122
3123 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3124 return MatchOperand_ParseFail;
3125
3126 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3127 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3128 Regs.push_back(RegNo);
3129
3130 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3131
3132 return MatchOperand_Success;
3133}
3134
Jack Carterdc1e35d2012-09-06 20:00:02 +00003135MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
3136
Vladimir Medic4c299852013-11-06 11:27:05 +00003137 MCSymbolRefExpr::VariantKind VK =
3138 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
3139 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
3140 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
3141 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
3142 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
3143 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
3144 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
3145 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
3146 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
3147 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
3148 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
3149 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
3150 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
3151 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
3152 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
3153 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
3154 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
3155 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00003156 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
3157 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
3158 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
3159 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
3160 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
3161 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00003162 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
3163 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00003164 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003165
Matheus Almeida2852af82014-04-22 10:15:54 +00003166 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00003167
Jack Carterdc1e35d2012-09-06 20:00:02 +00003168 return VK;
3169}
Jack Cartera63b16a2012-09-07 00:23:42 +00003170
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003171/// Sometimes (i.e. load/stores) the operand may be followed immediately by
3172/// either this.
3173/// ::= '(', register, ')'
3174/// handle it before we iterate so we don't get tripped up by the lack of
3175/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003176bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003177 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003178 if (getLexer().is(AsmToken::LParen)) {
3179 Operands.push_back(
3180 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
3181 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003182 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003183 SMLoc Loc = getLexer().getLoc();
3184 Parser.eatToEndOfStatement();
3185 return Error(Loc, "unexpected token in argument list");
3186 }
3187 if (Parser.getTok().isNot(AsmToken::RParen)) {
3188 SMLoc Loc = getLexer().getLoc();
3189 Parser.eatToEndOfStatement();
3190 return Error(Loc, "unexpected token, expected ')'");
3191 }
3192 Operands.push_back(
3193 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
3194 Parser.Lex();
3195 }
3196 return false;
3197}
3198
3199/// Sometimes (i.e. in MSA) the operand may be followed immediately by
3200/// either one of these.
3201/// ::= '[', register, ']'
3202/// ::= '[', integer, ']'
3203/// handle it before we iterate so we don't get tripped up by the lack of
3204/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003205bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00003206 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003207 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003208 if (getLexer().is(AsmToken::LBrac)) {
3209 Operands.push_back(
3210 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
3211 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003212 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003213 SMLoc Loc = getLexer().getLoc();
3214 Parser.eatToEndOfStatement();
3215 return Error(Loc, "unexpected token in argument list");
3216 }
3217 if (Parser.getTok().isNot(AsmToken::RBrac)) {
3218 SMLoc Loc = getLexer().getLoc();
3219 Parser.eatToEndOfStatement();
3220 return Error(Loc, "unexpected token, expected ']'");
3221 }
3222 Operands.push_back(
3223 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
3224 Parser.Lex();
3225 }
3226 return false;
3227}
3228
David Blaikie960ea3f2014-06-08 16:18:35 +00003229bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
3230 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003231 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003232 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003233
3234 // We have reached first instruction, module directive are now forbidden.
3235 getTargetStreamer().forbidModuleDirective();
3236
Vladimir Medic74593e62013-07-17 15:00:42 +00003237 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00003238 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00003239 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00003240 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00003241 }
Vladimir Medic64828a12013-07-16 10:07:14 +00003242 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003243 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003244
3245 // Read the remaining operands.
3246 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3247 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003248 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003249 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003250 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003251 return Error(Loc, "unexpected token in argument list");
3252 }
Toma Tabacu13964452014-09-04 13:23:44 +00003253 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003254 return true;
3255 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00003256
Jack Carterd0bd6422013-04-18 00:41:53 +00003257 while (getLexer().is(AsmToken::Comma)) {
3258 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00003259 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003260 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003261 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003262 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003263 return Error(Loc, "unexpected token in argument list");
3264 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003265 // Parse bracket and parenthesis suffixes before we iterate
3266 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00003267 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003268 return true;
3269 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00003270 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003271 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003272 }
3273 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003274 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3275 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003276 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003277 return Error(Loc, "unexpected token in argument list");
3278 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003279 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00003280 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00003281}
3282
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003283bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003284 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003285 SMLoc Loc = getLexer().getLoc();
3286 Parser.eatToEndOfStatement();
3287 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00003288}
3289
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003290bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003291 return Error(Loc, ErrorMsg);
3292}
3293
Jack Carter0b744b32012-10-04 02:29:46 +00003294bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003295 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003296 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00003297
3298 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00003299 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00003300
3301 Parser.Lex(); // Eat "noat".
3302
Jack Carterd0bd6422013-04-18 00:41:53 +00003303 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003304 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003305 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003306 return false;
3307 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003308
3309 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003310 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003311 return false;
3312}
Jack Carterd0bd6422013-04-18 00:41:53 +00003313
Jack Carter0b744b32012-10-04 02:29:46 +00003314bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00003315 // Line can be: ".set at", which sets $at to $1
3316 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00003317 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00003318 Parser.Lex(); // Eat "at".
3319
Jack Carter0b744b32012-10-04 02:29:46 +00003320 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003321 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00003322 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00003323
3324 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003325 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003326 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00003327 }
3328
3329 if (getLexer().isNot(AsmToken::Equal)) {
3330 reportParseError("unexpected token, expected equals sign");
3331 return false;
3332 }
3333 Parser.Lex(); // Eat "=".
3334
3335 if (getLexer().isNot(AsmToken::Dollar)) {
3336 if (getLexer().is(AsmToken::EndOfStatement)) {
3337 reportParseError("no register specified");
3338 return false;
3339 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00003340 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00003341 return false;
3342 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003343 }
3344 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00003345
Toma Tabacu16a74492015-02-13 10:30:57 +00003346 // Find out what "reg" is.
3347 unsigned AtRegNo;
3348 const AsmToken &Reg = Parser.getTok();
3349 if (Reg.is(AsmToken::Identifier)) {
3350 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
3351 } else if (Reg.is(AsmToken::Integer)) {
3352 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00003353 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00003354 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00003355 return false;
3356 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003357
3358 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00003359 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003360 reportParseError("invalid register");
3361 return false;
3362 }
3363 Parser.Lex(); // Eat "reg".
3364
3365 // If this is not the end of the statement, report an error.
3366 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3367 reportParseError("unexpected token, expected end of statement");
3368 return false;
3369 }
3370
3371 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
3372
3373 Parser.Lex(); // Consume the EndOfStatement.
3374 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003375}
3376
3377bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003378 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003379 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003380 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003381 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003382 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003383 return false;
3384 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003385 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00003386 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003387 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003388 return false;
3389}
3390
3391bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003392 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003393 Parser.Lex();
3394 // If this is not the end of the statement, report an error.
3395 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003396 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003397 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003398 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003399 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00003400 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003401 Parser.Lex(); // Consume the EndOfStatement.
3402 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003403}
3404
3405bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003406 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003407 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003408 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003409 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003410 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003411 return false;
3412 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003413 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003414 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003415 return false;
3416}
3417
3418bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003419 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003420 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003421 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003422 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003423 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003424 return false;
3425 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003426 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00003427 reportParseError("`noreorder' must be set before `nomacro'");
3428 return false;
3429 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003430 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003431 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003432 return false;
3433}
Jack Carterd76b2372013-03-21 21:44:16 +00003434
Daniel Sanders44934432014-08-07 12:03:36 +00003435bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003436 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003437 Parser.Lex();
3438
3439 // If this is not the end of the statement, report an error.
3440 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003441 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003442
3443 setFeatureBits(Mips::FeatureMSA, "msa");
3444 getTargetStreamer().emitDirectiveSetMsa();
3445 return false;
3446}
3447
3448bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003449 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003450 Parser.Lex();
3451
3452 // If this is not the end of the statement, report an error.
3453 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003454 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003455
3456 clearFeatureBits(Mips::FeatureMSA, "msa");
3457 getTargetStreamer().emitDirectiveSetNoMsa();
3458 return false;
3459}
3460
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003461bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003462 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003463 Parser.Lex(); // Eat "nodsp".
3464
3465 // If this is not the end of the statement, report an error.
3466 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3467 reportParseError("unexpected token, expected end of statement");
3468 return false;
3469 }
3470
3471 clearFeatureBits(Mips::FeatureDSP, "dsp");
3472 getTargetStreamer().emitDirectiveSetNoDsp();
3473 return false;
3474}
3475
Toma Tabacucc2502d2014-11-04 17:18:07 +00003476bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003477 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003478 Parser.Lex(); // Eat "mips16".
3479
Jack Carter39536722014-01-22 23:08:42 +00003480 // If this is not the end of the statement, report an error.
3481 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003482 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00003483 return false;
3484 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00003485
3486 setFeatureBits(Mips::FeatureMips16, "mips16");
3487 getTargetStreamer().emitDirectiveSetMips16();
3488 Parser.Lex(); // Consume the EndOfStatement.
3489 return false;
3490}
3491
3492bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003493 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003494 Parser.Lex(); // Eat "nomips16".
3495
3496 // If this is not the end of the statement, report an error.
3497 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3498 reportParseError("unexpected token, expected end of statement");
3499 return false;
3500 }
3501
3502 clearFeatureBits(Mips::FeatureMips16, "mips16");
3503 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00003504 Parser.Lex(); // Consume the EndOfStatement.
3505 return false;
3506}
3507
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003508bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003509 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003510 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003511 // Line can be: .set fp=32
3512 // .set fp=xx
3513 // .set fp=64
3514 Parser.Lex(); // Eat fp token
3515 AsmToken Tok = Parser.getTok();
3516 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003517 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003518 return false;
3519 }
3520 Parser.Lex(); // Eat '=' token.
3521 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003522
3523 if (!parseFpABIValue(FpAbiVal, ".set"))
3524 return false;
3525
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003526 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003527 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003528 return false;
3529 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003530 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003531 Parser.Lex(); // Consume the EndOfStatement.
3532 return false;
3533}
3534
Toma Tabacu9db22db2014-09-09 10:15:38 +00003535bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003536 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003537 SMLoc Loc = getLexer().getLoc();
3538
3539 Parser.Lex();
3540 if (getLexer().isNot(AsmToken::EndOfStatement))
3541 return reportParseError("unexpected token, expected end of statement");
3542
3543 // Always keep an element on the options "stack" to prevent the user
3544 // from changing the initial options. This is how we remember them.
3545 if (AssemblerOptions.size() == 2)
3546 return reportParseError(Loc, ".set pop with no .set push");
3547
3548 AssemblerOptions.pop_back();
3549 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
3550
3551 getTargetStreamer().emitDirectiveSetPop();
3552 return false;
3553}
3554
3555bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003556 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003557 Parser.Lex();
3558 if (getLexer().isNot(AsmToken::EndOfStatement))
3559 return reportParseError("unexpected token, expected end of statement");
3560
3561 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00003562 AssemblerOptions.push_back(
3563 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00003564
3565 getTargetStreamer().emitDirectiveSetPush();
3566 return false;
3567}
3568
Jack Carterd76b2372013-03-21 21:44:16 +00003569bool MipsAsmParser::parseSetAssignment() {
3570 StringRef Name;
3571 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00003572 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00003573
3574 if (Parser.parseIdentifier(Name))
3575 reportParseError("expected identifier after .set");
3576
3577 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003578 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00003579 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00003580
Jack Carter3b2c96e2014-01-22 23:31:38 +00003581 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00003582 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00003583
Toma Tabacuf25949b2015-04-07 13:59:39 +00003584 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00003585 Sym->setVariableValue(Value);
3586
3587 return false;
3588}
Jack Carterd0bd6422013-04-18 00:41:53 +00003589
Toma Tabacu26647792014-09-09 12:52:14 +00003590bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003591 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00003592 Parser.Lex();
3593 if (getLexer().isNot(AsmToken::EndOfStatement))
3594 return reportParseError("unexpected token, expected end of statement");
3595
3596 // Reset assembler options to their initial values.
3597 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
3598 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
3599
3600 getTargetStreamer().emitDirectiveSetMips0();
3601 return false;
3602}
3603
Toma Tabacu85618b32014-08-19 14:22:52 +00003604bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003605 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00003606 Parser.Lex();
3607 if (getLexer().isNot(AsmToken::Equal))
3608 return reportParseError("unexpected token, expected equals sign");
3609
3610 Parser.Lex();
3611 StringRef Arch;
3612 if (Parser.parseIdentifier(Arch))
3613 return reportParseError("expected arch identifier");
3614
3615 StringRef ArchFeatureName =
3616 StringSwitch<StringRef>(Arch)
3617 .Case("mips1", "mips1")
3618 .Case("mips2", "mips2")
3619 .Case("mips3", "mips3")
3620 .Case("mips4", "mips4")
3621 .Case("mips5", "mips5")
3622 .Case("mips32", "mips32")
3623 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003624 .Case("mips32r3", "mips32r3")
3625 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003626 .Case("mips32r6", "mips32r6")
3627 .Case("mips64", "mips64")
3628 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003629 .Case("mips64r3", "mips64r3")
3630 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003631 .Case("mips64r6", "mips64r6")
3632 .Case("cnmips", "cnmips")
3633 .Case("r4000", "mips3") // This is an implementation of Mips3.
3634 .Default("");
3635
3636 if (ArchFeatureName.empty())
3637 return reportParseError("unsupported architecture");
3638
3639 selectArch(ArchFeatureName);
3640 getTargetStreamer().emitDirectiveSetArch(Arch);
3641 return false;
3642}
3643
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003644bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003645 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003646 Parser.Lex();
3647 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003648 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003649
Matheus Almeida2852af82014-04-22 10:15:54 +00003650 switch (Feature) {
3651 default:
3652 llvm_unreachable("Unimplemented feature");
3653 case Mips::FeatureDSP:
3654 setFeatureBits(Mips::FeatureDSP, "dsp");
3655 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003656 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003657 case Mips::FeatureMicroMips:
3658 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003659 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003660 case Mips::FeatureMips1:
3661 selectArch("mips1");
3662 getTargetStreamer().emitDirectiveSetMips1();
3663 break;
3664 case Mips::FeatureMips2:
3665 selectArch("mips2");
3666 getTargetStreamer().emitDirectiveSetMips2();
3667 break;
3668 case Mips::FeatureMips3:
3669 selectArch("mips3");
3670 getTargetStreamer().emitDirectiveSetMips3();
3671 break;
3672 case Mips::FeatureMips4:
3673 selectArch("mips4");
3674 getTargetStreamer().emitDirectiveSetMips4();
3675 break;
3676 case Mips::FeatureMips5:
3677 selectArch("mips5");
3678 getTargetStreamer().emitDirectiveSetMips5();
3679 break;
3680 case Mips::FeatureMips32:
3681 selectArch("mips32");
3682 getTargetStreamer().emitDirectiveSetMips32();
3683 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003684 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003685 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003686 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003687 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003688 case Mips::FeatureMips32r3:
3689 selectArch("mips32r3");
3690 getTargetStreamer().emitDirectiveSetMips32R3();
3691 break;
3692 case Mips::FeatureMips32r5:
3693 selectArch("mips32r5");
3694 getTargetStreamer().emitDirectiveSetMips32R5();
3695 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003696 case Mips::FeatureMips32r6:
3697 selectArch("mips32r6");
3698 getTargetStreamer().emitDirectiveSetMips32R6();
3699 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003700 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003701 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00003702 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003703 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003704 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003705 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003706 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003707 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003708 case Mips::FeatureMips64r3:
3709 selectArch("mips64r3");
3710 getTargetStreamer().emitDirectiveSetMips64R3();
3711 break;
3712 case Mips::FeatureMips64r5:
3713 selectArch("mips64r5");
3714 getTargetStreamer().emitDirectiveSetMips64R5();
3715 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003716 case Mips::FeatureMips64r6:
3717 selectArch("mips64r6");
3718 getTargetStreamer().emitDirectiveSetMips64R6();
3719 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003720 }
3721 return false;
3722}
3723
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003724bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003725 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003726 if (getLexer().isNot(AsmToken::Comma)) {
3727 SMLoc Loc = getLexer().getLoc();
3728 Parser.eatToEndOfStatement();
3729 return Error(Loc, ErrorStr);
3730 }
3731
Matheus Almeida2852af82014-04-22 10:15:54 +00003732 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003733 return true;
3734}
3735
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003736bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003737 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00003738 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003739
Toma Tabacudde4c462014-11-06 10:02:45 +00003740 if (inMips16Mode()) {
3741 reportParseError(".cpload is not supported in Mips16 mode");
3742 return false;
3743 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003744
David Blaikie960ea3f2014-06-08 16:18:35 +00003745 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00003746 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003747 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3748 reportParseError("expected register containing function address");
3749 return false;
3750 }
3751
David Blaikie960ea3f2014-06-08 16:18:35 +00003752 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
3753 if (!RegOpnd.isGPRAsmReg()) {
3754 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003755 return false;
3756 }
3757
Toma Tabacudde4c462014-11-06 10:02:45 +00003758 // If this is not the end of the statement, report an error.
3759 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3760 reportParseError("unexpected token, expected end of statement");
3761 return false;
3762 }
3763
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003764 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003765 return false;
3766}
3767
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003768bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003769 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003770 unsigned FuncReg;
3771 unsigned Save;
3772 bool SaveIsReg = true;
3773
Matheus Almeida7e815762014-06-18 13:08:59 +00003774 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003775 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003776 if (ResTy == MatchOperand_NoMatch) {
3777 reportParseError("expected register containing function address");
3778 Parser.eatToEndOfStatement();
3779 return false;
3780 }
3781
3782 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3783 if (!FuncRegOpnd.isGPRAsmReg()) {
3784 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3785 Parser.eatToEndOfStatement();
3786 return false;
3787 }
3788
3789 FuncReg = FuncRegOpnd.getGPR32Reg();
3790 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003791
Toma Tabacu65f10572014-09-16 15:00:52 +00003792 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003793 return true;
3794
Toma Tabacu13964452014-09-04 13:23:44 +00003795 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003796 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003797 const AsmToken &Tok = Parser.getTok();
3798 if (Tok.is(AsmToken::Integer)) {
3799 Save = Tok.getIntVal();
3800 SaveIsReg = false;
3801 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003802 } else {
3803 reportParseError("expected save register or stack offset");
3804 Parser.eatToEndOfStatement();
3805 return false;
3806 }
3807 } else {
3808 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3809 if (!SaveOpnd.isGPRAsmReg()) {
3810 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3811 Parser.eatToEndOfStatement();
3812 return false;
3813 }
3814 Save = SaveOpnd.getGPR32Reg();
3815 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003816
Toma Tabacu65f10572014-09-16 15:00:52 +00003817 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003818 return true;
3819
Toma Tabacu8874eac2015-02-18 13:46:53 +00003820 const MCExpr *Expr;
3821 if (Parser.parseExpression(Expr)) {
3822 reportParseError("expected expression");
3823 return false;
3824 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003825
Toma Tabacu8874eac2015-02-18 13:46:53 +00003826 if (Expr->getKind() != MCExpr::SymbolRef) {
3827 reportParseError("expected symbol");
3828 return false;
3829 }
3830 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
3831
3832 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
3833 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003834 return false;
3835}
3836
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003837bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003838 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003839 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3840 const AsmToken &Tok = Parser.getTok();
3841
3842 if (Tok.getString() == "2008") {
3843 Parser.Lex();
3844 getTargetStreamer().emitDirectiveNaN2008();
3845 return false;
3846 } else if (Tok.getString() == "legacy") {
3847 Parser.Lex();
3848 getTargetStreamer().emitDirectiveNaNLegacy();
3849 return false;
3850 }
3851 }
3852 // If we don't recognize the option passed to the .nan
3853 // directive (e.g. no option or unknown option), emit an error.
3854 reportParseError("invalid option in .nan directive");
3855 return false;
3856}
3857
Jack Carter0b744b32012-10-04 02:29:46 +00003858bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003859 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003860 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003861 const AsmToken &Tok = Parser.getTok();
3862
3863 if (Tok.getString() == "noat") {
3864 return parseSetNoAtDirective();
3865 } else if (Tok.getString() == "at") {
3866 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003867 } else if (Tok.getString() == "arch") {
3868 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003869 } else if (Tok.getString() == "fp") {
3870 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003871 } else if (Tok.getString() == "pop") {
3872 return parseSetPopDirective();
3873 } else if (Tok.getString() == "push") {
3874 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003875 } else if (Tok.getString() == "reorder") {
3876 return parseSetReorderDirective();
3877 } else if (Tok.getString() == "noreorder") {
3878 return parseSetNoReorderDirective();
3879 } else if (Tok.getString() == "macro") {
3880 return parseSetMacroDirective();
3881 } else if (Tok.getString() == "nomacro") {
3882 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003883 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00003884 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003885 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003886 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003887 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003888 getTargetStreamer().emitDirectiveSetNoMicroMips();
3889 Parser.eatToEndOfStatement();
3890 return false;
3891 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003892 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003893 } else if (Tok.getString() == "mips0") {
3894 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003895 } else if (Tok.getString() == "mips1") {
3896 return parseSetFeature(Mips::FeatureMips1);
3897 } else if (Tok.getString() == "mips2") {
3898 return parseSetFeature(Mips::FeatureMips2);
3899 } else if (Tok.getString() == "mips3") {
3900 return parseSetFeature(Mips::FeatureMips3);
3901 } else if (Tok.getString() == "mips4") {
3902 return parseSetFeature(Mips::FeatureMips4);
3903 } else if (Tok.getString() == "mips5") {
3904 return parseSetFeature(Mips::FeatureMips5);
3905 } else if (Tok.getString() == "mips32") {
3906 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003907 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003908 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003909 } else if (Tok.getString() == "mips32r3") {
3910 return parseSetFeature(Mips::FeatureMips32r3);
3911 } else if (Tok.getString() == "mips32r5") {
3912 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003913 } else if (Tok.getString() == "mips32r6") {
3914 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003915 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003916 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003917 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003918 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003919 } else if (Tok.getString() == "mips64r3") {
3920 return parseSetFeature(Mips::FeatureMips64r3);
3921 } else if (Tok.getString() == "mips64r5") {
3922 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003923 } else if (Tok.getString() == "mips64r6") {
3924 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003925 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003926 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003927 } else if (Tok.getString() == "nodsp") {
3928 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003929 } else if (Tok.getString() == "msa") {
3930 return parseSetMsaDirective();
3931 } else if (Tok.getString() == "nomsa") {
3932 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003933 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003934 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003935 parseSetAssignment();
3936 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003937 }
Jack Carter07c818d2013-01-25 01:31:34 +00003938
Jack Carter0b744b32012-10-04 02:29:46 +00003939 return true;
3940}
3941
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003942/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003943/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003944bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003945 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003946 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3947 for (;;) {
3948 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003949 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003950 return true;
3951
3952 getParser().getStreamer().EmitValue(Value, Size);
3953
3954 if (getLexer().is(AsmToken::EndOfStatement))
3955 break;
3956
Jack Carter07c818d2013-01-25 01:31:34 +00003957 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003958 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00003959 Parser.Lex();
3960 }
3961 }
3962
3963 Parser.Lex();
3964 return false;
3965}
3966
Vladimir Medic4c299852013-11-06 11:27:05 +00003967/// parseDirectiveGpWord
3968/// ::= .gpword local_sym
3969bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003970 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003971 const MCExpr *Value;
3972 // EmitGPRel32Value requires an expression, so we are using base class
3973 // method to evaluate the expression.
3974 if (getParser().parseExpression(Value))
3975 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00003976 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00003977
Vladimir Medice10c1122013-11-13 13:18:04 +00003978 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003979 return Error(getLexer().getLoc(),
3980 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00003981 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00003982 return false;
3983}
3984
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003985/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00003986/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003987bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003988 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003989 const MCExpr *Value;
3990 // EmitGPRel64Value requires an expression, so we are using base class
3991 // method to evaluate the expression.
3992 if (getParser().parseExpression(Value))
3993 return true;
3994 getParser().getStreamer().EmitGPRel64Value(Value);
3995
3996 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003997 return Error(getLexer().getLoc(),
3998 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00003999 Parser.Lex(); // Eat EndOfStatement token.
4000 return false;
4001}
4002
Jack Carter0cd3c192014-01-06 23:27:31 +00004003bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004004 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00004005 // Get the option token.
4006 AsmToken Tok = Parser.getTok();
4007 // At the moment only identifiers are supported.
4008 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004009 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00004010 Parser.eatToEndOfStatement();
4011 return false;
4012 }
4013
4014 StringRef Option = Tok.getIdentifier();
4015
4016 if (Option == "pic0") {
4017 getTargetStreamer().emitDirectiveOptionPic0();
4018 Parser.Lex();
4019 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4020 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004021 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004022 Parser.eatToEndOfStatement();
4023 }
4024 return false;
4025 }
4026
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004027 if (Option == "pic2") {
4028 getTargetStreamer().emitDirectiveOptionPic2();
4029 Parser.Lex();
4030 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4031 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004032 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004033 Parser.eatToEndOfStatement();
4034 }
4035 return false;
4036 }
4037
Jack Carter0cd3c192014-01-06 23:27:31 +00004038 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00004039 Warning(Parser.getTok().getLoc(),
4040 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00004041 Parser.eatToEndOfStatement();
4042 return false;
4043}
4044
Toma Tabacu9ca50962015-04-16 09:53:47 +00004045/// parseInsnDirective
4046/// ::= .insn
4047bool MipsAsmParser::parseInsnDirective() {
4048 // If this is not the end of the statement, report an error.
4049 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4050 reportParseError("unexpected token, expected end of statement");
4051 return false;
4052 }
4053
4054 // The actual label marking happens in
4055 // MipsELFStreamer::createPendingLabelRelocs().
4056 getTargetStreamer().emitDirectiveInsn();
4057
4058 getParser().Lex(); // Eat EndOfStatement token.
4059 return false;
4060}
4061
Daniel Sanders7e527422014-07-10 13:38:23 +00004062/// parseDirectiveModule
4063/// ::= .module oddspreg
4064/// ::= .module nooddspreg
4065/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004066bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004067 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004068 MCAsmLexer &Lexer = getLexer();
4069 SMLoc L = Lexer.getLoc();
4070
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004071 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004072 // TODO : get a better message.
4073 reportParseError(".module directive must appear before any code");
4074 return false;
4075 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004076
Toma Tabacuc405c822015-01-23 10:40:19 +00004077 StringRef Option;
4078 if (Parser.parseIdentifier(Option)) {
4079 reportParseError("expected .module option identifier");
4080 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004081 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004082
Toma Tabacuc405c822015-01-23 10:40:19 +00004083 if (Option == "oddspreg") {
4084 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
4085 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4086
4087 // If this is not the end of the statement, report an error.
4088 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4089 reportParseError("unexpected token, expected end of statement");
4090 return false;
4091 }
4092
4093 return false; // parseDirectiveModule has finished successfully.
4094 } else if (Option == "nooddspreg") {
4095 if (!isABI_O32()) {
4096 Error(L, "'.module nooddspreg' requires the O32 ABI");
4097 return false;
4098 }
4099
4100 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
4101 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4102
4103 // If this is not the end of the statement, report an error.
4104 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4105 reportParseError("unexpected token, expected end of statement");
4106 return false;
4107 }
4108
4109 return false; // parseDirectiveModule has finished successfully.
4110 } else if (Option == "fp") {
4111 return parseDirectiveModuleFP();
4112 } else {
4113 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
4114 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004115}
4116
4117/// parseDirectiveModuleFP
4118/// ::= =32
4119/// ::= =xx
4120/// ::= =64
4121bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004122 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004123 MCAsmLexer &Lexer = getLexer();
4124
4125 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004126 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004127 return false;
4128 }
4129 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004130
Daniel Sanders7e527422014-07-10 13:38:23 +00004131 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004132 if (!parseFpABIValue(FpABI, ".module"))
4133 return false;
4134
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004135 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004136 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004137 return false;
4138 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004139
Daniel Sanders7201a3e2014-07-08 10:35:52 +00004140 // Emit appropriate flags.
4141 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00004142 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004143 return false;
4144}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004145
Daniel Sanders7e527422014-07-10 13:38:23 +00004146bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004147 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004148 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004149 MCAsmLexer &Lexer = getLexer();
4150
4151 if (Lexer.is(AsmToken::Identifier)) {
4152 StringRef Value = Parser.getTok().getString();
4153 Parser.Lex();
4154
4155 if (Value != "xx") {
4156 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4157 return false;
4158 }
4159
4160 if (!isABI_O32()) {
4161 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
4162 return false;
4163 }
4164
Daniel Sanders7e527422014-07-10 13:38:23 +00004165 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004166 return true;
4167 }
4168
4169 if (Lexer.is(AsmToken::Integer)) {
4170 unsigned Value = Parser.getTok().getIntVal();
4171 Parser.Lex();
4172
4173 if (Value != 32 && Value != 64) {
4174 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4175 return false;
4176 }
4177
4178 if (Value == 32) {
4179 if (!isABI_O32()) {
4180 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
4181 return false;
4182 }
4183
Daniel Sanders7e527422014-07-10 13:38:23 +00004184 FpABI = MipsABIFlagsSection::FpABIKind::S32;
4185 } else
4186 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004187
Daniel Sanders7e527422014-07-10 13:38:23 +00004188 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004189 }
4190
4191 return false;
4192}
4193
Jack Carter0b744b32012-10-04 02:29:46 +00004194bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004195 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004196 StringRef IDVal = DirectiveID.getString();
4197
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004198 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004199 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00004200 if (IDVal == ".dword") {
4201 parseDataDirective(8, DirectiveID.getLoc());
4202 return false;
4203 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004204 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004205 StringRef SymbolName;
4206
4207 if (Parser.parseIdentifier(SymbolName)) {
4208 reportParseError("expected identifier after .ent");
4209 return false;
4210 }
4211
4212 // There's an undocumented extension that allows an integer to
4213 // follow the name of the procedure which AFAICS is ignored by GAS.
4214 // Example: .ent foo,2
4215 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4216 if (getLexer().isNot(AsmToken::Comma)) {
4217 // Even though we accept this undocumented extension for compatibility
4218 // reasons, the additional integer argument does not actually change
4219 // the behaviour of the '.ent' directive, so we would like to discourage
4220 // its use. We do this by not referring to the extended version in
4221 // error messages which are not directly related to its use.
4222 reportParseError("unexpected token, expected end of statement");
4223 return false;
4224 }
4225 Parser.Lex(); // Eat the comma.
4226 const MCExpr *DummyNumber;
4227 int64_t DummyNumberVal;
4228 // If the user was explicitly trying to use the extended version,
4229 // we still give helpful extension-related error messages.
4230 if (Parser.parseExpression(DummyNumber)) {
4231 reportParseError("expected number after comma");
4232 return false;
4233 }
4234 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
4235 reportParseError("expected an absolute expression after comma");
4236 return false;
4237 }
4238 }
4239
4240 // If this is not the end of the statement, report an error.
4241 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4242 reportParseError("unexpected token, expected end of statement");
4243 return false;
4244 }
4245
4246 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
4247
4248 getTargetStreamer().emitDirectiveEnt(*Sym);
4249 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00004250 return false;
4251 }
4252
Jack Carter07c818d2013-01-25 01:31:34 +00004253 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004254 StringRef SymbolName;
4255
4256 if (Parser.parseIdentifier(SymbolName)) {
4257 reportParseError("expected identifier after .end");
4258 return false;
4259 }
4260
4261 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4262 reportParseError("unexpected token, expected end of statement");
4263 return false;
4264 }
4265
4266 if (CurrentFn == nullptr) {
4267 reportParseError(".end used without .ent");
4268 return false;
4269 }
4270
4271 if ((SymbolName != CurrentFn->getName())) {
4272 reportParseError(".end symbol does not match .ent symbol");
4273 return false;
4274 }
4275
4276 getTargetStreamer().emitDirectiveEnd(SymbolName);
4277 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00004278 return false;
4279 }
4280
Jack Carter07c818d2013-01-25 01:31:34 +00004281 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004282 // .frame $stack_reg, frame_size_in_bytes, $return_reg
4283 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004284 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004285 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4286 reportParseError("expected stack register");
4287 return false;
4288 }
4289
4290 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4291 if (!StackRegOpnd.isGPRAsmReg()) {
4292 reportParseError(StackRegOpnd.getStartLoc(),
4293 "expected general purpose register");
4294 return false;
4295 }
4296 unsigned StackReg = StackRegOpnd.getGPR32Reg();
4297
4298 if (Parser.getTok().is(AsmToken::Comma))
4299 Parser.Lex();
4300 else {
4301 reportParseError("unexpected token, expected comma");
4302 return false;
4303 }
4304
4305 // Parse the frame size.
4306 const MCExpr *FrameSize;
4307 int64_t FrameSizeVal;
4308
4309 if (Parser.parseExpression(FrameSize)) {
4310 reportParseError("expected frame size value");
4311 return false;
4312 }
4313
4314 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
4315 reportParseError("frame size not an absolute expression");
4316 return false;
4317 }
4318
4319 if (Parser.getTok().is(AsmToken::Comma))
4320 Parser.Lex();
4321 else {
4322 reportParseError("unexpected token, expected comma");
4323 return false;
4324 }
4325
4326 // Parse the return register.
4327 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00004328 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004329 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4330 reportParseError("expected return register");
4331 return false;
4332 }
4333
4334 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4335 if (!ReturnRegOpnd.isGPRAsmReg()) {
4336 reportParseError(ReturnRegOpnd.getStartLoc(),
4337 "expected general purpose register");
4338 return false;
4339 }
4340
4341 // If this is not the end of the statement, report an error.
4342 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4343 reportParseError("unexpected token, expected end of statement");
4344 return false;
4345 }
4346
4347 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
4348 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00004349 return false;
4350 }
4351
Jack Carter07c818d2013-01-25 01:31:34 +00004352 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00004353 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00004354 }
4355
Daniel Sandersd97a6342014-08-13 10:07:34 +00004356 if (IDVal == ".mask" || IDVal == ".fmask") {
4357 // .mask bitmask, frame_offset
4358 // bitmask: One bit for each register used.
4359 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
4360 // first register is expected to be saved.
4361 // Examples:
4362 // .mask 0x80000000, -4
4363 // .fmask 0x80000000, -4
4364 //
Jack Carterbe332172012-09-07 00:48:02 +00004365
Daniel Sandersd97a6342014-08-13 10:07:34 +00004366 // Parse the bitmask
4367 const MCExpr *BitMask;
4368 int64_t BitMaskVal;
4369
4370 if (Parser.parseExpression(BitMask)) {
4371 reportParseError("expected bitmask value");
4372 return false;
4373 }
4374
4375 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
4376 reportParseError("bitmask not an absolute expression");
4377 return false;
4378 }
4379
4380 if (Parser.getTok().is(AsmToken::Comma))
4381 Parser.Lex();
4382 else {
4383 reportParseError("unexpected token, expected comma");
4384 return false;
4385 }
4386
4387 // Parse the frame_offset
4388 const MCExpr *FrameOffset;
4389 int64_t FrameOffsetVal;
4390
4391 if (Parser.parseExpression(FrameOffset)) {
4392 reportParseError("expected frame offset value");
4393 return false;
4394 }
4395
4396 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
4397 reportParseError("frame offset not an absolute expression");
4398 return false;
4399 }
4400
4401 // If this is not the end of the statement, report an error.
4402 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4403 reportParseError("unexpected token, expected end of statement");
4404 return false;
4405 }
4406
4407 if (IDVal == ".mask")
4408 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
4409 else
4410 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00004411 return false;
4412 }
4413
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004414 if (IDVal == ".nan")
4415 return parseDirectiveNaN();
4416
Jack Carter07c818d2013-01-25 01:31:34 +00004417 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004418 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00004419 return false;
4420 }
4421
Rafael Espindolab59fb732014-03-28 18:50:26 +00004422 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004423 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004424 return false;
4425 }
4426
Jack Carter07c818d2013-01-25 01:31:34 +00004427 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004428 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00004429 return false;
4430 }
4431
Jack Carter0cd3c192014-01-06 23:27:31 +00004432 if (IDVal == ".option")
4433 return parseDirectiveOption();
4434
4435 if (IDVal == ".abicalls") {
4436 getTargetStreamer().emitDirectiveAbiCalls();
4437 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004438 Error(Parser.getTok().getLoc(),
4439 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004440 // Clear line
4441 Parser.eatToEndOfStatement();
4442 }
4443 return false;
4444 }
4445
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004446 if (IDVal == ".cpsetup")
4447 return parseDirectiveCPSetup();
4448
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004449 if (IDVal == ".module")
4450 return parseDirectiveModule();
4451
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004452 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
4453 return parseInternalDirectiveReallowModule();
4454
Toma Tabacu9ca50962015-04-16 09:53:47 +00004455 if (IDVal == ".insn")
4456 return parseInsnDirective();
4457
Rafael Espindola870c4e92012-01-11 03:56:41 +00004458 return true;
4459}
4460
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004461bool MipsAsmParser::parseInternalDirectiveReallowModule() {
4462 // If this is not the end of the statement, report an error.
4463 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4464 reportParseError("unexpected token, expected end of statement");
4465 return false;
4466 }
4467
4468 getTargetStreamer().reallowModuleDirective();
4469
4470 getParser().Lex(); // Eat EndOfStatement token.
4471 return false;
4472}
4473
Rafael Espindola870c4e92012-01-11 03:56:41 +00004474extern "C" void LLVMInitializeMipsAsmParser() {
4475 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
4476 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
4477 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
4478 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
4479}
Jack Carterb4dbc172012-09-05 23:34:03 +00004480
4481#define GET_REGISTER_MATCHER
4482#define GET_MATCHER_IMPLEMENTATION
4483#include "MipsGenAsmMatcher.inc"