blob: 4779c227465ea3b5fa2393b17bc0133c56b70fac [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>
Toma Tabacu61145652015-04-28 13:16:06 +00001636void createLShiftOri(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 }
Toma Tabacu7dea2e32015-04-28 14:06:35 +00001648 // There's no need for an ORi if the immediate is 0.
1649 if (Operand.isImm() && Operand.getImm() == 0)
1650 return;
1651
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001652 tmpInst.setOpcode(Mips::ORi);
1653 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1654 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001655 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001656 tmpInst.setLoc(IDLoc);
1657 Instructions.push_back(tmpInst);
1658}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001659
1660template <int Shift, bool PerformShift>
Toma Tabacu61145652015-04-28 13:16:06 +00001661void createLShiftOri(int64_t Value, unsigned RegNo, SMLoc IDLoc,
Toma Tabacu0d64b202014-08-14 10:29:17 +00001662 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu61145652015-04-28 13:16:06 +00001663 createLShiftOri<PerformShift>(
Toma Tabacu0d64b202014-08-14 10:29:17 +00001664 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)), RegNo,
1665 IDLoc, Instructions);
1666}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001667}
1668
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001669bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
1670 SmallVectorImpl<MCInst> &Instructions) {
1671 // Create a JALR instruction which is going to replace the pseudo-JAL.
1672 MCInst JalrInst;
1673 JalrInst.setLoc(IDLoc);
1674 const MCOperand FirstRegOp = Inst.getOperand(0);
1675 const unsigned Opcode = Inst.getOpcode();
1676
1677 if (Opcode == Mips::JalOneReg) {
1678 // jal $rs => jalr $rs
1679 if (inMicroMipsMode()) {
1680 JalrInst.setOpcode(Mips::JALR16_MM);
1681 JalrInst.addOperand(FirstRegOp);
1682 } else {
1683 JalrInst.setOpcode(Mips::JALR);
1684 JalrInst.addOperand(MCOperand::CreateReg(Mips::RA));
1685 JalrInst.addOperand(FirstRegOp);
1686 }
1687 } else if (Opcode == Mips::JalTwoReg) {
1688 // jal $rd, $rs => jalr $rd, $rs
1689 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
1690 JalrInst.addOperand(FirstRegOp);
1691 const MCOperand SecondRegOp = Inst.getOperand(1);
1692 JalrInst.addOperand(SecondRegOp);
1693 }
1694 Instructions.push_back(JalrInst);
1695
1696 // If .set reorder is active, emit a NOP after it.
1697 if (AssemblerOptions.back()->isReorder()) {
1698 // This is a 32-bit NOP because these 2 pseudo-instructions
1699 // do not have a short delay slot.
1700 MCInst NopInst;
1701 NopInst.setOpcode(Mips::SLL);
1702 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1703 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1704 NopInst.addOperand(MCOperand::CreateImm(0));
1705 Instructions.push_back(NopInst);
1706 }
1707
1708 return false;
1709}
1710
Matheus Almeida3813d572014-06-19 14:39:14 +00001711bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001712 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001713 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001714 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001715 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001716 const MCOperand &RegOp = Inst.getOperand(0);
1717 assert(RegOp.isReg() && "expected register operand kind");
1718
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001719 int64_t ImmValue = ImmOp.getImm();
Toma Tabacu137d90a2015-04-28 12:04:53 +00001720 unsigned Reg = RegOp.getReg();
Jack Carter92995f12012-10-06 00:53:28 +00001721 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001722 // FIXME: gas has a special case for values that are 000...1111, which
1723 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001724 if (0 <= ImmValue && ImmValue <= 65535) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001725 // For unsigned and positive signed 16-bit values (0 <= j <= 65535):
Jack Carter30a59822012-10-04 04:03:53 +00001726 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001727 tmpInst.setOpcode(Mips::ORi);
Toma Tabacu137d90a2015-04-28 12:04:53 +00001728 tmpInst.addOperand(MCOperand::CreateReg(Reg));
Jack Carterd0bd6422013-04-18 00:41:53 +00001729 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001730 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001731 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001732 } else if (ImmValue < 0 && ImmValue >= -32768) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001733 // For negative signed 16-bit values (-32768 <= j < 0):
Jack Carter30a59822012-10-04 04:03:53 +00001734 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001735 tmpInst.setOpcode(Mips::ADDiu);
Toma Tabacu137d90a2015-04-28 12:04:53 +00001736 tmpInst.addOperand(MCOperand::CreateReg(Reg));
Jack Carterd0bd6422013-04-18 00:41:53 +00001737 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001738 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001739 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001740 } else if ((ImmValue & 0xffffffff) == ImmValue) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001741 // For all other values which are representable as a 32-bit integer:
Jack Carter30a59822012-10-04 04:03:53 +00001742 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001743 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001744 tmpInst.setOpcode(Mips::LUi);
Toma Tabacu137d90a2015-04-28 12:04:53 +00001745 tmpInst.addOperand(MCOperand::CreateReg(Reg));
Jack Carter92995f12012-10-06 00:53:28 +00001746 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001747 Instructions.push_back(tmpInst);
Toma Tabacu61145652015-04-28 13:16:06 +00001748 createLShiftOri<0, false>(ImmValue, Reg, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001749 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001750 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001751 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001752 return true;
1753 }
1754
1755 // <------- lo32 ------>
1756 // <------- hi32 ------>
1757 // <- hi16 -> <- lo16 ->
1758 // _________________________________
1759 // | | | |
Toma Tabacubda745f2015-04-27 15:21:38 +00001760 // | 16-bits | 16-bits | 16-bits |
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001761 // |__________|__________|__________|
1762 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001763 // For any 64-bit value that is representable as a 48-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001764 // li d,j => lui d,hi16(j)
1765 // ori d,d,hi16(lo32(j))
1766 // dsll d,d,16
1767 // ori d,d,lo16(lo32(j))
1768 tmpInst.setOpcode(Mips::LUi);
Toma Tabacu137d90a2015-04-28 12:04:53 +00001769 tmpInst.addOperand(MCOperand::CreateReg(Reg));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001770 tmpInst.addOperand(
1771 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001772 Instructions.push_back(tmpInst);
Toma Tabacu61145652015-04-28 13:16:06 +00001773 createLShiftOri<16, false>(ImmValue, Reg, IDLoc, Instructions);
1774 createLShiftOri<0, true>(ImmValue, Reg, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001775 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001776 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001777 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001778 return true;
1779 }
1780
1781 // <------- hi32 ------> <------- lo32 ------>
1782 // <- hi16 -> <- lo16 ->
1783 // ___________________________________________
1784 // | | | | |
Toma Tabacubda745f2015-04-27 15:21:38 +00001785 // | 16-bits | 16-bits | 16-bits | 16-bits |
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001786 // |__________|__________|__________|__________|
1787 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001788 // For all other values which are representable as a 64-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001789 // li d,j => lui d,hi16(j)
1790 // ori d,d,lo16(hi32(j))
1791 // dsll d,d,16
1792 // ori d,d,hi16(lo32(j))
1793 // dsll d,d,16
1794 // ori d,d,lo16(lo32(j))
1795 tmpInst.setOpcode(Mips::LUi);
Toma Tabacu137d90a2015-04-28 12:04:53 +00001796 tmpInst.addOperand(MCOperand::CreateReg(Reg));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001797 tmpInst.addOperand(
1798 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1799 Instructions.push_back(tmpInst);
Toma Tabacu61145652015-04-28 13:16:06 +00001800 createLShiftOri<32, false>(ImmValue, Reg, IDLoc, Instructions);
1801 createLShiftOri<16, true>(ImmValue, Reg, IDLoc, Instructions);
1802 createLShiftOri<0, true>(ImmValue, Reg, IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001803 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001804 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001805}
Jack Carter92995f12012-10-06 00:53:28 +00001806
Matheus Almeida3813d572014-06-19 14:39:14 +00001807bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001808MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1809 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001810 MCInst tmpInst;
1811 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001812 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1813 "expected immediate operand kind");
1814 if (!ImmOp.isImm()) {
1815 expandLoadAddressSym(Inst, IDLoc, Instructions);
1816 return false;
1817 }
Jack Carter543fdf82012-10-09 23:29:45 +00001818 const MCOperand &SrcRegOp = Inst.getOperand(1);
1819 assert(SrcRegOp.isReg() && "expected register operand kind");
1820 const MCOperand &DstRegOp = Inst.getOperand(0);
1821 assert(DstRegOp.isReg() && "expected register operand kind");
1822 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001823 if (-32768 <= ImmValue && ImmValue <= 65535) {
1824 // For -32768 <= j <= 65535.
1825 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001826 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001827 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1828 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1829 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1830 Instructions.push_back(tmpInst);
1831 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001832 // For any other value of j that is representable as a 32-bit integer.
1833 // la d,j(s) => lui d,hi16(j)
1834 // ori d,d,lo16(j)
1835 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001836 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001837 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1838 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1839 Instructions.push_back(tmpInst);
1840 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001841 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001842 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1843 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1844 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1845 Instructions.push_back(tmpInst);
1846 tmpInst.clear();
1847 tmpInst.setOpcode(Mips::ADDu);
1848 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1849 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1850 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1851 Instructions.push_back(tmpInst);
1852 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001853 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001854}
1855
Matheus Almeida3813d572014-06-19 14:39:14 +00001856bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001857MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1858 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001859 MCInst tmpInst;
1860 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001861 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1862 "expected immediate operand kind");
1863 if (!ImmOp.isImm()) {
1864 expandLoadAddressSym(Inst, IDLoc, Instructions);
1865 return false;
1866 }
Jack Carter543fdf82012-10-09 23:29:45 +00001867 const MCOperand &RegOp = Inst.getOperand(0);
1868 assert(RegOp.isReg() && "expected register operand kind");
1869 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001870 if (-32768 <= ImmValue && ImmValue <= 65535) {
1871 // For -32768 <= j <= 65535.
1872 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001873 tmpInst.setOpcode(Mips::ADDiu);
1874 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001875 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001876 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1877 Instructions.push_back(tmpInst);
1878 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001879 // For any other value of j that is representable as a 32-bit integer.
1880 // la d,j => lui d,hi16(j)
1881 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001882 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001883 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1884 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1885 Instructions.push_back(tmpInst);
1886 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001887 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001888 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1889 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1890 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1891 Instructions.push_back(tmpInst);
1892 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001893 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001894}
1895
Toma Tabacu0d64b202014-08-14 10:29:17 +00001896void
1897MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1898 SmallVectorImpl<MCInst> &Instructions) {
1899 // FIXME: If we do have a valid at register to use, we should generate a
1900 // slightly shorter sequence here.
1901 MCInst tmpInst;
1902 int ExprOperandNo = 1;
1903 // Sometimes the assembly parser will get the immediate expression as
1904 // a $zero + an immediate.
1905 if (Inst.getNumOperands() == 3) {
1906 assert(Inst.getOperand(1).getReg() ==
1907 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1908 ExprOperandNo = 2;
1909 }
1910 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1911 assert(SymOp.isExpr() && "expected symbol operand kind");
1912 const MCOperand &RegOp = Inst.getOperand(0);
1913 unsigned RegNo = RegOp.getReg();
1914 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1915 const MCSymbolRefExpr *HiExpr =
1916 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1917 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1918 const MCSymbolRefExpr *LoExpr =
1919 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1920 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1921 if (isGP64bit()) {
1922 // If it's a 64-bit architecture, expand to:
1923 // la d,sym => lui d,highest(sym)
1924 // ori d,d,higher(sym)
1925 // dsll d,d,16
1926 // ori d,d,hi16(sym)
1927 // dsll d,d,16
1928 // ori d,d,lo16(sym)
1929 const MCSymbolRefExpr *HighestExpr =
1930 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1931 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1932 const MCSymbolRefExpr *HigherExpr =
1933 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1934 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1935
1936 tmpInst.setOpcode(Mips::LUi);
1937 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1938 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1939 Instructions.push_back(tmpInst);
1940
Toma Tabacu61145652015-04-28 13:16:06 +00001941 createLShiftOri<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00001942 Instructions);
Toma Tabacu61145652015-04-28 13:16:06 +00001943 createLShiftOri<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00001944 Instructions);
Toma Tabacu61145652015-04-28 13:16:06 +00001945 createLShiftOri<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00001946 Instructions);
1947 } else {
1948 // Otherwise, expand to:
1949 // la d,sym => lui d,hi16(sym)
1950 // ori d,d,lo16(sym)
1951 tmpInst.setOpcode(Mips::LUi);
1952 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1953 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1954 Instructions.push_back(tmpInst);
1955
Toma Tabacu61145652015-04-28 13:16:06 +00001956 createLShiftOri<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00001957 Instructions);
1958 }
1959}
1960
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00001961bool MipsAsmParser::expandUncondBranchMMPseudo(
1962 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00001963 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
1964 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001965
1966 MCOperand Offset = Inst.getOperand(0);
1967 if (Offset.isExpr()) {
1968 Inst.clear();
1969 Inst.setOpcode(Mips::BEQ_MM);
1970 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1971 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1972 Inst.addOperand(MCOperand::CreateExpr(Offset.getExpr()));
1973 } else {
1974 assert(Offset.isImm() && "expected immediate operand kind");
1975 if (isIntN(11, Offset.getImm())) {
1976 // If offset fits into 11 bits then this instruction becomes microMIPS
1977 // 16-bit unconditional branch instruction.
1978 Inst.setOpcode(Mips::B16_MM);
1979 } else {
1980 if (!isIntN(17, Offset.getImm()))
1981 Error(IDLoc, "branch target out of range");
1982 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
1983 Error(IDLoc, "branch to misaligned address");
1984 Inst.clear();
1985 Inst.setOpcode(Mips::BEQ_MM);
1986 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1987 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1988 Inst.addOperand(MCOperand::CreateImm(Offset.getImm()));
1989 }
1990 }
1991 Instructions.push_back(Inst);
1992
Toma Tabacu234482a2015-03-16 12:03:39 +00001993 // If .set reorder is active, emit a NOP after the branch instruction.
1994 if (AssemblerOptions.back()->isReorder())
1995 createNop(true, IDLoc, Instructions);
1996
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001997 return false;
1998}
1999
Jack Carter9e65aa32013-03-22 00:05:30 +00002000void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002001 SmallVectorImpl<MCInst> &Instructions,
2002 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002003 const MCSymbolRefExpr *SR;
2004 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00002005 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002006 const MCExpr *ExprOffset;
2007 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002008 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002009 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2010 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002011 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002012 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2013 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002014 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002015 if (isImmOpnd) {
2016 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2017 ImmOffset = Inst.getOperand(2).getImm();
2018 LoOffset = ImmOffset & 0x0000ffff;
2019 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002020 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002021 if (LoOffset & 0x8000)
2022 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002023 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002024 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002025 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002026 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002027 // These are some of the types of expansions we perform here:
2028 // 1) lw $8, sym => lui $8, %hi(sym)
2029 // lw $8, %lo(sym)($8)
2030 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2031 // add $8, $8, $9
2032 // lw $8, %lo(offset)($9)
2033 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2034 // add $at, $at, $8
2035 // lw $8, %lo(offset)($at)
2036 // 4) sw $8, sym => lui $at, %hi(sym)
2037 // sw $8, %lo(sym)($at)
2038 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2039 // add $at, $at, $8
2040 // sw $8, %lo(offset)($at)
2041 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2042 // ldc1 $f0, %lo(sym)($at)
2043 //
2044 // For load instructions we can use the destination register as a temporary
2045 // if base and dst are different (examples 1 and 2) and if the base register
2046 // is general purpose otherwise we must use $at (example 6) and error if it's
2047 // not available. For stores we must use $at (examples 4 and 5) because we
2048 // must not clobber the source register setting up the offset.
2049 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2050 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2051 unsigned RegClassIDOp0 =
2052 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2053 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2054 (RegClassIDOp0 == Mips::GPR64RegClassID);
2055 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002056 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002057 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002058 // At this point we need AT to perform the expansions and we exit if it is
2059 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002060 TmpRegNum = getATReg(IDLoc);
2061 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002062 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002063 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002064
Jack Carter9e65aa32013-03-22 00:05:30 +00002065 TempInst.setOpcode(Mips::LUi);
2066 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2067 if (isImmOpnd)
2068 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
2069 else {
2070 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002071 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00002072 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
2073 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
2074 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00002075 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002076 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002077 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00002078 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002079 }
2080 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002081 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002082 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002083 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002084 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002085 // Add temp register to base.
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002086 if (BaseRegNum != Mips::ZERO) {
2087 TempInst.setOpcode(Mips::ADDu);
2088 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2089 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2090 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
2091 Instructions.push_back(TempInst);
2092 TempInst.clear();
2093 }
Alp Tokercb402912014-01-24 17:20:08 +00002094 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002095 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002096 TempInst.setOpcode(Inst.getOpcode());
2097 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
2098 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2099 if (isImmOpnd)
2100 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
2101 else {
2102 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002103 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
2104 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
2105 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00002106 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002107 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002108 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00002109 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002110 }
2111 }
2112 Instructions.push_back(TempInst);
2113 TempInst.clear();
2114}
2115
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002116bool
2117MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2118 SmallVectorImpl<MCInst> &Instructions) {
2119 unsigned OpNum = Inst.getNumOperands();
2120 unsigned Opcode = Inst.getOpcode();
2121 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2122
2123 assert (Inst.getOperand(OpNum - 1).isImm() &&
2124 Inst.getOperand(OpNum - 2).isReg() &&
2125 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2126
2127 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2128 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2129 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2130 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2131 // It can be implemented as SWM16 or LWM16 instruction.
2132 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2133
2134 Inst.setOpcode(NewOpcode);
2135 Instructions.push_back(Inst);
2136 return false;
2137}
2138
Toma Tabacu234482a2015-03-16 12:03:39 +00002139void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
2140 SmallVectorImpl<MCInst> &Instructions) {
2141 MCInst NopInst;
2142 if (hasShortDelaySlot) {
2143 NopInst.setOpcode(Mips::MOVE16_MM);
2144 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2145 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2146 } else {
2147 NopInst.setOpcode(Mips::SLL);
2148 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2149 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2150 NopInst.addOperand(MCOperand::CreateImm(0));
2151 }
2152 Instructions.push_back(NopInst);
2153}
2154
Matheus Almeida595fcab2014-06-11 15:05:56 +00002155unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
2156 // As described by the Mips32r2 spec, the registers Rd and Rs for
2157 // jalr.hb must be different.
2158 unsigned Opcode = Inst.getOpcode();
2159
2160 if (Opcode == Mips::JALR_HB &&
2161 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
2162 return Match_RequiresDifferentSrcAndDst;
2163
2164 return Match_Success;
2165}
2166
David Blaikie960ea3f2014-06-08 16:18:35 +00002167bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
2168 OperandVector &Operands,
2169 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00002170 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00002171 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00002172
Jack Carterb4dbc172012-09-05 23:34:03 +00002173 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00002174 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00002175 unsigned MatchResult =
2176 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00002177
2178 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002179 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002180 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00002181 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00002182 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00002183 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00002184 return false;
2185 }
2186 case Match_MissingFeature:
2187 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
2188 return true;
2189 case Match_InvalidOperand: {
2190 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00002191 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002192 if (ErrorInfo >= Operands.size())
2193 return Error(IDLoc, "too few operands for instruction");
2194
David Blaikie960ea3f2014-06-08 16:18:35 +00002195 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00002196 if (ErrorLoc == SMLoc())
2197 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00002198 }
2199
2200 return Error(ErrorLoc, "invalid operand for instruction");
2201 }
2202 case Match_MnemonicFail:
2203 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00002204 case Match_RequiresDifferentSrcAndDst:
2205 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00002206 }
Craig Topper589ceee2015-01-03 08:16:34 +00002207
2208 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00002209}
2210
Toma Tabacud9d344b2015-04-27 14:05:04 +00002211void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
2212 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
2213 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
2214 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002215}
2216
Daniel Sandersef638fe2014-10-03 15:37:37 +00002217void
2218MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
2219 SMRange Range, bool ShowColors) {
2220 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00002221 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00002222 ShowColors);
2223}
2224
Jack Carter1ac53222013-02-20 23:11:17 +00002225int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002226 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002227
Vladimir Medic4c299852013-11-06 11:27:05 +00002228 CC = StringSwitch<unsigned>(Name)
2229 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002230 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00002231 .Case("a0", 4)
2232 .Case("a1", 5)
2233 .Case("a2", 6)
2234 .Case("a3", 7)
2235 .Case("v0", 2)
2236 .Case("v1", 3)
2237 .Case("s0", 16)
2238 .Case("s1", 17)
2239 .Case("s2", 18)
2240 .Case("s3", 19)
2241 .Case("s4", 20)
2242 .Case("s5", 21)
2243 .Case("s6", 22)
2244 .Case("s7", 23)
2245 .Case("k0", 26)
2246 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002247 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00002248 .Case("sp", 29)
2249 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002250 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00002251 .Case("ra", 31)
2252 .Case("t0", 8)
2253 .Case("t1", 9)
2254 .Case("t2", 10)
2255 .Case("t3", 11)
2256 .Case("t4", 12)
2257 .Case("t5", 13)
2258 .Case("t6", 14)
2259 .Case("t7", 15)
2260 .Case("t8", 24)
2261 .Case("t9", 25)
2262 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002263
Toma Tabacufda445c2014-09-15 15:33:01 +00002264 if (!(isABI_N32() || isABI_N64()))
2265 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002266
Daniel Sandersef638fe2014-10-03 15:37:37 +00002267 if (12 <= CC && CC <= 15) {
2268 // Name is one of t4-t7
2269 AsmToken RegTok = getLexer().peekTok();
2270 SMRange RegRange = RegTok.getLocRange();
2271
2272 StringRef FixedName = StringSwitch<StringRef>(Name)
2273 .Case("t4", "t0")
2274 .Case("t5", "t1")
2275 .Case("t6", "t2")
2276 .Case("t7", "t3")
2277 .Default("");
2278 assert(FixedName != "" && "Register name is not one of t4-t7.");
2279
2280 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
2281 "Did you mean $" + FixedName + "?", RegRange);
2282 }
2283
Toma Tabacufda445c2014-09-15 15:33:01 +00002284 // Although SGI documentation just cuts out t0-t3 for n32/n64,
2285 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
2286 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
2287 if (8 <= CC && CC <= 11)
2288 CC += 4;
2289
2290 if (CC == -1)
2291 CC = StringSwitch<unsigned>(Name)
2292 .Case("a4", 8)
2293 .Case("a5", 9)
2294 .Case("a6", 10)
2295 .Case("a7", 11)
2296 .Case("kt0", 26)
2297 .Case("kt1", 27)
2298 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002299
2300 return CC;
2301}
Jack Carterd0bd6422013-04-18 00:41:53 +00002302
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002303int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
2304 int CC;
2305
2306 CC = StringSwitch<unsigned>(Name)
2307 .Case("hwr_cpunum", 0)
2308 .Case("hwr_synci_step", 1)
2309 .Case("hwr_cc", 2)
2310 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00002311 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002312 .Default(-1);
2313
2314 return CC;
2315}
2316
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002317int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002318
Jack Cartera63b16a2012-09-07 00:23:42 +00002319 if (Name[0] == 'f') {
2320 StringRef NumString = Name.substr(1);
2321 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002322 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002323 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002324 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00002325 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002326 return IntVal;
2327 }
2328 return -1;
2329}
Jack Cartera63b16a2012-09-07 00:23:42 +00002330
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002331int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
2332
2333 if (Name.startswith("fcc")) {
2334 StringRef NumString = Name.substr(3);
2335 unsigned IntVal;
2336 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002337 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002338 if (IntVal > 7) // There are only 8 fcc registers.
2339 return -1;
2340 return IntVal;
2341 }
2342 return -1;
2343}
2344
2345int MipsAsmParser::matchACRegisterName(StringRef Name) {
2346
Akira Hatanaka274d24c2013-08-14 01:15:52 +00002347 if (Name.startswith("ac")) {
2348 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002349 unsigned IntVal;
2350 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002351 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002352 if (IntVal > 3) // There are only 3 acc registers.
2353 return -1;
2354 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00002355 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002356 return -1;
2357}
Jack Carterd0bd6422013-04-18 00:41:53 +00002358
Jack Carter5dc8ac92013-09-25 23:50:44 +00002359int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
2360 unsigned IntVal;
2361
2362 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2363 return -1;
2364
2365 if (IntVal > 31)
2366 return -1;
2367
2368 return IntVal;
2369}
2370
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002371int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
2372 int CC;
2373
2374 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00002375 .Case("msair", 0)
2376 .Case("msacsr", 1)
2377 .Case("msaaccess", 2)
2378 .Case("msasave", 3)
2379 .Case("msamodify", 4)
2380 .Case("msarequest", 5)
2381 .Case("msamap", 6)
2382 .Case("msaunmap", 7)
2383 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002384
2385 return CC;
2386}
2387
Toma Tabacu89a712b2015-04-15 10:48:56 +00002388unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00002389 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00002390 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002391 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00002392 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00002393 return 0;
2394 }
2395 unsigned AT = getReg(
2396 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00002397 return AT;
2398}
Jack Carter0b744b32012-10-04 02:29:46 +00002399
Jack Carterd0bd6422013-04-18 00:41:53 +00002400unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00002401 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00002402}
2403
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002404unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002405 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00002406 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002407}
2408
Jack Carter873c7242013-01-12 01:03:14 +00002409int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002410 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00002411 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00002412 return -1;
2413
Jack Carter873c7242013-01-12 01:03:14 +00002414 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00002415}
2416
Toma Tabacu13964452014-09-04 13:23:44 +00002417bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002418 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002419 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002420
Jack Carter30a59822012-10-04 04:03:53 +00002421 // Check if the current operand has a custom associated parser, if so, try to
2422 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00002423 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2424 if (ResTy == MatchOperand_Success)
2425 return false;
2426 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2427 // there was a match, but an error occurred, in which case, just return that
2428 // the operand parsing failed.
2429 if (ResTy == MatchOperand_ParseFail)
2430 return true;
2431
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002432 DEBUG(dbgs() << ".. Generic Parser\n");
2433
Jack Carterb4dbc172012-09-05 23:34:03 +00002434 switch (getLexer().getKind()) {
2435 default:
2436 Error(Parser.getTok().getLoc(), "unexpected token in operand");
2437 return true;
2438 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002439 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00002440 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00002441
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002442 // Almost all registers have been parsed by custom parsers. There is only
2443 // one exception to this. $zero (and it's alias $0) will reach this point
2444 // for div, divu, and similar instructions because it is not an operand
2445 // to the instruction definition but an explicit register. Special case
2446 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00002447 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00002448 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002449
Jack Carterd0bd6422013-04-18 00:41:53 +00002450 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00002451 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002452 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00002453 return true;
2454
Jack Carter873c7242013-01-12 01:03:14 +00002455 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00002456 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00002457 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00002458 const MCExpr *Res =
2459 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00002460
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002461 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002462 return false;
2463 }
Vladimir Medic4c299852013-11-06 11:27:05 +00002464 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00002465 case AsmToken::LParen:
2466 case AsmToken::Minus:
2467 case AsmToken::Plus:
2468 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002469 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00002470 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002471 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002472 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002473 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00002474 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00002475 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002476 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002477 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002478 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00002479 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00002480 return true;
2481
Jack Carter873c7242013-01-12 01:03:14 +00002482 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2483
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002484 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00002485 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002486 } // case AsmToken::Percent
2487 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00002488 return true;
2489}
2490
Vladimir Medic4c299852013-11-06 11:27:05 +00002491const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00002492 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00002493 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00002494 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002495 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00002496 // It's a constant, evaluate reloc value.
2497 int16_t Val;
2498 switch (getVariantKind(RelocStr)) {
2499 case MCSymbolRefExpr::VK_Mips_ABS_LO:
2500 // Get the 1st 16-bits.
2501 Val = MCE->getValue() & 0xffff;
2502 break;
2503 case MCSymbolRefExpr::VK_Mips_ABS_HI:
2504 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2505 // 16 bits being negative.
2506 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2507 break;
2508 case MCSymbolRefExpr::VK_Mips_HIGHER:
2509 // Get the 3rd 16-bits.
2510 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2511 break;
2512 case MCSymbolRefExpr::VK_Mips_HIGHEST:
2513 // Get the 4th 16-bits.
2514 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2515 break;
2516 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00002517 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00002518 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00002519 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002520 }
2521
Jack Carterb5cf5902013-04-17 00:18:04 +00002522 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002523 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00002524 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00002525 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00002526 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002527 return Res;
2528 }
2529
2530 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00002531 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2532
Sasa Stankovic06c47802014-04-03 10:37:45 +00002533 // Try to create target expression.
2534 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
2535 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002536
Jack Carterd0bd6422013-04-18 00:41:53 +00002537 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2538 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00002539 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
2540 return Res;
2541 }
2542
2543 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002544 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
2545 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
2546 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002547 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002548 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002549 return Expr;
2550}
2551
2552bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2553
2554 switch (Expr->getKind()) {
2555 case MCExpr::Constant:
2556 return true;
2557 case MCExpr::SymbolRef:
2558 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2559 case MCExpr::Binary:
2560 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2561 if (!isEvaluated(BE->getLHS()))
2562 return false;
2563 return isEvaluated(BE->getRHS());
2564 }
2565 case MCExpr::Unary:
2566 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002567 case MCExpr::Target:
2568 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002569 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002570 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002571}
Jack Carterd0bd6422013-04-18 00:41:53 +00002572
Jack Carterb5cf5902013-04-17 00:18:04 +00002573bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002574 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00002575 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002576 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002577 if (Tok.isNot(AsmToken::Identifier))
2578 return true;
2579
Yaron Keren075759a2015-03-30 15:42:36 +00002580 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00002581
Jack Carterd0bd6422013-04-18 00:41:53 +00002582 Parser.Lex(); // Eat the identifier.
2583 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002584 const MCExpr *IdVal;
2585 SMLoc EndLoc;
2586
2587 if (getLexer().getKind() == AsmToken::LParen) {
2588 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002589 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002590 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002591 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002592 const AsmToken &nextTok = Parser.getTok();
2593 if (nextTok.isNot(AsmToken::Identifier))
2594 return true;
2595 Str += "(%";
2596 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002597 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002598 if (getLexer().getKind() != AsmToken::LParen)
2599 return true;
2600 } else
2601 break;
2602 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002603 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002604 return true;
2605
2606 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002607 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002608
2609 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002610 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002611
Jack Carterd0bd6422013-04-18 00:41:53 +00002612 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002613 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002614}
2615
Jack Carterb4dbc172012-09-05 23:34:03 +00002616bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2617 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002618 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002619 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002620 if (ResTy == MatchOperand_Success) {
2621 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002622 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002623 StartLoc = Operand.getStartLoc();
2624 EndLoc = Operand.getEndLoc();
2625
2626 // AFAIK, we only support numeric registers and named GPR's in CFI
2627 // directives.
2628 // Don't worry about eating tokens before failing. Using an unrecognised
2629 // register is a parse error.
2630 if (Operand.isGPRAsmReg()) {
2631 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002632 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002633 }
2634
2635 return (RegNo == (unsigned)-1);
2636 }
2637
2638 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002639 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002640}
2641
Jack Carterb5cf5902013-04-17 00:18:04 +00002642bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002643 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00002644 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002645 bool Result = true;
2646
2647 while (getLexer().getKind() == AsmToken::LParen)
2648 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002649
Jack Carterd0bd6422013-04-18 00:41:53 +00002650 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002651 default:
2652 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002653 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002654 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002655 case AsmToken::Integer:
2656 case AsmToken::Minus:
2657 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002658 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002659 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002660 else
2661 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002662 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002663 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002664 break;
Jack Carter873c7242013-01-12 01:03:14 +00002665 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002666 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002667 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002668 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002669}
2670
David Blaikie960ea3f2014-06-08 16:18:35 +00002671MipsAsmParser::OperandMatchResultTy
2672MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002673 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002674 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002675 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002676 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002677 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002678 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002679 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002680 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002681
Jack Carterb5cf5902013-04-17 00:18:04 +00002682 if (getLexer().getKind() == AsmToken::LParen) {
2683 Parser.Lex();
2684 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002685 }
2686
Jack Carterb5cf5902013-04-17 00:18:04 +00002687 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002688 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002689 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002690
Jack Carterd0bd6422013-04-18 00:41:53 +00002691 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002692 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002693 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2694 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002695 SMLoc E =
2696 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002697 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002698 return MatchOperand_Success;
2699 }
2700 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002701 SMLoc E =
2702 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002703
Jack Carterd0bd6422013-04-18 00:41:53 +00002704 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002705 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002706 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002707 S, E, *this);
2708 Operands.push_back(
2709 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002710 return MatchOperand_Success;
2711 }
2712 Error(Parser.getTok().getLoc(), "'(' expected");
2713 return MatchOperand_ParseFail;
2714 }
2715
Jack Carterd0bd6422013-04-18 00:41:53 +00002716 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002717 }
2718
Toma Tabacu13964452014-09-04 13:23:44 +00002719 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002720 if (Res != MatchOperand_Success)
2721 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002722
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002723 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002724 Error(Parser.getTok().getLoc(), "')' expected");
2725 return MatchOperand_ParseFail;
2726 }
2727
Jack Carter873c7242013-01-12 01:03:14 +00002728 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2729
Jack Carterd0bd6422013-04-18 00:41:53 +00002730 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002731
Craig Topper062a2ba2014-04-25 05:30:21 +00002732 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002733 IdVal = MCConstantExpr::Create(0, getContext());
2734
Jack Carterd0bd6422013-04-18 00:41:53 +00002735 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002736 std::unique_ptr<MipsOperand> op(
2737 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002738 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002739 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002740 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002741 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002742 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2743 int64_t Imm;
2744 if (IdVal->EvaluateAsAbsolute(Imm))
2745 IdVal = MCConstantExpr::Create(Imm, getContext());
2746 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2747 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2748 getContext());
2749 }
2750
David Blaikie960ea3f2014-06-08 16:18:35 +00002751 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002752 return MatchOperand_Success;
2753}
2754
David Blaikie960ea3f2014-06-08 16:18:35 +00002755bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002756 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00002757 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2758 if (Sym) {
2759 SMLoc S = Parser.getTok().getLoc();
2760 const MCExpr *Expr;
2761 if (Sym->isVariable())
2762 Expr = Sym->getVariableValue();
2763 else
2764 return false;
2765 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002766 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002767 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002768 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002769 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002770 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002771 if (ResTy == MatchOperand_Success) {
2772 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002773 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002774 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002775 llvm_unreachable("Should never ParseFail");
2776 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002777 }
2778 } else if (Expr->getKind() == MCExpr::Constant) {
2779 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002780 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002781 Operands.push_back(
2782 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002783 return true;
2784 }
2785 }
2786 return false;
2787}
Jack Carterd0bd6422013-04-18 00:41:53 +00002788
Jack Carter873c7242013-01-12 01:03:14 +00002789MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002790MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002791 StringRef Identifier,
2792 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002793 int Index = matchCPURegisterName(Identifier);
2794 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002795 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002796 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2797 return MatchOperand_Success;
2798 }
2799
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002800 Index = matchHWRegsRegisterName(Identifier);
2801 if (Index != -1) {
2802 Operands.push_back(MipsOperand::createHWRegsReg(
2803 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2804 return MatchOperand_Success;
2805 }
2806
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002807 Index = matchFPURegisterName(Identifier);
2808 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002809 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002810 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2811 return MatchOperand_Success;
2812 }
2813
2814 Index = matchFCCRegisterName(Identifier);
2815 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002816 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002817 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2818 return MatchOperand_Success;
2819 }
2820
2821 Index = matchACRegisterName(Identifier);
2822 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002823 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002824 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2825 return MatchOperand_Success;
2826 }
2827
2828 Index = matchMSA128RegisterName(Identifier);
2829 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002830 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002831 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2832 return MatchOperand_Success;
2833 }
2834
2835 Index = matchMSA128CtrlRegisterName(Identifier);
2836 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002837 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002838 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2839 return MatchOperand_Success;
2840 }
2841
2842 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002843}
2844
2845MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002846MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002847 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00002848 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002849
2850 if (Token.is(AsmToken::Identifier)) {
2851 DEBUG(dbgs() << ".. identifier\n");
2852 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002853 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002854 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002855 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002856 } else if (Token.is(AsmToken::Integer)) {
2857 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002858 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002859 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2860 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002861 return MatchOperand_Success;
2862 }
2863
2864 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2865
2866 return MatchOperand_NoMatch;
2867}
2868
David Blaikie960ea3f2014-06-08 16:18:35 +00002869MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002870MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002871 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002872 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002873
2874 auto Token = Parser.getTok();
2875
2876 SMLoc S = Token.getLoc();
2877
2878 if (Token.isNot(AsmToken::Dollar)) {
2879 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2880 if (Token.is(AsmToken::Identifier)) {
2881 if (searchSymbolAlias(Operands))
2882 return MatchOperand_Success;
2883 }
2884 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2885 return MatchOperand_NoMatch;
2886 }
2887 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002888
Toma Tabacu13964452014-09-04 13:23:44 +00002889 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002890 if (ResTy == MatchOperand_Success) {
2891 Parser.Lex(); // $
2892 Parser.Lex(); // identifier
2893 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002894 return ResTy;
2895}
2896
2897MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002898MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002899 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002900 switch (getLexer().getKind()) {
2901 default:
2902 return MatchOperand_NoMatch;
2903 case AsmToken::LParen:
2904 case AsmToken::Minus:
2905 case AsmToken::Plus:
2906 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002907 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002908 case AsmToken::String:
2909 break;
2910 }
2911
2912 const MCExpr *IdVal;
2913 SMLoc S = Parser.getTok().getLoc();
2914 if (getParser().parseExpression(IdVal))
2915 return MatchOperand_ParseFail;
2916
2917 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2918 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2919 return MatchOperand_Success;
2920}
2921
David Blaikie960ea3f2014-06-08 16:18:35 +00002922MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002923MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002924 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002925 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002926
2927 SMLoc S = getLexer().getLoc();
2928
2929 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002930 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002931 if (ResTy != MatchOperand_NoMatch)
2932 return ResTy;
2933
Daniel Sanders315386c2014-04-01 10:40:14 +00002934 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002935 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002936 if (ResTy != MatchOperand_NoMatch)
2937 return ResTy;
2938
Daniel Sandersffd84362014-04-01 10:41:48 +00002939 const MCExpr *Expr = nullptr;
2940 if (Parser.parseExpression(Expr)) {
2941 // We have no way of knowing if a symbol was consumed so we must ParseFail
2942 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002943 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002944 Operands.push_back(
2945 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002946 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002947}
2948
Vladimir Medic2b953d02013-10-01 09:48:56 +00002949MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002950MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002951 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00002952 const MCExpr *IdVal;
2953 // If the first token is '$' we may have register operand.
2954 if (Parser.getTok().is(AsmToken::Dollar))
2955 return MatchOperand_NoMatch;
2956 SMLoc S = Parser.getTok().getLoc();
2957 if (getParser().parseExpression(IdVal))
2958 return MatchOperand_ParseFail;
2959 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002960 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002961 int64_t Val = MCE->getValue();
2962 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2963 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002964 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002965 return MatchOperand_Success;
2966}
2967
Matheus Almeida779c5932013-11-18 12:32:49 +00002968MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002969MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002970 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00002971 switch (getLexer().getKind()) {
2972 default:
2973 return MatchOperand_NoMatch;
2974 case AsmToken::LParen:
2975 case AsmToken::Plus:
2976 case AsmToken::Minus:
2977 case AsmToken::Integer:
2978 break;
2979 }
2980
2981 const MCExpr *Expr;
2982 SMLoc S = Parser.getTok().getLoc();
2983
2984 if (getParser().parseExpression(Expr))
2985 return MatchOperand_ParseFail;
2986
2987 int64_t Val;
2988 if (!Expr->EvaluateAsAbsolute(Val)) {
2989 Error(S, "expected immediate value");
2990 return MatchOperand_ParseFail;
2991 }
2992
2993 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2994 // and because the CPU always adds one to the immediate field, the allowed
2995 // range becomes 1..4. We'll only check the range here and will deal
2996 // with the addition/subtraction when actually decoding/encoding
2997 // the instruction.
2998 if (Val < 1 || Val > 4) {
2999 Error(S, "immediate not in range (1..4)");
3000 return MatchOperand_ParseFail;
3001 }
3002
Jack Carter3b2c96e2014-01-22 23:31:38 +00003003 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003004 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00003005 return MatchOperand_Success;
3006}
3007
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00003008MipsAsmParser::OperandMatchResultTy
3009MipsAsmParser::parseRegisterList(OperandVector &Operands) {
3010 MCAsmParser &Parser = getParser();
3011 SmallVector<unsigned, 10> Regs;
3012 unsigned RegNo;
3013 unsigned PrevReg = Mips::NoRegister;
3014 bool RegRange = false;
3015 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3016
3017 if (Parser.getTok().isNot(AsmToken::Dollar))
3018 return MatchOperand_ParseFail;
3019
3020 SMLoc S = Parser.getTok().getLoc();
3021 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
3022 SMLoc E = getLexer().getLoc();
3023 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
3024 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
3025 if (RegRange) {
3026 // Remove last register operand because registers from register range
3027 // should be inserted first.
3028 if (RegNo == Mips::RA) {
3029 Regs.push_back(RegNo);
3030 } else {
3031 unsigned TmpReg = PrevReg + 1;
3032 while (TmpReg <= RegNo) {
3033 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
3034 Error(E, "invalid register operand");
3035 return MatchOperand_ParseFail;
3036 }
3037
3038 PrevReg = TmpReg;
3039 Regs.push_back(TmpReg++);
3040 }
3041 }
3042
3043 RegRange = false;
3044 } else {
3045 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
3046 (RegNo != Mips::RA)) {
3047 Error(E, "$16 or $31 expected");
3048 return MatchOperand_ParseFail;
3049 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
3050 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3051 Error(E, "invalid register operand");
3052 return MatchOperand_ParseFail;
3053 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
3054 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3055 Error(E, "consecutive register numbers expected");
3056 return MatchOperand_ParseFail;
3057 }
3058
3059 Regs.push_back(RegNo);
3060 }
3061
3062 if (Parser.getTok().is(AsmToken::Minus))
3063 RegRange = true;
3064
3065 if (!Parser.getTok().isNot(AsmToken::Minus) &&
3066 !Parser.getTok().isNot(AsmToken::Comma)) {
3067 Error(E, "',' or '-' expected");
3068 return MatchOperand_ParseFail;
3069 }
3070
3071 Lex(); // Consume comma or minus
3072 if (Parser.getTok().isNot(AsmToken::Dollar))
3073 break;
3074
3075 PrevReg = RegNo;
3076 }
3077
3078 SMLoc E = Parser.getTok().getLoc();
3079 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3080 parseMemOperand(Operands);
3081 return MatchOperand_Success;
3082}
3083
Zoran Jovanovic2deca342014-12-16 14:59:10 +00003084MipsAsmParser::OperandMatchResultTy
3085MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
3086 MCAsmParser &Parser = getParser();
3087
3088 SMLoc S = Parser.getTok().getLoc();
3089 if (parseAnyRegister(Operands) != MatchOperand_Success)
3090 return MatchOperand_ParseFail;
3091
3092 SMLoc E = Parser.getTok().getLoc();
3093 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
3094 unsigned Reg = Op.getGPR32Reg();
3095 Operands.pop_back();
3096 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
3097 return MatchOperand_Success;
3098}
3099
Zoran Jovanovic41688672015-02-10 16:36:20 +00003100MipsAsmParser::OperandMatchResultTy
3101MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
3102 MCAsmParser &Parser = getParser();
3103 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3104 SmallVector<unsigned, 10> Regs;
3105
3106 if (Parser.getTok().isNot(AsmToken::Dollar))
3107 return MatchOperand_ParseFail;
3108
3109 SMLoc S = Parser.getTok().getLoc();
3110
3111 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3112 return MatchOperand_ParseFail;
3113
3114 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3115 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3116 Regs.push_back(RegNo);
3117
3118 SMLoc E = Parser.getTok().getLoc();
3119 if (Parser.getTok().isNot(AsmToken::Comma)) {
3120 Error(E, "',' expected");
3121 return MatchOperand_ParseFail;
3122 }
3123
3124 // Remove comma.
3125 Parser.Lex();
3126
3127 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3128 return MatchOperand_ParseFail;
3129
3130 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3131 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3132 Regs.push_back(RegNo);
3133
3134 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3135
3136 return MatchOperand_Success;
3137}
3138
Jack Carterdc1e35d2012-09-06 20:00:02 +00003139MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
3140
Vladimir Medic4c299852013-11-06 11:27:05 +00003141 MCSymbolRefExpr::VariantKind VK =
3142 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
3143 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
3144 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
3145 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
3146 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
3147 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
3148 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
3149 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
3150 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
3151 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
3152 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
3153 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
3154 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
3155 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
3156 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
3157 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
3158 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
3159 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00003160 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
3161 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
3162 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
3163 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
3164 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
3165 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00003166 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
3167 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00003168 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003169
Matheus Almeida2852af82014-04-22 10:15:54 +00003170 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00003171
Jack Carterdc1e35d2012-09-06 20:00:02 +00003172 return VK;
3173}
Jack Cartera63b16a2012-09-07 00:23:42 +00003174
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003175/// Sometimes (i.e. load/stores) the operand may be followed immediately by
3176/// either this.
3177/// ::= '(', register, ')'
3178/// handle it before we iterate so we don't get tripped up by the lack of
3179/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003180bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003181 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003182 if (getLexer().is(AsmToken::LParen)) {
3183 Operands.push_back(
3184 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
3185 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003186 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003187 SMLoc Loc = getLexer().getLoc();
3188 Parser.eatToEndOfStatement();
3189 return Error(Loc, "unexpected token in argument list");
3190 }
3191 if (Parser.getTok().isNot(AsmToken::RParen)) {
3192 SMLoc Loc = getLexer().getLoc();
3193 Parser.eatToEndOfStatement();
3194 return Error(Loc, "unexpected token, expected ')'");
3195 }
3196 Operands.push_back(
3197 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
3198 Parser.Lex();
3199 }
3200 return false;
3201}
3202
3203/// Sometimes (i.e. in MSA) the operand may be followed immediately by
3204/// either one of these.
3205/// ::= '[', register, ']'
3206/// ::= '[', integer, ']'
3207/// handle it before we iterate so we don't get tripped up by the lack of
3208/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003209bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00003210 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003211 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003212 if (getLexer().is(AsmToken::LBrac)) {
3213 Operands.push_back(
3214 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
3215 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003216 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003217 SMLoc Loc = getLexer().getLoc();
3218 Parser.eatToEndOfStatement();
3219 return Error(Loc, "unexpected token in argument list");
3220 }
3221 if (Parser.getTok().isNot(AsmToken::RBrac)) {
3222 SMLoc Loc = getLexer().getLoc();
3223 Parser.eatToEndOfStatement();
3224 return Error(Loc, "unexpected token, expected ']'");
3225 }
3226 Operands.push_back(
3227 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
3228 Parser.Lex();
3229 }
3230 return false;
3231}
3232
David Blaikie960ea3f2014-06-08 16:18:35 +00003233bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
3234 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003235 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003236 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003237
3238 // We have reached first instruction, module directive are now forbidden.
3239 getTargetStreamer().forbidModuleDirective();
3240
Vladimir Medic74593e62013-07-17 15:00:42 +00003241 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00003242 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00003243 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00003244 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00003245 }
Vladimir Medic64828a12013-07-16 10:07:14 +00003246 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003247 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003248
3249 // Read the remaining operands.
3250 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3251 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003252 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003253 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003254 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003255 return Error(Loc, "unexpected token in argument list");
3256 }
Toma Tabacu13964452014-09-04 13:23:44 +00003257 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003258 return true;
3259 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00003260
Jack Carterd0bd6422013-04-18 00:41:53 +00003261 while (getLexer().is(AsmToken::Comma)) {
3262 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00003263 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003264 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003265 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003266 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003267 return Error(Loc, "unexpected token in argument list");
3268 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003269 // Parse bracket and parenthesis suffixes before we iterate
3270 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00003271 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003272 return true;
3273 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00003274 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003275 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003276 }
3277 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003278 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3279 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003280 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003281 return Error(Loc, "unexpected token in argument list");
3282 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003283 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00003284 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00003285}
3286
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003287bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003288 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003289 SMLoc Loc = getLexer().getLoc();
3290 Parser.eatToEndOfStatement();
3291 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00003292}
3293
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003294bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003295 return Error(Loc, ErrorMsg);
3296}
3297
Jack Carter0b744b32012-10-04 02:29:46 +00003298bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003299 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003300 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00003301
3302 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00003303 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00003304
3305 Parser.Lex(); // Eat "noat".
3306
Jack Carterd0bd6422013-04-18 00:41:53 +00003307 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003308 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003309 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003310 return false;
3311 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003312
3313 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003314 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003315 return false;
3316}
Jack Carterd0bd6422013-04-18 00:41:53 +00003317
Jack Carter0b744b32012-10-04 02:29:46 +00003318bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00003319 // Line can be: ".set at", which sets $at to $1
3320 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00003321 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00003322 Parser.Lex(); // Eat "at".
3323
Jack Carter0b744b32012-10-04 02:29:46 +00003324 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003325 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00003326 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00003327
3328 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003329 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003330 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00003331 }
3332
3333 if (getLexer().isNot(AsmToken::Equal)) {
3334 reportParseError("unexpected token, expected equals sign");
3335 return false;
3336 }
3337 Parser.Lex(); // Eat "=".
3338
3339 if (getLexer().isNot(AsmToken::Dollar)) {
3340 if (getLexer().is(AsmToken::EndOfStatement)) {
3341 reportParseError("no register specified");
3342 return false;
3343 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00003344 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00003345 return false;
3346 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003347 }
3348 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00003349
Toma Tabacu16a74492015-02-13 10:30:57 +00003350 // Find out what "reg" is.
3351 unsigned AtRegNo;
3352 const AsmToken &Reg = Parser.getTok();
3353 if (Reg.is(AsmToken::Identifier)) {
3354 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
3355 } else if (Reg.is(AsmToken::Integer)) {
3356 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00003357 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00003358 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00003359 return false;
3360 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003361
3362 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00003363 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003364 reportParseError("invalid register");
3365 return false;
3366 }
3367 Parser.Lex(); // Eat "reg".
3368
3369 // If this is not the end of the statement, report an error.
3370 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3371 reportParseError("unexpected token, expected end of statement");
3372 return false;
3373 }
3374
3375 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
3376
3377 Parser.Lex(); // Consume the EndOfStatement.
3378 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003379}
3380
3381bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003382 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003383 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003384 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003385 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003386 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003387 return false;
3388 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003389 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00003390 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003391 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003392 return false;
3393}
3394
3395bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003396 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003397 Parser.Lex();
3398 // If this is not the end of the statement, report an error.
3399 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003400 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003401 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003402 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003403 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00003404 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003405 Parser.Lex(); // Consume the EndOfStatement.
3406 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003407}
3408
3409bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003410 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003411 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003412 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003413 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003414 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003415 return false;
3416 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003417 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003418 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003419 return false;
3420}
3421
3422bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003423 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003424 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003425 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003426 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003427 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003428 return false;
3429 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003430 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00003431 reportParseError("`noreorder' must be set before `nomacro'");
3432 return false;
3433 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003434 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003435 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003436 return false;
3437}
Jack Carterd76b2372013-03-21 21:44:16 +00003438
Daniel Sanders44934432014-08-07 12:03:36 +00003439bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003440 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003441 Parser.Lex();
3442
3443 // If this is not the end of the statement, report an error.
3444 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003445 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003446
3447 setFeatureBits(Mips::FeatureMSA, "msa");
3448 getTargetStreamer().emitDirectiveSetMsa();
3449 return false;
3450}
3451
3452bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003453 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003454 Parser.Lex();
3455
3456 // If this is not the end of the statement, report an error.
3457 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003458 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003459
3460 clearFeatureBits(Mips::FeatureMSA, "msa");
3461 getTargetStreamer().emitDirectiveSetNoMsa();
3462 return false;
3463}
3464
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003465bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003466 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003467 Parser.Lex(); // Eat "nodsp".
3468
3469 // If this is not the end of the statement, report an error.
3470 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3471 reportParseError("unexpected token, expected end of statement");
3472 return false;
3473 }
3474
3475 clearFeatureBits(Mips::FeatureDSP, "dsp");
3476 getTargetStreamer().emitDirectiveSetNoDsp();
3477 return false;
3478}
3479
Toma Tabacucc2502d2014-11-04 17:18:07 +00003480bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003481 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003482 Parser.Lex(); // Eat "mips16".
3483
Jack Carter39536722014-01-22 23:08:42 +00003484 // If this is not the end of the statement, report an error.
3485 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003486 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00003487 return false;
3488 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00003489
3490 setFeatureBits(Mips::FeatureMips16, "mips16");
3491 getTargetStreamer().emitDirectiveSetMips16();
3492 Parser.Lex(); // Consume the EndOfStatement.
3493 return false;
3494}
3495
3496bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003497 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003498 Parser.Lex(); // Eat "nomips16".
3499
3500 // If this is not the end of the statement, report an error.
3501 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3502 reportParseError("unexpected token, expected end of statement");
3503 return false;
3504 }
3505
3506 clearFeatureBits(Mips::FeatureMips16, "mips16");
3507 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00003508 Parser.Lex(); // Consume the EndOfStatement.
3509 return false;
3510}
3511
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003512bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003513 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003514 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003515 // Line can be: .set fp=32
3516 // .set fp=xx
3517 // .set fp=64
3518 Parser.Lex(); // Eat fp token
3519 AsmToken Tok = Parser.getTok();
3520 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003521 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003522 return false;
3523 }
3524 Parser.Lex(); // Eat '=' token.
3525 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003526
3527 if (!parseFpABIValue(FpAbiVal, ".set"))
3528 return false;
3529
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003530 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003531 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003532 return false;
3533 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003534 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003535 Parser.Lex(); // Consume the EndOfStatement.
3536 return false;
3537}
3538
Toma Tabacu9db22db2014-09-09 10:15:38 +00003539bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003540 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003541 SMLoc Loc = getLexer().getLoc();
3542
3543 Parser.Lex();
3544 if (getLexer().isNot(AsmToken::EndOfStatement))
3545 return reportParseError("unexpected token, expected end of statement");
3546
3547 // Always keep an element on the options "stack" to prevent the user
3548 // from changing the initial options. This is how we remember them.
3549 if (AssemblerOptions.size() == 2)
3550 return reportParseError(Loc, ".set pop with no .set push");
3551
3552 AssemblerOptions.pop_back();
3553 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
3554
3555 getTargetStreamer().emitDirectiveSetPop();
3556 return false;
3557}
3558
3559bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003560 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003561 Parser.Lex();
3562 if (getLexer().isNot(AsmToken::EndOfStatement))
3563 return reportParseError("unexpected token, expected end of statement");
3564
3565 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00003566 AssemblerOptions.push_back(
3567 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00003568
3569 getTargetStreamer().emitDirectiveSetPush();
3570 return false;
3571}
3572
Jack Carterd76b2372013-03-21 21:44:16 +00003573bool MipsAsmParser::parseSetAssignment() {
3574 StringRef Name;
3575 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00003576 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00003577
3578 if (Parser.parseIdentifier(Name))
3579 reportParseError("expected identifier after .set");
3580
3581 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003582 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00003583 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00003584
Jack Carter3b2c96e2014-01-22 23:31:38 +00003585 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00003586 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00003587
Toma Tabacuf25949b2015-04-07 13:59:39 +00003588 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00003589 Sym->setVariableValue(Value);
3590
3591 return false;
3592}
Jack Carterd0bd6422013-04-18 00:41:53 +00003593
Toma Tabacu26647792014-09-09 12:52:14 +00003594bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003595 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00003596 Parser.Lex();
3597 if (getLexer().isNot(AsmToken::EndOfStatement))
3598 return reportParseError("unexpected token, expected end of statement");
3599
3600 // Reset assembler options to their initial values.
3601 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
3602 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
3603
3604 getTargetStreamer().emitDirectiveSetMips0();
3605 return false;
3606}
3607
Toma Tabacu85618b32014-08-19 14:22:52 +00003608bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003609 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00003610 Parser.Lex();
3611 if (getLexer().isNot(AsmToken::Equal))
3612 return reportParseError("unexpected token, expected equals sign");
3613
3614 Parser.Lex();
3615 StringRef Arch;
3616 if (Parser.parseIdentifier(Arch))
3617 return reportParseError("expected arch identifier");
3618
3619 StringRef ArchFeatureName =
3620 StringSwitch<StringRef>(Arch)
3621 .Case("mips1", "mips1")
3622 .Case("mips2", "mips2")
3623 .Case("mips3", "mips3")
3624 .Case("mips4", "mips4")
3625 .Case("mips5", "mips5")
3626 .Case("mips32", "mips32")
3627 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003628 .Case("mips32r3", "mips32r3")
3629 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003630 .Case("mips32r6", "mips32r6")
3631 .Case("mips64", "mips64")
3632 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003633 .Case("mips64r3", "mips64r3")
3634 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003635 .Case("mips64r6", "mips64r6")
3636 .Case("cnmips", "cnmips")
3637 .Case("r4000", "mips3") // This is an implementation of Mips3.
3638 .Default("");
3639
3640 if (ArchFeatureName.empty())
3641 return reportParseError("unsupported architecture");
3642
3643 selectArch(ArchFeatureName);
3644 getTargetStreamer().emitDirectiveSetArch(Arch);
3645 return false;
3646}
3647
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003648bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003649 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003650 Parser.Lex();
3651 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003652 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003653
Matheus Almeida2852af82014-04-22 10:15:54 +00003654 switch (Feature) {
3655 default:
3656 llvm_unreachable("Unimplemented feature");
3657 case Mips::FeatureDSP:
3658 setFeatureBits(Mips::FeatureDSP, "dsp");
3659 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003660 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003661 case Mips::FeatureMicroMips:
3662 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003663 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003664 case Mips::FeatureMips1:
3665 selectArch("mips1");
3666 getTargetStreamer().emitDirectiveSetMips1();
3667 break;
3668 case Mips::FeatureMips2:
3669 selectArch("mips2");
3670 getTargetStreamer().emitDirectiveSetMips2();
3671 break;
3672 case Mips::FeatureMips3:
3673 selectArch("mips3");
3674 getTargetStreamer().emitDirectiveSetMips3();
3675 break;
3676 case Mips::FeatureMips4:
3677 selectArch("mips4");
3678 getTargetStreamer().emitDirectiveSetMips4();
3679 break;
3680 case Mips::FeatureMips5:
3681 selectArch("mips5");
3682 getTargetStreamer().emitDirectiveSetMips5();
3683 break;
3684 case Mips::FeatureMips32:
3685 selectArch("mips32");
3686 getTargetStreamer().emitDirectiveSetMips32();
3687 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003688 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003689 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003690 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003691 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003692 case Mips::FeatureMips32r3:
3693 selectArch("mips32r3");
3694 getTargetStreamer().emitDirectiveSetMips32R3();
3695 break;
3696 case Mips::FeatureMips32r5:
3697 selectArch("mips32r5");
3698 getTargetStreamer().emitDirectiveSetMips32R5();
3699 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003700 case Mips::FeatureMips32r6:
3701 selectArch("mips32r6");
3702 getTargetStreamer().emitDirectiveSetMips32R6();
3703 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003704 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003705 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00003706 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003707 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003708 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003709 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003710 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003711 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003712 case Mips::FeatureMips64r3:
3713 selectArch("mips64r3");
3714 getTargetStreamer().emitDirectiveSetMips64R3();
3715 break;
3716 case Mips::FeatureMips64r5:
3717 selectArch("mips64r5");
3718 getTargetStreamer().emitDirectiveSetMips64R5();
3719 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003720 case Mips::FeatureMips64r6:
3721 selectArch("mips64r6");
3722 getTargetStreamer().emitDirectiveSetMips64R6();
3723 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003724 }
3725 return false;
3726}
3727
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003728bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003729 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003730 if (getLexer().isNot(AsmToken::Comma)) {
3731 SMLoc Loc = getLexer().getLoc();
3732 Parser.eatToEndOfStatement();
3733 return Error(Loc, ErrorStr);
3734 }
3735
Matheus Almeida2852af82014-04-22 10:15:54 +00003736 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003737 return true;
3738}
3739
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003740bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003741 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00003742 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003743
Toma Tabacudde4c462014-11-06 10:02:45 +00003744 if (inMips16Mode()) {
3745 reportParseError(".cpload is not supported in Mips16 mode");
3746 return false;
3747 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003748
David Blaikie960ea3f2014-06-08 16:18:35 +00003749 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00003750 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003751 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3752 reportParseError("expected register containing function address");
3753 return false;
3754 }
3755
David Blaikie960ea3f2014-06-08 16:18:35 +00003756 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
3757 if (!RegOpnd.isGPRAsmReg()) {
3758 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003759 return false;
3760 }
3761
Toma Tabacudde4c462014-11-06 10:02:45 +00003762 // If this is not the end of the statement, report an error.
3763 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3764 reportParseError("unexpected token, expected end of statement");
3765 return false;
3766 }
3767
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003768 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003769 return false;
3770}
3771
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003772bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003773 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003774 unsigned FuncReg;
3775 unsigned Save;
3776 bool SaveIsReg = true;
3777
Matheus Almeida7e815762014-06-18 13:08:59 +00003778 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003779 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003780 if (ResTy == MatchOperand_NoMatch) {
3781 reportParseError("expected register containing function address");
3782 Parser.eatToEndOfStatement();
3783 return false;
3784 }
3785
3786 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3787 if (!FuncRegOpnd.isGPRAsmReg()) {
3788 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3789 Parser.eatToEndOfStatement();
3790 return false;
3791 }
3792
3793 FuncReg = FuncRegOpnd.getGPR32Reg();
3794 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003795
Toma Tabacu65f10572014-09-16 15:00:52 +00003796 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003797 return true;
3798
Toma Tabacu13964452014-09-04 13:23:44 +00003799 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003800 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003801 const AsmToken &Tok = Parser.getTok();
3802 if (Tok.is(AsmToken::Integer)) {
3803 Save = Tok.getIntVal();
3804 SaveIsReg = false;
3805 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003806 } else {
3807 reportParseError("expected save register or stack offset");
3808 Parser.eatToEndOfStatement();
3809 return false;
3810 }
3811 } else {
3812 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3813 if (!SaveOpnd.isGPRAsmReg()) {
3814 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3815 Parser.eatToEndOfStatement();
3816 return false;
3817 }
3818 Save = SaveOpnd.getGPR32Reg();
3819 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003820
Toma Tabacu65f10572014-09-16 15:00:52 +00003821 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003822 return true;
3823
Toma Tabacu8874eac2015-02-18 13:46:53 +00003824 const MCExpr *Expr;
3825 if (Parser.parseExpression(Expr)) {
3826 reportParseError("expected expression");
3827 return false;
3828 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003829
Toma Tabacu8874eac2015-02-18 13:46:53 +00003830 if (Expr->getKind() != MCExpr::SymbolRef) {
3831 reportParseError("expected symbol");
3832 return false;
3833 }
3834 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
3835
3836 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
3837 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003838 return false;
3839}
3840
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003841bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003842 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003843 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3844 const AsmToken &Tok = Parser.getTok();
3845
3846 if (Tok.getString() == "2008") {
3847 Parser.Lex();
3848 getTargetStreamer().emitDirectiveNaN2008();
3849 return false;
3850 } else if (Tok.getString() == "legacy") {
3851 Parser.Lex();
3852 getTargetStreamer().emitDirectiveNaNLegacy();
3853 return false;
3854 }
3855 }
3856 // If we don't recognize the option passed to the .nan
3857 // directive (e.g. no option or unknown option), emit an error.
3858 reportParseError("invalid option in .nan directive");
3859 return false;
3860}
3861
Jack Carter0b744b32012-10-04 02:29:46 +00003862bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003863 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003864 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003865 const AsmToken &Tok = Parser.getTok();
3866
3867 if (Tok.getString() == "noat") {
3868 return parseSetNoAtDirective();
3869 } else if (Tok.getString() == "at") {
3870 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003871 } else if (Tok.getString() == "arch") {
3872 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003873 } else if (Tok.getString() == "fp") {
3874 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003875 } else if (Tok.getString() == "pop") {
3876 return parseSetPopDirective();
3877 } else if (Tok.getString() == "push") {
3878 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003879 } else if (Tok.getString() == "reorder") {
3880 return parseSetReorderDirective();
3881 } else if (Tok.getString() == "noreorder") {
3882 return parseSetNoReorderDirective();
3883 } else if (Tok.getString() == "macro") {
3884 return parseSetMacroDirective();
3885 } else if (Tok.getString() == "nomacro") {
3886 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003887 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00003888 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003889 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003890 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003891 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003892 getTargetStreamer().emitDirectiveSetNoMicroMips();
3893 Parser.eatToEndOfStatement();
3894 return false;
3895 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003896 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003897 } else if (Tok.getString() == "mips0") {
3898 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003899 } else if (Tok.getString() == "mips1") {
3900 return parseSetFeature(Mips::FeatureMips1);
3901 } else if (Tok.getString() == "mips2") {
3902 return parseSetFeature(Mips::FeatureMips2);
3903 } else if (Tok.getString() == "mips3") {
3904 return parseSetFeature(Mips::FeatureMips3);
3905 } else if (Tok.getString() == "mips4") {
3906 return parseSetFeature(Mips::FeatureMips4);
3907 } else if (Tok.getString() == "mips5") {
3908 return parseSetFeature(Mips::FeatureMips5);
3909 } else if (Tok.getString() == "mips32") {
3910 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003911 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003912 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003913 } else if (Tok.getString() == "mips32r3") {
3914 return parseSetFeature(Mips::FeatureMips32r3);
3915 } else if (Tok.getString() == "mips32r5") {
3916 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003917 } else if (Tok.getString() == "mips32r6") {
3918 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003919 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003920 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003921 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003922 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003923 } else if (Tok.getString() == "mips64r3") {
3924 return parseSetFeature(Mips::FeatureMips64r3);
3925 } else if (Tok.getString() == "mips64r5") {
3926 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003927 } else if (Tok.getString() == "mips64r6") {
3928 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003929 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003930 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003931 } else if (Tok.getString() == "nodsp") {
3932 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003933 } else if (Tok.getString() == "msa") {
3934 return parseSetMsaDirective();
3935 } else if (Tok.getString() == "nomsa") {
3936 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003937 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003938 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003939 parseSetAssignment();
3940 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003941 }
Jack Carter07c818d2013-01-25 01:31:34 +00003942
Jack Carter0b744b32012-10-04 02:29:46 +00003943 return true;
3944}
3945
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003946/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003947/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003948bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003949 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003950 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3951 for (;;) {
3952 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003953 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003954 return true;
3955
3956 getParser().getStreamer().EmitValue(Value, Size);
3957
3958 if (getLexer().is(AsmToken::EndOfStatement))
3959 break;
3960
Jack Carter07c818d2013-01-25 01:31:34 +00003961 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003962 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00003963 Parser.Lex();
3964 }
3965 }
3966
3967 Parser.Lex();
3968 return false;
3969}
3970
Vladimir Medic4c299852013-11-06 11:27:05 +00003971/// parseDirectiveGpWord
3972/// ::= .gpword local_sym
3973bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003974 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003975 const MCExpr *Value;
3976 // EmitGPRel32Value requires an expression, so we are using base class
3977 // method to evaluate the expression.
3978 if (getParser().parseExpression(Value))
3979 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00003980 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00003981
Vladimir Medice10c1122013-11-13 13:18:04 +00003982 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003983 return Error(getLexer().getLoc(),
3984 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00003985 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00003986 return false;
3987}
3988
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003989/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00003990/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003991bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003992 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003993 const MCExpr *Value;
3994 // EmitGPRel64Value requires an expression, so we are using base class
3995 // method to evaluate the expression.
3996 if (getParser().parseExpression(Value))
3997 return true;
3998 getParser().getStreamer().EmitGPRel64Value(Value);
3999
4000 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004001 return Error(getLexer().getLoc(),
4002 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00004003 Parser.Lex(); // Eat EndOfStatement token.
4004 return false;
4005}
4006
Jack Carter0cd3c192014-01-06 23:27:31 +00004007bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004008 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00004009 // Get the option token.
4010 AsmToken Tok = Parser.getTok();
4011 // At the moment only identifiers are supported.
4012 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004013 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00004014 Parser.eatToEndOfStatement();
4015 return false;
4016 }
4017
4018 StringRef Option = Tok.getIdentifier();
4019
4020 if (Option == "pic0") {
4021 getTargetStreamer().emitDirectiveOptionPic0();
4022 Parser.Lex();
4023 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4024 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004025 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004026 Parser.eatToEndOfStatement();
4027 }
4028 return false;
4029 }
4030
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004031 if (Option == "pic2") {
4032 getTargetStreamer().emitDirectiveOptionPic2();
4033 Parser.Lex();
4034 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4035 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004036 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004037 Parser.eatToEndOfStatement();
4038 }
4039 return false;
4040 }
4041
Jack Carter0cd3c192014-01-06 23:27:31 +00004042 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00004043 Warning(Parser.getTok().getLoc(),
4044 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00004045 Parser.eatToEndOfStatement();
4046 return false;
4047}
4048
Toma Tabacu9ca50962015-04-16 09:53:47 +00004049/// parseInsnDirective
4050/// ::= .insn
4051bool MipsAsmParser::parseInsnDirective() {
4052 // If this is not the end of the statement, report an error.
4053 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4054 reportParseError("unexpected token, expected end of statement");
4055 return false;
4056 }
4057
4058 // The actual label marking happens in
4059 // MipsELFStreamer::createPendingLabelRelocs().
4060 getTargetStreamer().emitDirectiveInsn();
4061
4062 getParser().Lex(); // Eat EndOfStatement token.
4063 return false;
4064}
4065
Daniel Sanders7e527422014-07-10 13:38:23 +00004066/// parseDirectiveModule
4067/// ::= .module oddspreg
4068/// ::= .module nooddspreg
4069/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004070bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004071 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004072 MCAsmLexer &Lexer = getLexer();
4073 SMLoc L = Lexer.getLoc();
4074
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004075 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004076 // TODO : get a better message.
4077 reportParseError(".module directive must appear before any code");
4078 return false;
4079 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004080
Toma Tabacuc405c822015-01-23 10:40:19 +00004081 StringRef Option;
4082 if (Parser.parseIdentifier(Option)) {
4083 reportParseError("expected .module option identifier");
4084 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004085 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004086
Toma Tabacuc405c822015-01-23 10:40:19 +00004087 if (Option == "oddspreg") {
4088 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
4089 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4090
4091 // If this is not the end of the statement, report an error.
4092 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4093 reportParseError("unexpected token, expected end of statement");
4094 return false;
4095 }
4096
4097 return false; // parseDirectiveModule has finished successfully.
4098 } else if (Option == "nooddspreg") {
4099 if (!isABI_O32()) {
4100 Error(L, "'.module nooddspreg' requires the O32 ABI");
4101 return false;
4102 }
4103
4104 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
4105 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4106
4107 // If this is not the end of the statement, report an error.
4108 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4109 reportParseError("unexpected token, expected end of statement");
4110 return false;
4111 }
4112
4113 return false; // parseDirectiveModule has finished successfully.
4114 } else if (Option == "fp") {
4115 return parseDirectiveModuleFP();
4116 } else {
4117 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
4118 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004119}
4120
4121/// parseDirectiveModuleFP
4122/// ::= =32
4123/// ::= =xx
4124/// ::= =64
4125bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004126 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004127 MCAsmLexer &Lexer = getLexer();
4128
4129 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004130 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004131 return false;
4132 }
4133 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004134
Daniel Sanders7e527422014-07-10 13:38:23 +00004135 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004136 if (!parseFpABIValue(FpABI, ".module"))
4137 return false;
4138
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004139 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004140 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004141 return false;
4142 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004143
Daniel Sanders7201a3e2014-07-08 10:35:52 +00004144 // Emit appropriate flags.
4145 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00004146 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004147 return false;
4148}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004149
Daniel Sanders7e527422014-07-10 13:38:23 +00004150bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004151 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004152 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004153 MCAsmLexer &Lexer = getLexer();
4154
4155 if (Lexer.is(AsmToken::Identifier)) {
4156 StringRef Value = Parser.getTok().getString();
4157 Parser.Lex();
4158
4159 if (Value != "xx") {
4160 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4161 return false;
4162 }
4163
4164 if (!isABI_O32()) {
4165 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
4166 return false;
4167 }
4168
Daniel Sanders7e527422014-07-10 13:38:23 +00004169 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004170 return true;
4171 }
4172
4173 if (Lexer.is(AsmToken::Integer)) {
4174 unsigned Value = Parser.getTok().getIntVal();
4175 Parser.Lex();
4176
4177 if (Value != 32 && Value != 64) {
4178 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4179 return false;
4180 }
4181
4182 if (Value == 32) {
4183 if (!isABI_O32()) {
4184 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
4185 return false;
4186 }
4187
Daniel Sanders7e527422014-07-10 13:38:23 +00004188 FpABI = MipsABIFlagsSection::FpABIKind::S32;
4189 } else
4190 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004191
Daniel Sanders7e527422014-07-10 13:38:23 +00004192 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004193 }
4194
4195 return false;
4196}
4197
Jack Carter0b744b32012-10-04 02:29:46 +00004198bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004199 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004200 StringRef IDVal = DirectiveID.getString();
4201
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004202 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004203 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00004204 if (IDVal == ".dword") {
4205 parseDataDirective(8, DirectiveID.getLoc());
4206 return false;
4207 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004208 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004209 StringRef SymbolName;
4210
4211 if (Parser.parseIdentifier(SymbolName)) {
4212 reportParseError("expected identifier after .ent");
4213 return false;
4214 }
4215
4216 // There's an undocumented extension that allows an integer to
4217 // follow the name of the procedure which AFAICS is ignored by GAS.
4218 // Example: .ent foo,2
4219 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4220 if (getLexer().isNot(AsmToken::Comma)) {
4221 // Even though we accept this undocumented extension for compatibility
4222 // reasons, the additional integer argument does not actually change
4223 // the behaviour of the '.ent' directive, so we would like to discourage
4224 // its use. We do this by not referring to the extended version in
4225 // error messages which are not directly related to its use.
4226 reportParseError("unexpected token, expected end of statement");
4227 return false;
4228 }
4229 Parser.Lex(); // Eat the comma.
4230 const MCExpr *DummyNumber;
4231 int64_t DummyNumberVal;
4232 // If the user was explicitly trying to use the extended version,
4233 // we still give helpful extension-related error messages.
4234 if (Parser.parseExpression(DummyNumber)) {
4235 reportParseError("expected number after comma");
4236 return false;
4237 }
4238 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
4239 reportParseError("expected an absolute expression after comma");
4240 return false;
4241 }
4242 }
4243
4244 // If this is not the end of the statement, report an error.
4245 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4246 reportParseError("unexpected token, expected end of statement");
4247 return false;
4248 }
4249
4250 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
4251
4252 getTargetStreamer().emitDirectiveEnt(*Sym);
4253 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00004254 return false;
4255 }
4256
Jack Carter07c818d2013-01-25 01:31:34 +00004257 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004258 StringRef SymbolName;
4259
4260 if (Parser.parseIdentifier(SymbolName)) {
4261 reportParseError("expected identifier after .end");
4262 return false;
4263 }
4264
4265 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4266 reportParseError("unexpected token, expected end of statement");
4267 return false;
4268 }
4269
4270 if (CurrentFn == nullptr) {
4271 reportParseError(".end used without .ent");
4272 return false;
4273 }
4274
4275 if ((SymbolName != CurrentFn->getName())) {
4276 reportParseError(".end symbol does not match .ent symbol");
4277 return false;
4278 }
4279
4280 getTargetStreamer().emitDirectiveEnd(SymbolName);
4281 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00004282 return false;
4283 }
4284
Jack Carter07c818d2013-01-25 01:31:34 +00004285 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004286 // .frame $stack_reg, frame_size_in_bytes, $return_reg
4287 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004288 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004289 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4290 reportParseError("expected stack register");
4291 return false;
4292 }
4293
4294 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4295 if (!StackRegOpnd.isGPRAsmReg()) {
4296 reportParseError(StackRegOpnd.getStartLoc(),
4297 "expected general purpose register");
4298 return false;
4299 }
4300 unsigned StackReg = StackRegOpnd.getGPR32Reg();
4301
4302 if (Parser.getTok().is(AsmToken::Comma))
4303 Parser.Lex();
4304 else {
4305 reportParseError("unexpected token, expected comma");
4306 return false;
4307 }
4308
4309 // Parse the frame size.
4310 const MCExpr *FrameSize;
4311 int64_t FrameSizeVal;
4312
4313 if (Parser.parseExpression(FrameSize)) {
4314 reportParseError("expected frame size value");
4315 return false;
4316 }
4317
4318 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
4319 reportParseError("frame size not an absolute expression");
4320 return false;
4321 }
4322
4323 if (Parser.getTok().is(AsmToken::Comma))
4324 Parser.Lex();
4325 else {
4326 reportParseError("unexpected token, expected comma");
4327 return false;
4328 }
4329
4330 // Parse the return register.
4331 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00004332 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004333 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4334 reportParseError("expected return register");
4335 return false;
4336 }
4337
4338 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4339 if (!ReturnRegOpnd.isGPRAsmReg()) {
4340 reportParseError(ReturnRegOpnd.getStartLoc(),
4341 "expected general purpose register");
4342 return false;
4343 }
4344
4345 // If this is not the end of the statement, report an error.
4346 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4347 reportParseError("unexpected token, expected end of statement");
4348 return false;
4349 }
4350
4351 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
4352 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00004353 return false;
4354 }
4355
Jack Carter07c818d2013-01-25 01:31:34 +00004356 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00004357 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00004358 }
4359
Daniel Sandersd97a6342014-08-13 10:07:34 +00004360 if (IDVal == ".mask" || IDVal == ".fmask") {
4361 // .mask bitmask, frame_offset
4362 // bitmask: One bit for each register used.
4363 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
4364 // first register is expected to be saved.
4365 // Examples:
4366 // .mask 0x80000000, -4
4367 // .fmask 0x80000000, -4
4368 //
Jack Carterbe332172012-09-07 00:48:02 +00004369
Daniel Sandersd97a6342014-08-13 10:07:34 +00004370 // Parse the bitmask
4371 const MCExpr *BitMask;
4372 int64_t BitMaskVal;
4373
4374 if (Parser.parseExpression(BitMask)) {
4375 reportParseError("expected bitmask value");
4376 return false;
4377 }
4378
4379 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
4380 reportParseError("bitmask not an absolute expression");
4381 return false;
4382 }
4383
4384 if (Parser.getTok().is(AsmToken::Comma))
4385 Parser.Lex();
4386 else {
4387 reportParseError("unexpected token, expected comma");
4388 return false;
4389 }
4390
4391 // Parse the frame_offset
4392 const MCExpr *FrameOffset;
4393 int64_t FrameOffsetVal;
4394
4395 if (Parser.parseExpression(FrameOffset)) {
4396 reportParseError("expected frame offset value");
4397 return false;
4398 }
4399
4400 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
4401 reportParseError("frame offset not an absolute expression");
4402 return false;
4403 }
4404
4405 // If this is not the end of the statement, report an error.
4406 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4407 reportParseError("unexpected token, expected end of statement");
4408 return false;
4409 }
4410
4411 if (IDVal == ".mask")
4412 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
4413 else
4414 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00004415 return false;
4416 }
4417
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004418 if (IDVal == ".nan")
4419 return parseDirectiveNaN();
4420
Jack Carter07c818d2013-01-25 01:31:34 +00004421 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004422 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00004423 return false;
4424 }
4425
Rafael Espindolab59fb732014-03-28 18:50:26 +00004426 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004427 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004428 return false;
4429 }
4430
Jack Carter07c818d2013-01-25 01:31:34 +00004431 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004432 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00004433 return false;
4434 }
4435
Jack Carter0cd3c192014-01-06 23:27:31 +00004436 if (IDVal == ".option")
4437 return parseDirectiveOption();
4438
4439 if (IDVal == ".abicalls") {
4440 getTargetStreamer().emitDirectiveAbiCalls();
4441 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004442 Error(Parser.getTok().getLoc(),
4443 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004444 // Clear line
4445 Parser.eatToEndOfStatement();
4446 }
4447 return false;
4448 }
4449
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004450 if (IDVal == ".cpsetup")
4451 return parseDirectiveCPSetup();
4452
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004453 if (IDVal == ".module")
4454 return parseDirectiveModule();
4455
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004456 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
4457 return parseInternalDirectiveReallowModule();
4458
Toma Tabacu9ca50962015-04-16 09:53:47 +00004459 if (IDVal == ".insn")
4460 return parseInsnDirective();
4461
Rafael Espindola870c4e92012-01-11 03:56:41 +00004462 return true;
4463}
4464
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004465bool MipsAsmParser::parseInternalDirectiveReallowModule() {
4466 // If this is not the end of the statement, report an error.
4467 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4468 reportParseError("unexpected token, expected end of statement");
4469 return false;
4470 }
4471
4472 getTargetStreamer().reallowModuleDirective();
4473
4474 getParser().Lex(); // Eat EndOfStatement token.
4475 return false;
4476}
4477
Rafael Espindola870c4e92012-01-11 03:56:41 +00004478extern "C" void LLVMInitializeMipsAsmParser() {
4479 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
4480 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
4481 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
4482 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
4483}
Jack Carterb4dbc172012-09-05 23:34:03 +00004484
4485#define GET_REGISTER_MATCHER
4486#define GET_MATCHER_IMPLEMENTATION
4487#include "MipsGenAsmMatcher.inc"