blob: 89742c0003800351e341c5901d68add45ecd5b6d [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Eric Christophera5762812015-01-26 17:33:46 +000010#include "MCTargetDesc/MipsABIInfo.h"
Petar Jovanovica5da5882014-02-04 18:41:57 +000011#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000012#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000013#include "MipsRegisterInfo.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000014#include "MipsTargetStreamer.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000015#include "llvm/ADT/APInt.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000016#include "llvm/ADT/SmallVector.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000017#include "llvm/ADT/StringSwitch.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000018#include "llvm/MC/MCContext.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000021#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000022#include "llvm/MC/MCParser/MCAsmLexer.h"
23#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000024#include "llvm/MC/MCStreamer.h"
25#include "llvm/MC/MCSubtargetInfo.h"
26#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000027#include "llvm/MC/MCTargetAsmParser.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000028#include "llvm/Support/Debug.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000029#include "llvm/Support/MathExtras.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000030#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000031#include "llvm/Support/TargetRegistry.h"
Benjamin Kramer799003b2015-03-23 19:32:43 +000032#include "llvm/Support/raw_ostream.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000033#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000034
35using namespace llvm;
36
Chandler Carruthe96dd892014-04-21 22:55:11 +000037#define DEBUG_TYPE "mips-asm-parser"
38
Joey Gouly0e76fa72013-09-12 10:28:05 +000039namespace llvm {
40class MCInstrInfo;
41}
42
Rafael Espindola870c4e92012-01-11 03:56:41 +000043namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000044class MipsAssemblerOptions {
45public:
Toma Tabacu9db22db2014-09-09 10:15:38 +000046 MipsAssemblerOptions(uint64_t Features_) :
47 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000048
Toma Tabacu9db22db2014-09-09 10:15:38 +000049 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000050 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000051 Reorder = Opts->isReorder();
52 Macro = Opts->isMacro();
53 Features = Opts->getFeatures();
54 }
55
Toma Tabacub19cf202015-04-27 13:12:59 +000056 unsigned getATRegIndex() const { return ATReg; }
57 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000058 if (Reg > 31)
59 return false;
60
61 ATReg = Reg;
62 return true;
63 }
Jack Carter0b744b32012-10-04 02:29:46 +000064
Toma Tabacu9db22db2014-09-09 10:15:38 +000065 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000066 void setReorder() { Reorder = true; }
67 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000068
Toma Tabacu9db22db2014-09-09 10:15:38 +000069 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000070 void setMacro() { Macro = true; }
71 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000072
Toma Tabacu9db22db2014-09-09 10:15:38 +000073 uint64_t getFeatures() const { return Features; }
74 void setFeatures(uint64_t Features_) { Features = Features_; }
75
Daniel Sandersf0df2212014-08-04 12:20:00 +000076 // Set of features that are either architecture features or referenced
77 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
78 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
79 // The reason we need this mask is explained in the selectArch function.
80 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kuperstein29704e72015-03-24 12:56:59 +000081 static const uint64_t AllArchRelatedMask =
82 Mips::FeatureMips1 | Mips::FeatureMips2 | Mips::FeatureMips3 |
83 Mips::FeatureMips3_32 | Mips::FeatureMips3_32r2 | Mips::FeatureMips4 |
84 Mips::FeatureMips4_32 | Mips::FeatureMips4_32r2 | Mips::FeatureMips5 |
85 Mips::FeatureMips5_32r2 | Mips::FeatureMips32 | Mips::FeatureMips32r2 |
86 Mips::FeatureMips32r3 | Mips::FeatureMips32r5 | Mips::FeatureMips32r6 |
87 Mips::FeatureMips64 | Mips::FeatureMips64r2 | Mips::FeatureMips64r3 |
88 Mips::FeatureMips64r5 | Mips::FeatureMips64r6 | Mips::FeatureCnMips |
89 Mips::FeatureFP64Bit | Mips::FeatureGP64Bit | Mips::FeatureNaN2008;
Daniel Sandersf0df2212014-08-04 12:20:00 +000090
Jack Carter0b744b32012-10-04 02:29:46 +000091private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000092 unsigned ATReg;
93 bool Reorder;
94 bool Macro;
Toma Tabacu9db22db2014-09-09 10:15:38 +000095 uint64_t Features;
Jack Carter0b744b32012-10-04 02:29:46 +000096};
97}
98
99namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +0000100class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000101 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000102 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000103 return static_cast<MipsTargetStreamer &>(TS);
104 }
105
Jack Carterb4dbc172012-09-05 23:34:03 +0000106 MCSubtargetInfo &STI;
Eric Christophera5762812015-01-26 17:33:46 +0000107 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000108 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000109 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
110 // nullptr, which indicates that no function is currently
111 // selected. This usually happens after an '.end func'
112 // directive.
Jack Carter0b744b32012-10-04 02:29:46 +0000113
Daniel Sandersef638fe2014-10-03 15:37:37 +0000114 // Print a warning along with its fix-it message at the given range.
115 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
116 SMRange Range, bool ShowColors = true);
117
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000118#define GET_ASSEMBLER_HEADER
119#include "MipsGenAsmMatcher.inc"
120
Matheus Almeida595fcab2014-06-11 15:05:56 +0000121 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
122
Chad Rosier49963552012-10-13 00:26:04 +0000123 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000124 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000125 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000126 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000127
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000128 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000129 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000130
Toma Tabacu13964452014-09-04 13:23:44 +0000131 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000132
Toma Tabacu13964452014-09-04 13:23:44 +0000133 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000134
David Blaikie960ea3f2014-06-08 16:18:35 +0000135 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
136 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000137
Craig Topper56c590a2014-04-29 07:58:02 +0000138 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000139
David Blaikie960ea3f2014-06-08 16:18:35 +0000140 MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000141
142 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000143 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000144 StringRef Identifier, SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000145
Jack Carter873c7242013-01-12 01:03:14 +0000146 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000147 matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
Jack Carter873c7242013-01-12 01:03:14 +0000148
Toma Tabacu13964452014-09-04 13:23:44 +0000149 MipsAsmParser::OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000150
Toma Tabacu13964452014-09-04 13:23:44 +0000151 MipsAsmParser::OperandMatchResultTy parseImm(OperandVector &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000152
Toma Tabacu13964452014-09-04 13:23:44 +0000153 MipsAsmParser::OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000154
David Blaikie960ea3f2014-06-08 16:18:35 +0000155 MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000156
Toma Tabacu13964452014-09-04 13:23:44 +0000157 MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000158
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000159 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000160 parseRegisterPair (OperandVector &Operands);
161
162 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +0000163 parseMovePRegPair(OperandVector &Operands);
164
165 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000166 parseRegisterList (OperandVector &Operands);
167
David Blaikie960ea3f2014-06-08 16:18:35 +0000168 bool searchSymbolAlias(OperandVector &Operands);
169
Toma Tabacu13964452014-09-04 13:23:44 +0000170 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000171
Jack Carter30a59822012-10-04 04:03:53 +0000172 bool needsExpansion(MCInst &Inst);
173
Matheus Almeida3813d572014-06-19 14:39:14 +0000174 // Expands assembly pseudo instructions.
175 // Returns false on success, true otherwise.
176 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000177 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000178
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000179 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
180 SmallVectorImpl<MCInst> &Instructions);
181
Matheus Almeida3813d572014-06-19 14:39:14 +0000182 bool expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000183 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000184
185 bool expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000186 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000187
188 bool expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000189 SmallVectorImpl<MCInst> &Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000190 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
191 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000192
Toma Tabacu0d64b202014-08-14 10:29:17 +0000193 void expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
194 SmallVectorImpl<MCInst> &Instructions);
195
Jack Carter9e65aa32013-03-22 00:05:30 +0000196 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000197 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
198 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000199
200 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
201 SmallVectorImpl<MCInst> &Instructions);
202
Toma Tabacu234482a2015-03-16 12:03:39 +0000203 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
204 SmallVectorImpl<MCInst> &Instructions);
205
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000206 bool reportParseError(Twine ErrorMsg);
207 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000208
Jack Carterb5cf5902013-04-17 00:18:04 +0000209 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000210 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000211
Vladimir Medic4c299852013-11-06 11:27:05 +0000212 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000213
214 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000215 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000216 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000217 bool parseSetFeature(uint64_t Feature);
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000218 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000219 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000220 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000221 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000222 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000223 bool parseInsnDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000224
225 bool parseSetAtDirective();
226 bool parseSetNoAtDirective();
227 bool parseSetMacroDirective();
228 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000229 bool parseSetMsaDirective();
230 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000231 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000232 bool parseSetReorderDirective();
233 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000234 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000235 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000236 bool parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000237 bool parseSetPopDirective();
238 bool parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000239
Jack Carterd76b2372013-03-21 21:44:16 +0000240 bool parseSetAssignment();
241
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000242 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000243 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000244 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000245 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000246 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000247 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
248 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000249
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000250 bool parseInternalDirectiveReallowModule();
251
Jack Carterdc1e35d2012-09-06 20:00:02 +0000252 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000253
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000254 bool eatComma(StringRef ErrorStr);
255
Jack Carter1ac53222013-02-20 23:11:17 +0000256 int matchCPURegisterName(StringRef Symbol);
257
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000258 int matchHWRegsRegisterName(StringRef Symbol);
259
Jack Carter873c7242013-01-12 01:03:14 +0000260 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000261
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000262 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000263
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000264 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000265
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000266 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000267
Jack Carter5dc8ac92013-09-25 23:50:44 +0000268 int matchMSA128RegisterName(StringRef Name);
269
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000270 int matchMSA128CtrlRegisterName(StringRef Name);
271
Jack Carterd0bd6422013-04-18 00:41:53 +0000272 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000273
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000274 unsigned getGPR(int RegNo);
275
Toma Tabacu89a712b2015-04-15 10:48:56 +0000276 /// Returns the internal register number for the current AT. Also checks if
277 /// the current AT is unavailable (set to $0) and gives an error if it is.
278 /// This should be used in pseudo-instruction expansions which need AT.
279 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000280
281 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000282 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000283
284 // Helper function that checks if the value of a vector index is within the
285 // boundaries of accepted values for each RegisterKind
286 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
287 bool validateMSAIndex(int Val, int RegKind);
288
Daniel Sandersf0df2212014-08-04 12:20:00 +0000289 // Selects a new architecture by updating the FeatureBits with the necessary
290 // info including implied dependencies.
291 // Internally, it clears all the feature bits related to *any* architecture
292 // and selects the new one using the ToggleFeature functionality of the
293 // MCSubtargetInfo object that handles implied dependencies. The reason we
294 // clear all the arch related bits manually is because ToggleFeature only
295 // clears the features that imply the feature being cleared and not the
296 // features implied by the feature being cleared. This is easier to see
297 // with an example:
298 // --------------------------------------------------
299 // | Feature | Implies |
300 // | -------------------------------------------------|
301 // | FeatureMips1 | None |
302 // | FeatureMips2 | FeatureMips1 |
303 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
304 // | FeatureMips4 | FeatureMips3 |
305 // | ... | |
306 // --------------------------------------------------
307 //
308 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
309 // FeatureMipsGP64 | FeatureMips1)
310 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
311 void selectArch(StringRef ArchFeature) {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000312 uint64_t FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000313 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
314 STI.setFeatureBits(FeatureBits);
315 setAvailableFeatures(
316 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000317 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000318 }
319
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000320 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000321 if (!(STI.getFeatureBits() & Feature)) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000322 setAvailableFeatures(
323 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000324 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000325 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000326 }
327
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000328 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000329 if (STI.getFeatureBits() & Feature) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000330 setAvailableFeatures(
331 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000332 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000333 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000334 }
335
Rafael Espindola870c4e92012-01-11 03:56:41 +0000336public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000337 enum MipsMatchResultTy {
338 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
339#define GET_OPERAND_DIAGNOSTIC_TYPES
340#include "MipsGenAsmMatcher.inc"
341#undef GET_OPERAND_DIAGNOSTIC_TYPES
342
343 };
344
Joey Gouly0e76fa72013-09-12 10:28:05 +0000345 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000346 const MCInstrInfo &MII, const MCTargetOptions &Options)
Eric Christophera5762812015-01-26 17:33:46 +0000347 : MCTargetAsmParser(), STI(sti),
348 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
349 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000350 MCAsmParserExtension::Initialize(parser);
351
Toma Tabacu11e14a92015-04-21 11:50:52 +0000352 parser.addAliasForDirective(".asciiz", ".asciz");
353
Jack Carterb4dbc172012-09-05 23:34:03 +0000354 // Initialize the set of available features.
355 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000356
357 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000358 AssemblerOptions.push_back(
359 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000360
361 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000362 AssemblerOptions.push_back(
363 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000364
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000365 getTargetStreamer().updateABIInfo(*this);
366
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000367 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000368 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000369
370 CurrentFn = nullptr;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000371 }
372
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000373 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
374 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
375
Michael Kuperstein29704e72015-03-24 12:56:59 +0000376 bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; }
377 bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; }
Eric Christophera5762812015-01-26 17:33:46 +0000378 const MipsABIInfo &getABI() const { return ABI; }
379 bool isABI_N32() const { return ABI.IsN32(); }
380 bool isABI_N64() const { return ABI.IsN64(); }
381 bool isABI_O32() const { return ABI.IsO32(); }
Michael Kuperstein29704e72015-03-24 12:56:59 +0000382 bool isABI_FPXX() const { return STI.getFeatureBits() & Mips::FeatureFPXX; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000383
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000384 bool useOddSPReg() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000385 return !(STI.getFeatureBits() & Mips::FeatureNoOddSPReg);
Daniel Sanders7e527422014-07-10 13:38:23 +0000386 }
387
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000388 bool inMicroMipsMode() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000389 return STI.getFeatureBits() & Mips::FeatureMicroMips;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000390 }
Michael Kuperstein29704e72015-03-24 12:56:59 +0000391 bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; }
392 bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; }
393 bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; }
394 bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
395 bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000396 bool hasMips32() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000397 return (STI.getFeatureBits() & Mips::FeatureMips32);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000398 }
399 bool hasMips64() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000400 return (STI.getFeatureBits() & Mips::FeatureMips64);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000401 }
402 bool hasMips32r2() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000403 return (STI.getFeatureBits() & Mips::FeatureMips32r2);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000404 }
405 bool hasMips64r2() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000406 return (STI.getFeatureBits() & Mips::FeatureMips64r2);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000407 }
Daniel Sanders17793142015-02-18 16:24:50 +0000408 bool hasMips32r3() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000409 return (STI.getFeatureBits() & Mips::FeatureMips32r3);
Daniel Sanders17793142015-02-18 16:24:50 +0000410 }
411 bool hasMips64r3() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000412 return (STI.getFeatureBits() & Mips::FeatureMips64r3);
Daniel Sanders17793142015-02-18 16:24:50 +0000413 }
414 bool hasMips32r5() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000415 return (STI.getFeatureBits() & Mips::FeatureMips32r5);
Daniel Sanders17793142015-02-18 16:24:50 +0000416 }
417 bool hasMips64r5() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000418 return (STI.getFeatureBits() & Mips::FeatureMips64r5);
Daniel Sanders17793142015-02-18 16:24:50 +0000419 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000420 bool hasMips32r6() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000421 return (STI.getFeatureBits() & Mips::FeatureMips32r6);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000422 }
423 bool hasMips64r6() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000424 return (STI.getFeatureBits() & Mips::FeatureMips64r6);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000425 }
Kai Nackee0245392015-01-27 19:11:28 +0000426 bool hasCnMips() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000427 return (STI.getFeatureBits() & Mips::FeatureCnMips);
Kai Nackee0245392015-01-27 19:11:28 +0000428 }
Michael Kuperstein29704e72015-03-24 12:56:59 +0000429 bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
430 bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
431 bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000432
433 bool inMips16Mode() const {
Michael Kuperstein29704e72015-03-24 12:56:59 +0000434 return STI.getFeatureBits() & Mips::FeatureMips16;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000435 }
436 // TODO: see how can we get this info.
Eric Christopher7394e232014-07-18 00:08:50 +0000437 bool abiUsesSoftFloat() const { return false; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000438
Toma Tabacud9d344b2015-04-27 14:05:04 +0000439 /// Warn if RegIndex is the same as the current AT.
440 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000441};
442}
443
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000444namespace {
445
446/// MipsOperand - Instances of this class represent a parsed Mips machine
447/// instruction.
448class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000449public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000450 /// Broad categories of register classes
451 /// The exact class is finalized by the render method.
452 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000453 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000454 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000455 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000456 RegKind_FCC = 4, /// FCC
457 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
458 RegKind_MSACtrl = 16, /// MSA control registers
459 RegKind_COP2 = 32, /// COP2
460 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
461 /// context).
462 RegKind_CCR = 128, /// CCR
463 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000464 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000465
466 /// Potentially any (e.g. $1)
467 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
468 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000469 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000470 };
471
472private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000473 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000474 k_Immediate, /// An immediate (possibly involving symbol references)
475 k_Memory, /// Base + Offset Memory Address
476 k_PhysRegister, /// A physical register from the Mips namespace
477 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000478 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000479 k_RegList, /// A physical register list
480 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000481 } Kind;
482
David Blaikie960ea3f2014-06-08 16:18:35 +0000483public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000484 MipsOperand(KindTy K, MipsAsmParser &Parser)
485 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
486
David Blaikie960ea3f2014-06-08 16:18:35 +0000487private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000488 /// For diagnostics, and checking the assembler temporary
489 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000490
Eric Christopher8996c5d2013-03-15 00:42:55 +0000491 struct Token {
492 const char *Data;
493 unsigned Length;
494 };
495
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000496 struct PhysRegOp {
497 unsigned Num; /// Register Number
498 };
499
500 struct RegIdxOp {
501 unsigned Index; /// Index into the register class
502 RegKind Kind; /// Bitfield of the kinds it could possibly be
503 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000504 };
505
506 struct ImmOp {
507 const MCExpr *Val;
508 };
509
510 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000511 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000512 const MCExpr *Off;
513 };
514
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000515 struct RegListOp {
516 SmallVector<unsigned, 10> *List;
517 };
518
Jack Carterb4dbc172012-09-05 23:34:03 +0000519 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000520 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000521 struct PhysRegOp PhysReg;
522 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000523 struct ImmOp Imm;
524 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000525 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000526 };
527
528 SMLoc StartLoc, EndLoc;
529
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000530 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000531 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
532 const MCRegisterInfo *RegInfo,
533 SMLoc S, SMLoc E,
534 MipsAsmParser &Parser) {
535 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000536 Op->RegIdx.Index = Index;
537 Op->RegIdx.RegInfo = RegInfo;
538 Op->RegIdx.Kind = RegKind;
539 Op->StartLoc = S;
540 Op->EndLoc = E;
541 return Op;
542 }
543
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000544public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000545 /// Coerce the register to GPR32 and return the real register for the current
546 /// target.
547 unsigned getGPR32Reg() const {
548 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000549 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000550 unsigned ClassID = Mips::GPR32RegClassID;
551 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000552 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000553
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000554 /// Coerce the register to GPR32 and return the real register for the current
555 /// target.
556 unsigned getGPRMM16Reg() const {
557 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
558 unsigned ClassID = Mips::GPR32RegClassID;
559 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
560 }
561
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000562 /// Coerce the register to GPR64 and return the real register for the current
563 /// target.
564 unsigned getGPR64Reg() const {
565 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
566 unsigned ClassID = Mips::GPR64RegClassID;
567 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000568 }
569
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000570private:
571 /// Coerce the register to AFGR64 and return the real register for the current
572 /// target.
573 unsigned getAFGR64Reg() const {
574 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
575 if (RegIdx.Index % 2 != 0)
576 AsmParser.Warning(StartLoc, "Float register should be even.");
577 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
578 .getRegister(RegIdx.Index / 2);
579 }
580
581 /// Coerce the register to FGR64 and return the real register for the current
582 /// target.
583 unsigned getFGR64Reg() const {
584 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
585 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
586 .getRegister(RegIdx.Index);
587 }
588
589 /// Coerce the register to FGR32 and return the real register for the current
590 /// target.
591 unsigned getFGR32Reg() const {
592 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
593 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
594 .getRegister(RegIdx.Index);
595 }
596
597 /// Coerce the register to FGRH32 and return the real register for the current
598 /// target.
599 unsigned getFGRH32Reg() const {
600 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
601 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
602 .getRegister(RegIdx.Index);
603 }
604
605 /// Coerce the register to FCC and return the real register for the current
606 /// target.
607 unsigned getFCCReg() const {
608 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
609 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
610 .getRegister(RegIdx.Index);
611 }
612
613 /// Coerce the register to MSA128 and return the real register for the current
614 /// target.
615 unsigned getMSA128Reg() const {
616 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
617 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
618 // identical
619 unsigned ClassID = Mips::MSA128BRegClassID;
620 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
621 }
622
623 /// Coerce the register to MSACtrl and return the real register for the
624 /// current target.
625 unsigned getMSACtrlReg() const {
626 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
627 unsigned ClassID = Mips::MSACtrlRegClassID;
628 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
629 }
630
631 /// Coerce the register to COP2 and return the real register for the
632 /// current target.
633 unsigned getCOP2Reg() const {
634 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
635 unsigned ClassID = Mips::COP2RegClassID;
636 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
637 }
638
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000639 /// Coerce the register to COP3 and return the real register for the
640 /// current target.
641 unsigned getCOP3Reg() const {
642 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
643 unsigned ClassID = Mips::COP3RegClassID;
644 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
645 }
646
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000647 /// Coerce the register to ACC64DSP and return the real register for the
648 /// current target.
649 unsigned getACC64DSPReg() const {
650 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
651 unsigned ClassID = Mips::ACC64DSPRegClassID;
652 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
653 }
654
655 /// Coerce the register to HI32DSP and return the real register for the
656 /// current target.
657 unsigned getHI32DSPReg() const {
658 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
659 unsigned ClassID = Mips::HI32DSPRegClassID;
660 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
661 }
662
663 /// Coerce the register to LO32DSP and return the real register for the
664 /// current target.
665 unsigned getLO32DSPReg() const {
666 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
667 unsigned ClassID = Mips::LO32DSPRegClassID;
668 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
669 }
670
671 /// Coerce the register to CCR and return the real register for the
672 /// current target.
673 unsigned getCCRReg() const {
674 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
675 unsigned ClassID = Mips::CCRRegClassID;
676 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
677 }
678
679 /// Coerce the register to HWRegs and return the real register for the
680 /// current target.
681 unsigned getHWRegsReg() const {
682 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
683 unsigned ClassID = Mips::HWRegsRegClassID;
684 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
685 }
686
687public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000688 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000689 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000690 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000691 Inst.addOperand(MCOperand::CreateImm(0));
692 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
693 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
694 else
695 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000696 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000697
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000698 void addRegOperands(MCInst &Inst, unsigned N) const {
699 llvm_unreachable("Use a custom parser instead");
700 }
701
Daniel Sanders21bce302014-04-01 12:35:23 +0000702 /// Render the operand to an MCInst as a GPR32
703 /// Asserts if the wrong number of operands are requested, or the operand
704 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000705 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
706 assert(N == 1 && "Invalid number of operands!");
707 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
708 }
709
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000710 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
711 assert(N == 1 && "Invalid number of operands!");
712 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
713 }
714
Jozef Kolek1904fa22014-11-24 14:25:53 +0000715 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
716 assert(N == 1 && "Invalid number of operands!");
717 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
718 }
719
Zoran Jovanovic41688672015-02-10 16:36:20 +0000720 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
721 assert(N == 1 && "Invalid number of operands!");
722 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
723 }
724
Daniel Sanders21bce302014-04-01 12:35:23 +0000725 /// Render the operand to an MCInst as a GPR64
726 /// Asserts if the wrong number of operands are requested, or the operand
727 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000728 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
729 assert(N == 1 && "Invalid number of operands!");
730 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
731 }
732
733 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
734 assert(N == 1 && "Invalid number of operands!");
735 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
736 }
737
738 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
739 assert(N == 1 && "Invalid number of operands!");
740 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
741 }
742
743 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
744 assert(N == 1 && "Invalid number of operands!");
745 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000746 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000747 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000748 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
749 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000750 }
751
752 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
753 assert(N == 1 && "Invalid number of operands!");
754 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
755 }
756
757 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
758 assert(N == 1 && "Invalid number of operands!");
759 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
760 }
761
762 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
763 assert(N == 1 && "Invalid number of operands!");
764 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
765 }
766
767 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
768 assert(N == 1 && "Invalid number of operands!");
769 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
770 }
771
772 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
773 assert(N == 1 && "Invalid number of operands!");
774 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
775 }
776
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000777 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
778 assert(N == 1 && "Invalid number of operands!");
779 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
780 }
781
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000782 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
783 assert(N == 1 && "Invalid number of operands!");
784 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
785 }
786
787 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
788 assert(N == 1 && "Invalid number of operands!");
789 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
790 }
791
792 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
793 assert(N == 1 && "Invalid number of operands!");
794 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
795 }
796
797 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
798 assert(N == 1 && "Invalid number of operands!");
799 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
800 }
801
802 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
803 assert(N == 1 && "Invalid number of operands!");
804 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
805 }
806
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000807 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000808 assert(N == 1 && "Invalid number of operands!");
809 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000810 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000811 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000812
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000813 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000814 assert(N == 2 && "Invalid number of operands!");
815
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000816 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000817
818 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000819 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000820 }
821
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000822 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
823 assert(N == 2 && "Invalid number of operands!");
824
825 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPRMM16Reg()));
826
827 const MCExpr *Expr = getMemOff();
828 addExpr(Inst, Expr);
829 }
830
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000831 void addRegListOperands(MCInst &Inst, unsigned N) const {
832 assert(N == 1 && "Invalid number of operands!");
833
834 for (auto RegNo : getRegList())
835 Inst.addOperand(MCOperand::CreateReg(RegNo));
836 }
837
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000838 void addRegPairOperands(MCInst &Inst, unsigned N) const {
839 assert(N == 2 && "Invalid number of operands!");
840 unsigned RegNo = getRegPair();
841 Inst.addOperand(MCOperand::CreateReg(RegNo++));
842 Inst.addOperand(MCOperand::CreateReg(RegNo));
843 }
844
Zoran Jovanovic41688672015-02-10 16:36:20 +0000845 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
846 assert(N == 2 && "Invalid number of operands!");
847 for (auto RegNo : getRegList())
848 Inst.addOperand(MCOperand::CreateReg(RegNo));
849 }
850
Craig Topper56c590a2014-04-29 07:58:02 +0000851 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000852 // As a special case until we sort out the definition of div/divu, pretend
853 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
854 if (isGPRAsmReg() && RegIdx.Index == 0)
855 return true;
856
857 return Kind == k_PhysRegister;
858 }
859 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000860 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000861 bool isConstantImm() const {
862 return isImm() && dyn_cast<MCConstantExpr>(getImm());
863 }
Craig Topper56c590a2014-04-29 07:58:02 +0000864 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000865 // Note: It's not possible to pretend that other operand kinds are tokens.
866 // The matcher emitter checks tokens first.
867 return Kind == k_Token;
868 }
Craig Topper56c590a2014-04-29 07:58:02 +0000869 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000870 bool isConstantMemOff() const {
871 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
872 }
873 template <unsigned Bits> bool isMemWithSimmOffset() const {
874 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
875 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000876 bool isMemWithGRPMM16Base() const {
877 return isMem() && getMemBase()->isMM16AsmReg();
878 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000879 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
880 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
881 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
882 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000883 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
884 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
885 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
886 && (getMemBase()->getGPR32Reg() == Mips::SP);
887 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000888 bool isRegList16() const {
889 if (!isRegList())
890 return false;
891
892 int Size = RegList.List->size();
893 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
894 RegList.List->back() != Mips::RA)
895 return false;
896
897 int PrevReg = *RegList.List->begin();
898 for (int i = 1; i < Size - 1; i++) {
899 int Reg = (*(RegList.List))[i];
900 if ( Reg != PrevReg + 1)
901 return false;
902 PrevReg = Reg;
903 }
904
905 return true;
906 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000907 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000908 bool isLSAImm() const {
909 if (!isConstantImm())
910 return false;
911 int64_t Val = getConstantImm();
912 return 1 <= Val && Val <= 4;
913 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000914 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +0000915 bool isMovePRegPair() const {
916 if (Kind != k_RegList || RegList.List->size() != 2)
917 return false;
918
919 unsigned R0 = RegList.List->front();
920 unsigned R1 = RegList.List->back();
921
922 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
923 (R0 == Mips::A1 && R1 == Mips::A3) ||
924 (R0 == Mips::A2 && R1 == Mips::A3) ||
925 (R0 == Mips::A0 && R1 == Mips::S5) ||
926 (R0 == Mips::A0 && R1 == Mips::S6) ||
927 (R0 == Mips::A0 && R1 == Mips::A1) ||
928 (R0 == Mips::A0 && R1 == Mips::A2) ||
929 (R0 == Mips::A0 && R1 == Mips::A3))
930 return true;
931
932 return false;
933 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000934
935 StringRef getToken() const {
936 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000937 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000938 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000939 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000940
Craig Topper56c590a2014-04-29 07:58:02 +0000941 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000942 // As a special case until we sort out the definition of div/divu, pretend
943 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
944 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
945 RegIdx.Kind & RegKind_GPR)
946 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000947
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000948 assert(Kind == k_PhysRegister && "Invalid access!");
949 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000950 }
951
Jack Carterb4dbc172012-09-05 23:34:03 +0000952 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000953 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000954 return Imm.Val;
955 }
956
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000957 int64_t getConstantImm() const {
958 const MCExpr *Val = getImm();
959 return static_cast<const MCConstantExpr *>(Val)->getValue();
960 }
961
962 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000963 assert((Kind == k_Memory) && "Invalid access!");
964 return Mem.Base;
965 }
966
967 const MCExpr *getMemOff() const {
968 assert((Kind == k_Memory) && "Invalid access!");
969 return Mem.Off;
970 }
971
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000972 int64_t getConstantMemOff() const {
973 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
974 }
975
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000976 const SmallVectorImpl<unsigned> &getRegList() const {
977 assert((Kind == k_RegList) && "Invalid access!");
978 return *(RegList.List);
979 }
980
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000981 unsigned getRegPair() const {
982 assert((Kind == k_RegPair) && "Invalid access!");
983 return RegIdx.Index;
984 }
985
David Blaikie960ea3f2014-06-08 16:18:35 +0000986 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
987 MipsAsmParser &Parser) {
988 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000989 Op->Tok.Data = Str.data();
990 Op->Tok.Length = Str.size();
991 Op->StartLoc = S;
992 Op->EndLoc = S;
993 return Op;
994 }
995
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000996 /// Create a numeric register (e.g. $1). The exact register remains
997 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +0000998 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000999 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001000 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001001 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001002 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001003 }
1004
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001005 /// Create a register that is definitely a GPR.
1006 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001007 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001008 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001009 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001010 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001011 }
1012
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001013 /// Create a register that is definitely a FGR.
1014 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001015 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001016 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001017 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001018 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1019 }
1020
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001021 /// Create a register that is definitely a HWReg.
1022 /// This is typically only used for named registers such as $hwr_cpunum.
1023 static std::unique_ptr<MipsOperand>
1024 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1025 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1026 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1027 }
1028
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001029 /// Create a register that is definitely an FCC.
1030 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001031 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001032 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001033 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001034 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1035 }
1036
1037 /// Create a register that is definitely an ACC.
1038 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001039 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001040 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001041 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001042 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1043 }
1044
1045 /// Create a register that is definitely an MSA128.
1046 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001047 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001048 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001049 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001050 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1051 }
1052
1053 /// Create a register that is definitely an MSACtrl.
1054 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001055 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001056 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001057 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001058 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1059 }
1060
David Blaikie960ea3f2014-06-08 16:18:35 +00001061 static std::unique_ptr<MipsOperand>
1062 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1063 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001064 Op->Imm.Val = Val;
1065 Op->StartLoc = S;
1066 Op->EndLoc = E;
1067 return Op;
1068 }
1069
David Blaikie960ea3f2014-06-08 16:18:35 +00001070 static std::unique_ptr<MipsOperand>
1071 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1072 SMLoc E, MipsAsmParser &Parser) {
1073 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1074 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001075 Op->Mem.Off = Off;
1076 Op->StartLoc = S;
1077 Op->EndLoc = E;
1078 return Op;
1079 }
1080
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001081 static std::unique_ptr<MipsOperand>
1082 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1083 MipsAsmParser &Parser) {
1084 assert (Regs.size() > 0 && "Empty list not allowed");
1085
1086 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001087 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001088 Op->StartLoc = StartLoc;
1089 Op->EndLoc = EndLoc;
1090 return Op;
1091 }
1092
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001093 static std::unique_ptr<MipsOperand>
1094 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1095 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1096 Op->RegIdx.Index = RegNo;
1097 Op->StartLoc = S;
1098 Op->EndLoc = E;
1099 return Op;
1100 }
1101
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001102 bool isGPRAsmReg() const {
1103 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001104 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001105 bool isMM16AsmReg() const {
1106 if (!(isRegIdx() && RegIdx.Kind))
1107 return false;
1108 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1109 || RegIdx.Index == 16 || RegIdx.Index == 17);
1110 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001111 bool isMM16AsmRegZero() const {
1112 if (!(isRegIdx() && RegIdx.Kind))
1113 return false;
1114 return (RegIdx.Index == 0 ||
1115 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1116 RegIdx.Index == 17);
1117 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001118 bool isMM16AsmRegMoveP() const {
1119 if (!(isRegIdx() && RegIdx.Kind))
1120 return false;
1121 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1122 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1123 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001124 bool isFGRAsmReg() const {
1125 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1126 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001127 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001128 bool isHWRegsAsmReg() const {
1129 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001130 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001131 bool isCCRAsmReg() const {
1132 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001133 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001134 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001135 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1136 return false;
1137 if (!AsmParser.hasEightFccRegisters())
1138 return RegIdx.Index == 0;
1139 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001140 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001141 bool isACCAsmReg() const {
1142 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001143 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001144 bool isCOP2AsmReg() const {
1145 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001146 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001147 bool isCOP3AsmReg() const {
1148 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1149 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001150 bool isMSA128AsmReg() const {
1151 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001152 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001153 bool isMSACtrlAsmReg() const {
1154 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001155 }
1156
Jack Carterb4dbc172012-09-05 23:34:03 +00001157 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001158 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001159 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001160 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001161
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001162 virtual ~MipsOperand() {
1163 switch (Kind) {
1164 case k_Immediate:
1165 break;
1166 case k_Memory:
1167 delete Mem.Base;
1168 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001169 case k_RegList:
1170 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001171 case k_PhysRegister:
1172 case k_RegisterIndex:
1173 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001174 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001175 break;
1176 }
1177 }
1178
Craig Topper56c590a2014-04-29 07:58:02 +00001179 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001180 switch (Kind) {
1181 case k_Immediate:
1182 OS << "Imm<";
1183 Imm.Val->print(OS);
1184 OS << ">";
1185 break;
1186 case k_Memory:
1187 OS << "Mem<";
1188 Mem.Base->print(OS);
1189 OS << ", ";
1190 Mem.Off->print(OS);
1191 OS << ">";
1192 break;
1193 case k_PhysRegister:
1194 OS << "PhysReg<" << PhysReg.Num << ">";
1195 break;
1196 case k_RegisterIndex:
1197 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1198 break;
1199 case k_Token:
1200 OS << Tok.Data;
1201 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001202 case k_RegList:
1203 OS << "RegList< ";
1204 for (auto Reg : (*RegList.List))
1205 OS << Reg << " ";
1206 OS << ">";
1207 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001208 case k_RegPair:
1209 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1210 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001211 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001212 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001213}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001214} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001215
Jack Carter9e65aa32013-03-22 00:05:30 +00001216namespace llvm {
1217extern const MCInstrDesc MipsInsts[];
1218}
1219static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1220 return MipsInsts[Opcode];
1221}
1222
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001223static bool hasShortDelaySlot(unsigned Opcode) {
1224 switch (Opcode) {
1225 case Mips::JALS_MM:
1226 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001227 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001228 case Mips::BGEZALS_MM:
1229 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001230 return true;
1231 default:
1232 return false;
1233 }
1234}
1235
Jack Carter9e65aa32013-03-22 00:05:30 +00001236bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001237 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001238 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001239
Jack Carter9e65aa32013-03-22 00:05:30 +00001240 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001241
1242 if (MCID.isBranch() || MCID.isCall()) {
1243 const unsigned Opcode = Inst.getOpcode();
1244 MCOperand Offset;
1245
1246 switch (Opcode) {
1247 default:
1248 break;
Kai Nackee0245392015-01-27 19:11:28 +00001249 case Mips::BBIT0:
1250 case Mips::BBIT032:
1251 case Mips::BBIT1:
1252 case Mips::BBIT132:
1253 assert(hasCnMips() && "instruction only valid for octeon cpus");
1254 // Fall through
1255
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001256 case Mips::BEQ:
1257 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001258 case Mips::BEQ_MM:
1259 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001260 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001261 Offset = Inst.getOperand(2);
1262 if (!Offset.isImm())
1263 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001264 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001265 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001266 if (OffsetToAlignment(Offset.getImm(),
1267 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001268 return Error(IDLoc, "branch to misaligned address");
1269 break;
1270 case Mips::BGEZ:
1271 case Mips::BGTZ:
1272 case Mips::BLEZ:
1273 case Mips::BLTZ:
1274 case Mips::BGEZAL:
1275 case Mips::BLTZAL:
1276 case Mips::BC1F:
1277 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001278 case Mips::BGEZ_MM:
1279 case Mips::BGTZ_MM:
1280 case Mips::BLEZ_MM:
1281 case Mips::BLTZ_MM:
1282 case Mips::BGEZAL_MM:
1283 case Mips::BLTZAL_MM:
1284 case Mips::BC1F_MM:
1285 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001286 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001287 Offset = Inst.getOperand(1);
1288 if (!Offset.isImm())
1289 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001290 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001291 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001292 if (OffsetToAlignment(Offset.getImm(),
1293 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001294 return Error(IDLoc, "branch to misaligned address");
1295 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001296 case Mips::BEQZ16_MM:
1297 case Mips::BNEZ16_MM:
1298 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1299 Offset = Inst.getOperand(1);
1300 if (!Offset.isImm())
1301 break; // We'll deal with this situation later on when applying fixups.
1302 if (!isIntN(8, Offset.getImm()))
1303 return Error(IDLoc, "branch target out of range");
1304 if (OffsetToAlignment(Offset.getImm(), 2LL))
1305 return Error(IDLoc, "branch to misaligned address");
1306 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001307 }
1308 }
1309
Daniel Sandersa84989a2014-06-16 13:25:35 +00001310 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1311 // We still accept it but it is a normal nop.
1312 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1313 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1314 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1315 "nop instruction");
1316 }
1317
Kai Nackee0245392015-01-27 19:11:28 +00001318 if (hasCnMips()) {
1319 const unsigned Opcode = Inst.getOpcode();
1320 MCOperand Opnd;
1321 int Imm;
1322
1323 switch (Opcode) {
1324 default:
1325 break;
1326
1327 case Mips::BBIT0:
1328 case Mips::BBIT032:
1329 case Mips::BBIT1:
1330 case Mips::BBIT132:
1331 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1332 // The offset is handled above
1333 Opnd = Inst.getOperand(1);
1334 if (!Opnd.isImm())
1335 return Error(IDLoc, "expected immediate operand kind");
1336 Imm = Opnd.getImm();
1337 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1338 Opcode == Mips::BBIT1 ? 63 : 31))
1339 return Error(IDLoc, "immediate operand value out of range");
1340 if (Imm > 31) {
1341 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1342 : Mips::BBIT132);
1343 Inst.getOperand(1).setImm(Imm - 32);
1344 }
1345 break;
1346
1347 case Mips::CINS:
1348 case Mips::CINS32:
1349 case Mips::EXTS:
1350 case Mips::EXTS32:
1351 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1352 // Check length
1353 Opnd = Inst.getOperand(3);
1354 if (!Opnd.isImm())
1355 return Error(IDLoc, "expected immediate operand kind");
1356 Imm = Opnd.getImm();
1357 if (Imm < 0 || Imm > 31)
1358 return Error(IDLoc, "immediate operand value out of range");
1359 // Check position
1360 Opnd = Inst.getOperand(2);
1361 if (!Opnd.isImm())
1362 return Error(IDLoc, "expected immediate operand kind");
1363 Imm = Opnd.getImm();
1364 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1365 Opcode == Mips::EXTS ? 63 : 31))
1366 return Error(IDLoc, "immediate operand value out of range");
1367 if (Imm > 31) {
1368 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1369 Inst.getOperand(2).setImm(Imm - 32);
1370 }
1371 break;
1372
1373 case Mips::SEQi:
1374 case Mips::SNEi:
1375 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1376 Opnd = Inst.getOperand(2);
1377 if (!Opnd.isImm())
1378 return Error(IDLoc, "expected immediate operand kind");
1379 Imm = Opnd.getImm();
1380 if (!isInt<10>(Imm))
1381 return Error(IDLoc, "immediate operand value out of range");
1382 break;
1383 }
1384 }
1385
Jack Carter9e65aa32013-03-22 00:05:30 +00001386 if (MCID.mayLoad() || MCID.mayStore()) {
1387 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001388 // reference or immediate we may have to expand instructions.
1389 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001390 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001391 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1392 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001393 MCOperand &Op = Inst.getOperand(i);
1394 if (Op.isImm()) {
1395 int MemOffset = Op.getImm();
1396 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001397 // Offset can't exceed 16bit value.
1398 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001399 return false;
1400 }
1401 } else if (Op.isExpr()) {
1402 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001403 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001404 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001405 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001406 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001407 // Expand symbol.
1408 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001409 return false;
1410 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001411 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001412 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001413 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001414 }
1415 }
1416 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001417 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001418 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001419
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001420 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001421 if (MCID.mayLoad()) {
1422 // Try to create 16-bit GP relative load instruction.
1423 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1424 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1425 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1426 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1427 MCOperand &Op = Inst.getOperand(i);
1428 if (Op.isImm()) {
1429 int MemOffset = Op.getImm();
1430 MCOperand &DstReg = Inst.getOperand(0);
1431 MCOperand &BaseReg = Inst.getOperand(1);
1432 if (isIntN(9, MemOffset) && (MemOffset % 4 == 0) &&
1433 getContext().getRegisterInfo()->getRegClass(
1434 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
1435 BaseReg.getReg() == Mips::GP) {
1436 MCInst TmpInst;
1437 TmpInst.setLoc(IDLoc);
1438 TmpInst.setOpcode(Mips::LWGP_MM);
1439 TmpInst.addOperand(MCOperand::CreateReg(DstReg.getReg()));
1440 TmpInst.addOperand(MCOperand::CreateReg(Mips::GP));
1441 TmpInst.addOperand(MCOperand::CreateImm(MemOffset));
1442 Instructions.push_back(TmpInst);
1443 return false;
1444 }
1445 }
1446 }
1447 } // for
1448 } // if load
1449
1450 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1451
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001452 MCOperand Opnd;
1453 int Imm;
1454
1455 switch (Inst.getOpcode()) {
1456 default:
1457 break;
1458 case Mips::ADDIUS5_MM:
1459 Opnd = Inst.getOperand(2);
1460 if (!Opnd.isImm())
1461 return Error(IDLoc, "expected immediate operand kind");
1462 Imm = Opnd.getImm();
1463 if (Imm < -8 || Imm > 7)
1464 return Error(IDLoc, "immediate operand value out of range");
1465 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001466 case Mips::ADDIUSP_MM:
1467 Opnd = Inst.getOperand(0);
1468 if (!Opnd.isImm())
1469 return Error(IDLoc, "expected immediate operand kind");
1470 Imm = Opnd.getImm();
1471 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1472 Imm % 4 != 0)
1473 return Error(IDLoc, "immediate operand value out of range");
1474 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001475 case Mips::SLL16_MM:
1476 case Mips::SRL16_MM:
1477 Opnd = Inst.getOperand(2);
1478 if (!Opnd.isImm())
1479 return Error(IDLoc, "expected immediate operand kind");
1480 Imm = Opnd.getImm();
1481 if (Imm < 1 || Imm > 8)
1482 return Error(IDLoc, "immediate operand value out of range");
1483 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001484 case Mips::LI16_MM:
1485 Opnd = Inst.getOperand(1);
1486 if (!Opnd.isImm())
1487 return Error(IDLoc, "expected immediate operand kind");
1488 Imm = Opnd.getImm();
1489 if (Imm < -1 || Imm > 126)
1490 return Error(IDLoc, "immediate operand value out of range");
1491 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001492 case Mips::ADDIUR2_MM:
1493 Opnd = Inst.getOperand(2);
1494 if (!Opnd.isImm())
1495 return Error(IDLoc, "expected immediate operand kind");
1496 Imm = Opnd.getImm();
1497 if (!(Imm == 1 || Imm == -1 ||
1498 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1499 return Error(IDLoc, "immediate operand value out of range");
1500 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001501 case Mips::ADDIUR1SP_MM:
1502 Opnd = Inst.getOperand(1);
1503 if (!Opnd.isImm())
1504 return Error(IDLoc, "expected immediate operand kind");
1505 Imm = Opnd.getImm();
1506 if (OffsetToAlignment(Imm, 4LL))
1507 return Error(IDLoc, "misaligned immediate operand value");
1508 if (Imm < 0 || Imm > 255)
1509 return Error(IDLoc, "immediate operand value out of range");
1510 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001511 case Mips::ANDI16_MM:
1512 Opnd = Inst.getOperand(2);
1513 if (!Opnd.isImm())
1514 return Error(IDLoc, "expected immediate operand kind");
1515 Imm = Opnd.getImm();
1516 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1517 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1518 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1519 return Error(IDLoc, "immediate operand value out of range");
1520 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001521 case Mips::LBU16_MM:
1522 Opnd = Inst.getOperand(2);
1523 if (!Opnd.isImm())
1524 return Error(IDLoc, "expected immediate operand kind");
1525 Imm = Opnd.getImm();
1526 if (Imm < -1 || Imm > 14)
1527 return Error(IDLoc, "immediate operand value out of range");
1528 break;
1529 case Mips::SB16_MM:
1530 Opnd = Inst.getOperand(2);
1531 if (!Opnd.isImm())
1532 return Error(IDLoc, "expected immediate operand kind");
1533 Imm = Opnd.getImm();
1534 if (Imm < 0 || Imm > 15)
1535 return Error(IDLoc, "immediate operand value out of range");
1536 break;
1537 case Mips::LHU16_MM:
1538 case Mips::SH16_MM:
1539 Opnd = Inst.getOperand(2);
1540 if (!Opnd.isImm())
1541 return Error(IDLoc, "expected immediate operand kind");
1542 Imm = Opnd.getImm();
1543 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1544 return Error(IDLoc, "immediate operand value out of range");
1545 break;
1546 case Mips::LW16_MM:
1547 case Mips::SW16_MM:
1548 Opnd = Inst.getOperand(2);
1549 if (!Opnd.isImm())
1550 return Error(IDLoc, "expected immediate operand kind");
1551 Imm = Opnd.getImm();
1552 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1553 return Error(IDLoc, "immediate operand value out of range");
1554 break;
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001555 case Mips::CACHE:
1556 case Mips::PREF:
1557 Opnd = Inst.getOperand(2);
1558 if (!Opnd.isImm())
1559 return Error(IDLoc, "expected immediate operand kind");
1560 Imm = Opnd.getImm();
1561 if (!isUInt<5>(Imm))
1562 return Error(IDLoc, "immediate operand value out of range");
1563 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001564 case Mips::ADDIUPC_MM:
1565 MCOperand Opnd = Inst.getOperand(1);
1566 if (!Opnd.isImm())
1567 return Error(IDLoc, "expected immediate operand kind");
1568 int Imm = Opnd.getImm();
1569 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1570 return Error(IDLoc, "immediate operand value out of range");
1571 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001572 }
1573 }
1574
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001575 if (needsExpansion(Inst)) {
1576 if (expandInstruction(Inst, IDLoc, Instructions))
1577 return true;
1578 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001579 Instructions.push_back(Inst);
1580
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001581 // If this instruction has a delay slot and .set reorder is active,
1582 // emit a NOP after it.
1583 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1584 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1585
Jack Carter9e65aa32013-03-22 00:05:30 +00001586 return false;
1587}
1588
Jack Carter30a59822012-10-04 04:03:53 +00001589bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1590
Jack Carterd0bd6422013-04-18 00:41:53 +00001591 switch (Inst.getOpcode()) {
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001592 case Mips::LoadImm32:
1593 case Mips::LoadImm64:
1594 case Mips::LoadAddrImm32:
1595 case Mips::LoadAddrReg32:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001596 case Mips::B_MM_Pseudo:
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001597 case Mips::LWM_MM:
1598 case Mips::SWM_MM:
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001599 case Mips::JalOneReg:
1600 case Mips::JalTwoReg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001601 return true;
1602 default:
1603 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001604 }
1605}
Jack Carter92995f12012-10-06 00:53:28 +00001606
Matheus Almeida3813d572014-06-19 14:39:14 +00001607bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001608 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001609 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001610 default: llvm_unreachable("unimplemented expansion");
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001611 case Mips::LoadImm32:
Jack Carterd0bd6422013-04-18 00:41:53 +00001612 return expandLoadImm(Inst, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001613 case Mips::LoadImm64:
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001614 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001615 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001616 return true;
1617 }
1618 return expandLoadImm(Inst, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001619 case Mips::LoadAddrImm32:
Jack Carterd0bd6422013-04-18 00:41:53 +00001620 return expandLoadAddressImm(Inst, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001621 case Mips::LoadAddrReg32:
Jack Carterd0bd6422013-04-18 00:41:53 +00001622 return expandLoadAddressReg(Inst, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001623 case Mips::B_MM_Pseudo:
1624 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001625 case Mips::SWM_MM:
1626 case Mips::LWM_MM:
1627 return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001628 case Mips::JalOneReg:
1629 case Mips::JalTwoReg:
1630 return expandJalWithRegs(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001631 }
Jack Carter30a59822012-10-04 04:03:53 +00001632}
Jack Carter92995f12012-10-06 00:53:28 +00001633
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001634namespace {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001635template <bool PerformShift>
1636void createShiftOr(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001637 SmallVectorImpl<MCInst> &Instructions) {
1638 MCInst tmpInst;
1639 if (PerformShift) {
1640 tmpInst.setOpcode(Mips::DSLL);
1641 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1642 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1643 tmpInst.addOperand(MCOperand::CreateImm(16));
1644 tmpInst.setLoc(IDLoc);
1645 Instructions.push_back(tmpInst);
1646 tmpInst.clear();
1647 }
1648 tmpInst.setOpcode(Mips::ORi);
1649 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1650 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001651 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001652 tmpInst.setLoc(IDLoc);
1653 Instructions.push_back(tmpInst);
1654}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001655
1656template <int Shift, bool PerformShift>
1657void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1658 SmallVectorImpl<MCInst> &Instructions) {
1659 createShiftOr<PerformShift>(
1660 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)), RegNo,
1661 IDLoc, Instructions);
1662}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001663}
1664
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001665bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
1666 SmallVectorImpl<MCInst> &Instructions) {
1667 // Create a JALR instruction which is going to replace the pseudo-JAL.
1668 MCInst JalrInst;
1669 JalrInst.setLoc(IDLoc);
1670 const MCOperand FirstRegOp = Inst.getOperand(0);
1671 const unsigned Opcode = Inst.getOpcode();
1672
1673 if (Opcode == Mips::JalOneReg) {
1674 // jal $rs => jalr $rs
1675 if (inMicroMipsMode()) {
1676 JalrInst.setOpcode(Mips::JALR16_MM);
1677 JalrInst.addOperand(FirstRegOp);
1678 } else {
1679 JalrInst.setOpcode(Mips::JALR);
1680 JalrInst.addOperand(MCOperand::CreateReg(Mips::RA));
1681 JalrInst.addOperand(FirstRegOp);
1682 }
1683 } else if (Opcode == Mips::JalTwoReg) {
1684 // jal $rd, $rs => jalr $rd, $rs
1685 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
1686 JalrInst.addOperand(FirstRegOp);
1687 const MCOperand SecondRegOp = Inst.getOperand(1);
1688 JalrInst.addOperand(SecondRegOp);
1689 }
1690 Instructions.push_back(JalrInst);
1691
1692 // If .set reorder is active, emit a NOP after it.
1693 if (AssemblerOptions.back()->isReorder()) {
1694 // This is a 32-bit NOP because these 2 pseudo-instructions
1695 // do not have a short delay slot.
1696 MCInst NopInst;
1697 NopInst.setOpcode(Mips::SLL);
1698 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1699 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1700 NopInst.addOperand(MCOperand::CreateImm(0));
1701 Instructions.push_back(NopInst);
1702 }
1703
1704 return false;
1705}
1706
Matheus Almeida3813d572014-06-19 14:39:14 +00001707bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001708 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001709 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001710 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001711 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001712 const MCOperand &RegOp = Inst.getOperand(0);
1713 assert(RegOp.isReg() && "expected register operand kind");
1714
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001715 int64_t ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001716 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001717 // FIXME: gas has a special case for values that are 000...1111, which
1718 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001719 if (0 <= ImmValue && ImmValue <= 65535) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001720 // For unsigned and positive signed 16-bit values (0 <= j <= 65535):
Jack Carter30a59822012-10-04 04:03:53 +00001721 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001722 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001723 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001724 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001725 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001726 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001727 } else if (ImmValue < 0 && ImmValue >= -32768) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001728 // For negative signed 16-bit values (-32768 <= j < 0):
Jack Carter30a59822012-10-04 04:03:53 +00001729 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001730 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001731 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001732 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001733 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001734 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001735 } else if ((ImmValue & 0xffffffff) == ImmValue) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001736 // For all other values which are representable as a 32-bit integer:
Jack Carter30a59822012-10-04 04:03:53 +00001737 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001738 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001739 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001740 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1741 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001742 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001743 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1744 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001745 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001746 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001747 return true;
1748 }
1749
1750 // <------- lo32 ------>
1751 // <------- hi32 ------>
1752 // <- hi16 -> <- lo16 ->
1753 // _________________________________
1754 // | | | |
1755 // | 16-bytes | 16-bytes | 16-bytes |
1756 // |__________|__________|__________|
1757 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001758 // For any 64-bit value that is representable as a 48-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001759 // li d,j => lui d,hi16(j)
1760 // ori d,d,hi16(lo32(j))
1761 // dsll d,d,16
1762 // ori d,d,lo16(lo32(j))
1763 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001764 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001765 tmpInst.addOperand(
1766 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001767 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001768 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1769 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1770 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001771 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001772 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001773 return true;
1774 }
1775
1776 // <------- hi32 ------> <------- lo32 ------>
1777 // <- hi16 -> <- lo16 ->
1778 // ___________________________________________
1779 // | | | | |
1780 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1781 // |__________|__________|__________|__________|
1782 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001783 // For all other values which are representable as a 64-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001784 // li d,j => lui d,hi16(j)
1785 // ori d,d,lo16(hi32(j))
1786 // dsll d,d,16
1787 // ori d,d,hi16(lo32(j))
1788 // dsll d,d,16
1789 // ori d,d,lo16(lo32(j))
1790 tmpInst.setOpcode(Mips::LUi);
1791 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1792 tmpInst.addOperand(
1793 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1794 Instructions.push_back(tmpInst);
1795 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1796 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1797 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001798 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001799 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001800}
Jack Carter92995f12012-10-06 00:53:28 +00001801
Matheus Almeida3813d572014-06-19 14:39:14 +00001802bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001803MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1804 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001805 MCInst tmpInst;
1806 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001807 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1808 "expected immediate operand kind");
1809 if (!ImmOp.isImm()) {
1810 expandLoadAddressSym(Inst, IDLoc, Instructions);
1811 return false;
1812 }
Jack Carter543fdf82012-10-09 23:29:45 +00001813 const MCOperand &SrcRegOp = Inst.getOperand(1);
1814 assert(SrcRegOp.isReg() && "expected register operand kind");
1815 const MCOperand &DstRegOp = Inst.getOperand(0);
1816 assert(DstRegOp.isReg() && "expected register operand kind");
1817 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001818 if (-32768 <= ImmValue && ImmValue <= 65535) {
1819 // For -32768 <= j <= 65535.
1820 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001821 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001822 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1823 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1824 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1825 Instructions.push_back(tmpInst);
1826 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001827 // For any other value of j that is representable as a 32-bit integer.
1828 // la d,j(s) => lui d,hi16(j)
1829 // ori d,d,lo16(j)
1830 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001831 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001832 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1833 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1834 Instructions.push_back(tmpInst);
1835 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001836 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001837 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1838 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1839 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1840 Instructions.push_back(tmpInst);
1841 tmpInst.clear();
1842 tmpInst.setOpcode(Mips::ADDu);
1843 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1844 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1845 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1846 Instructions.push_back(tmpInst);
1847 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001848 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001849}
1850
Matheus Almeida3813d572014-06-19 14:39:14 +00001851bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001852MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1853 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001854 MCInst tmpInst;
1855 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001856 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1857 "expected immediate operand kind");
1858 if (!ImmOp.isImm()) {
1859 expandLoadAddressSym(Inst, IDLoc, Instructions);
1860 return false;
1861 }
Jack Carter543fdf82012-10-09 23:29:45 +00001862 const MCOperand &RegOp = Inst.getOperand(0);
1863 assert(RegOp.isReg() && "expected register operand kind");
1864 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001865 if (-32768 <= ImmValue && ImmValue <= 65535) {
1866 // For -32768 <= j <= 65535.
1867 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001868 tmpInst.setOpcode(Mips::ADDiu);
1869 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001870 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001871 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1872 Instructions.push_back(tmpInst);
1873 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001874 // For any other value of j that is representable as a 32-bit integer.
1875 // la d,j => lui d,hi16(j)
1876 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001877 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001878 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1879 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1880 Instructions.push_back(tmpInst);
1881 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001882 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001883 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1884 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1885 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1886 Instructions.push_back(tmpInst);
1887 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001888 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001889}
1890
Toma Tabacu0d64b202014-08-14 10:29:17 +00001891void
1892MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1893 SmallVectorImpl<MCInst> &Instructions) {
1894 // FIXME: If we do have a valid at register to use, we should generate a
1895 // slightly shorter sequence here.
1896 MCInst tmpInst;
1897 int ExprOperandNo = 1;
1898 // Sometimes the assembly parser will get the immediate expression as
1899 // a $zero + an immediate.
1900 if (Inst.getNumOperands() == 3) {
1901 assert(Inst.getOperand(1).getReg() ==
1902 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1903 ExprOperandNo = 2;
1904 }
1905 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1906 assert(SymOp.isExpr() && "expected symbol operand kind");
1907 const MCOperand &RegOp = Inst.getOperand(0);
1908 unsigned RegNo = RegOp.getReg();
1909 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1910 const MCSymbolRefExpr *HiExpr =
1911 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1912 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1913 const MCSymbolRefExpr *LoExpr =
1914 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1915 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1916 if (isGP64bit()) {
1917 // If it's a 64-bit architecture, expand to:
1918 // la d,sym => lui d,highest(sym)
1919 // ori d,d,higher(sym)
1920 // dsll d,d,16
1921 // ori d,d,hi16(sym)
1922 // dsll d,d,16
1923 // ori d,d,lo16(sym)
1924 const MCSymbolRefExpr *HighestExpr =
1925 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1926 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1927 const MCSymbolRefExpr *HigherExpr =
1928 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1929 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1930
1931 tmpInst.setOpcode(Mips::LUi);
1932 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1933 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1934 Instructions.push_back(tmpInst);
1935
1936 createShiftOr<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1937 Instructions);
1938 createShiftOr<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
1939 Instructions);
1940 createShiftOr<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1941 Instructions);
1942 } else {
1943 // Otherwise, expand to:
1944 // la d,sym => lui d,hi16(sym)
1945 // ori d,d,lo16(sym)
1946 tmpInst.setOpcode(Mips::LUi);
1947 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1948 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1949 Instructions.push_back(tmpInst);
1950
1951 createShiftOr<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1952 Instructions);
1953 }
1954}
1955
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00001956bool MipsAsmParser::expandUncondBranchMMPseudo(
1957 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00001958 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
1959 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001960
1961 MCOperand Offset = Inst.getOperand(0);
1962 if (Offset.isExpr()) {
1963 Inst.clear();
1964 Inst.setOpcode(Mips::BEQ_MM);
1965 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1966 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1967 Inst.addOperand(MCOperand::CreateExpr(Offset.getExpr()));
1968 } else {
1969 assert(Offset.isImm() && "expected immediate operand kind");
1970 if (isIntN(11, Offset.getImm())) {
1971 // If offset fits into 11 bits then this instruction becomes microMIPS
1972 // 16-bit unconditional branch instruction.
1973 Inst.setOpcode(Mips::B16_MM);
1974 } else {
1975 if (!isIntN(17, Offset.getImm()))
1976 Error(IDLoc, "branch target out of range");
1977 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
1978 Error(IDLoc, "branch to misaligned address");
1979 Inst.clear();
1980 Inst.setOpcode(Mips::BEQ_MM);
1981 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1982 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1983 Inst.addOperand(MCOperand::CreateImm(Offset.getImm()));
1984 }
1985 }
1986 Instructions.push_back(Inst);
1987
Toma Tabacu234482a2015-03-16 12:03:39 +00001988 // If .set reorder is active, emit a NOP after the branch instruction.
1989 if (AssemblerOptions.back()->isReorder())
1990 createNop(true, IDLoc, Instructions);
1991
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001992 return false;
1993}
1994
Jack Carter9e65aa32013-03-22 00:05:30 +00001995void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001996 SmallVectorImpl<MCInst> &Instructions,
1997 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001998 const MCSymbolRefExpr *SR;
1999 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00002000 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002001 const MCExpr *ExprOffset;
2002 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002003 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002004 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2005 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002006 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002007 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2008 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002009 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002010 if (isImmOpnd) {
2011 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2012 ImmOffset = Inst.getOperand(2).getImm();
2013 LoOffset = ImmOffset & 0x0000ffff;
2014 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002015 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002016 if (LoOffset & 0x8000)
2017 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002018 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002019 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002020 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002021 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002022 // These are some of the types of expansions we perform here:
2023 // 1) lw $8, sym => lui $8, %hi(sym)
2024 // lw $8, %lo(sym)($8)
2025 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2026 // add $8, $8, $9
2027 // lw $8, %lo(offset)($9)
2028 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2029 // add $at, $at, $8
2030 // lw $8, %lo(offset)($at)
2031 // 4) sw $8, sym => lui $at, %hi(sym)
2032 // sw $8, %lo(sym)($at)
2033 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2034 // add $at, $at, $8
2035 // sw $8, %lo(offset)($at)
2036 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2037 // ldc1 $f0, %lo(sym)($at)
2038 //
2039 // For load instructions we can use the destination register as a temporary
2040 // if base and dst are different (examples 1 and 2) and if the base register
2041 // is general purpose otherwise we must use $at (example 6) and error if it's
2042 // not available. For stores we must use $at (examples 4 and 5) because we
2043 // must not clobber the source register setting up the offset.
2044 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2045 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2046 unsigned RegClassIDOp0 =
2047 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2048 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2049 (RegClassIDOp0 == Mips::GPR64RegClassID);
2050 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002051 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002052 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002053 // At this point we need AT to perform the expansions and we exit if it is
2054 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002055 TmpRegNum = getATReg(IDLoc);
2056 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002057 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002058 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002059
Jack Carter9e65aa32013-03-22 00:05:30 +00002060 TempInst.setOpcode(Mips::LUi);
2061 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2062 if (isImmOpnd)
2063 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
2064 else {
2065 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002066 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00002067 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
2068 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
2069 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00002070 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002071 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002072 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00002073 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002074 }
2075 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002076 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002077 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002078 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002079 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002080 // Add temp register to base.
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002081 if (BaseRegNum != Mips::ZERO) {
2082 TempInst.setOpcode(Mips::ADDu);
2083 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2084 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2085 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
2086 Instructions.push_back(TempInst);
2087 TempInst.clear();
2088 }
Alp Tokercb402912014-01-24 17:20:08 +00002089 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002090 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002091 TempInst.setOpcode(Inst.getOpcode());
2092 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
2093 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2094 if (isImmOpnd)
2095 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
2096 else {
2097 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002098 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
2099 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
2100 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00002101 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002102 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002103 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00002104 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002105 }
2106 }
2107 Instructions.push_back(TempInst);
2108 TempInst.clear();
2109}
2110
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002111bool
2112MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2113 SmallVectorImpl<MCInst> &Instructions) {
2114 unsigned OpNum = Inst.getNumOperands();
2115 unsigned Opcode = Inst.getOpcode();
2116 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2117
2118 assert (Inst.getOperand(OpNum - 1).isImm() &&
2119 Inst.getOperand(OpNum - 2).isReg() &&
2120 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2121
2122 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2123 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2124 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2125 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2126 // It can be implemented as SWM16 or LWM16 instruction.
2127 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2128
2129 Inst.setOpcode(NewOpcode);
2130 Instructions.push_back(Inst);
2131 return false;
2132}
2133
Toma Tabacu234482a2015-03-16 12:03:39 +00002134void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
2135 SmallVectorImpl<MCInst> &Instructions) {
2136 MCInst NopInst;
2137 if (hasShortDelaySlot) {
2138 NopInst.setOpcode(Mips::MOVE16_MM);
2139 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2140 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2141 } else {
2142 NopInst.setOpcode(Mips::SLL);
2143 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2144 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2145 NopInst.addOperand(MCOperand::CreateImm(0));
2146 }
2147 Instructions.push_back(NopInst);
2148}
2149
Matheus Almeida595fcab2014-06-11 15:05:56 +00002150unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
2151 // As described by the Mips32r2 spec, the registers Rd and Rs for
2152 // jalr.hb must be different.
2153 unsigned Opcode = Inst.getOpcode();
2154
2155 if (Opcode == Mips::JALR_HB &&
2156 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
2157 return Match_RequiresDifferentSrcAndDst;
2158
2159 return Match_Success;
2160}
2161
David Blaikie960ea3f2014-06-08 16:18:35 +00002162bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
2163 OperandVector &Operands,
2164 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00002165 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00002166 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00002167
Jack Carterb4dbc172012-09-05 23:34:03 +00002168 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00002169 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00002170 unsigned MatchResult =
2171 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00002172
2173 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002174 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002175 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00002176 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00002177 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00002178 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00002179 return false;
2180 }
2181 case Match_MissingFeature:
2182 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
2183 return true;
2184 case Match_InvalidOperand: {
2185 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00002186 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002187 if (ErrorInfo >= Operands.size())
2188 return Error(IDLoc, "too few operands for instruction");
2189
David Blaikie960ea3f2014-06-08 16:18:35 +00002190 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00002191 if (ErrorLoc == SMLoc())
2192 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00002193 }
2194
2195 return Error(ErrorLoc, "invalid operand for instruction");
2196 }
2197 case Match_MnemonicFail:
2198 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00002199 case Match_RequiresDifferentSrcAndDst:
2200 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00002201 }
Craig Topper589ceee2015-01-03 08:16:34 +00002202
2203 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00002204}
2205
Toma Tabacud9d344b2015-04-27 14:05:04 +00002206void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
2207 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
2208 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
2209 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002210}
2211
Daniel Sandersef638fe2014-10-03 15:37:37 +00002212void
2213MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
2214 SMRange Range, bool ShowColors) {
2215 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00002216 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00002217 ShowColors);
2218}
2219
Jack Carter1ac53222013-02-20 23:11:17 +00002220int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002221 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002222
Vladimir Medic4c299852013-11-06 11:27:05 +00002223 CC = StringSwitch<unsigned>(Name)
2224 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002225 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00002226 .Case("a0", 4)
2227 .Case("a1", 5)
2228 .Case("a2", 6)
2229 .Case("a3", 7)
2230 .Case("v0", 2)
2231 .Case("v1", 3)
2232 .Case("s0", 16)
2233 .Case("s1", 17)
2234 .Case("s2", 18)
2235 .Case("s3", 19)
2236 .Case("s4", 20)
2237 .Case("s5", 21)
2238 .Case("s6", 22)
2239 .Case("s7", 23)
2240 .Case("k0", 26)
2241 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002242 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00002243 .Case("sp", 29)
2244 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002245 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00002246 .Case("ra", 31)
2247 .Case("t0", 8)
2248 .Case("t1", 9)
2249 .Case("t2", 10)
2250 .Case("t3", 11)
2251 .Case("t4", 12)
2252 .Case("t5", 13)
2253 .Case("t6", 14)
2254 .Case("t7", 15)
2255 .Case("t8", 24)
2256 .Case("t9", 25)
2257 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002258
Toma Tabacufda445c2014-09-15 15:33:01 +00002259 if (!(isABI_N32() || isABI_N64()))
2260 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002261
Daniel Sandersef638fe2014-10-03 15:37:37 +00002262 if (12 <= CC && CC <= 15) {
2263 // Name is one of t4-t7
2264 AsmToken RegTok = getLexer().peekTok();
2265 SMRange RegRange = RegTok.getLocRange();
2266
2267 StringRef FixedName = StringSwitch<StringRef>(Name)
2268 .Case("t4", "t0")
2269 .Case("t5", "t1")
2270 .Case("t6", "t2")
2271 .Case("t7", "t3")
2272 .Default("");
2273 assert(FixedName != "" && "Register name is not one of t4-t7.");
2274
2275 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
2276 "Did you mean $" + FixedName + "?", RegRange);
2277 }
2278
Toma Tabacufda445c2014-09-15 15:33:01 +00002279 // Although SGI documentation just cuts out t0-t3 for n32/n64,
2280 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
2281 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
2282 if (8 <= CC && CC <= 11)
2283 CC += 4;
2284
2285 if (CC == -1)
2286 CC = StringSwitch<unsigned>(Name)
2287 .Case("a4", 8)
2288 .Case("a5", 9)
2289 .Case("a6", 10)
2290 .Case("a7", 11)
2291 .Case("kt0", 26)
2292 .Case("kt1", 27)
2293 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002294
2295 return CC;
2296}
Jack Carterd0bd6422013-04-18 00:41:53 +00002297
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002298int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
2299 int CC;
2300
2301 CC = StringSwitch<unsigned>(Name)
2302 .Case("hwr_cpunum", 0)
2303 .Case("hwr_synci_step", 1)
2304 .Case("hwr_cc", 2)
2305 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00002306 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002307 .Default(-1);
2308
2309 return CC;
2310}
2311
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002312int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002313
Jack Cartera63b16a2012-09-07 00:23:42 +00002314 if (Name[0] == 'f') {
2315 StringRef NumString = Name.substr(1);
2316 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002317 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002318 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002319 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00002320 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002321 return IntVal;
2322 }
2323 return -1;
2324}
Jack Cartera63b16a2012-09-07 00:23:42 +00002325
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002326int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
2327
2328 if (Name.startswith("fcc")) {
2329 StringRef NumString = Name.substr(3);
2330 unsigned IntVal;
2331 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002332 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002333 if (IntVal > 7) // There are only 8 fcc registers.
2334 return -1;
2335 return IntVal;
2336 }
2337 return -1;
2338}
2339
2340int MipsAsmParser::matchACRegisterName(StringRef Name) {
2341
Akira Hatanaka274d24c2013-08-14 01:15:52 +00002342 if (Name.startswith("ac")) {
2343 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002344 unsigned IntVal;
2345 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002346 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002347 if (IntVal > 3) // There are only 3 acc registers.
2348 return -1;
2349 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00002350 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002351 return -1;
2352}
Jack Carterd0bd6422013-04-18 00:41:53 +00002353
Jack Carter5dc8ac92013-09-25 23:50:44 +00002354int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
2355 unsigned IntVal;
2356
2357 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2358 return -1;
2359
2360 if (IntVal > 31)
2361 return -1;
2362
2363 return IntVal;
2364}
2365
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002366int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
2367 int CC;
2368
2369 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00002370 .Case("msair", 0)
2371 .Case("msacsr", 1)
2372 .Case("msaaccess", 2)
2373 .Case("msasave", 3)
2374 .Case("msamodify", 4)
2375 .Case("msarequest", 5)
2376 .Case("msamap", 6)
2377 .Case("msaunmap", 7)
2378 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002379
2380 return CC;
2381}
2382
Toma Tabacu89a712b2015-04-15 10:48:56 +00002383unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00002384 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00002385 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002386 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00002387 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00002388 return 0;
2389 }
2390 unsigned AT = getReg(
2391 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00002392 return AT;
2393}
Jack Carter0b744b32012-10-04 02:29:46 +00002394
Jack Carterd0bd6422013-04-18 00:41:53 +00002395unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00002396 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00002397}
2398
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002399unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002400 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00002401 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002402}
2403
Jack Carter873c7242013-01-12 01:03:14 +00002404int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002405 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00002406 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00002407 return -1;
2408
Jack Carter873c7242013-01-12 01:03:14 +00002409 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00002410}
2411
Toma Tabacu13964452014-09-04 13:23:44 +00002412bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002413 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002414 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002415
Jack Carter30a59822012-10-04 04:03:53 +00002416 // Check if the current operand has a custom associated parser, if so, try to
2417 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00002418 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2419 if (ResTy == MatchOperand_Success)
2420 return false;
2421 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2422 // there was a match, but an error occurred, in which case, just return that
2423 // the operand parsing failed.
2424 if (ResTy == MatchOperand_ParseFail)
2425 return true;
2426
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002427 DEBUG(dbgs() << ".. Generic Parser\n");
2428
Jack Carterb4dbc172012-09-05 23:34:03 +00002429 switch (getLexer().getKind()) {
2430 default:
2431 Error(Parser.getTok().getLoc(), "unexpected token in operand");
2432 return true;
2433 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002434 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00002435 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00002436
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002437 // Almost all registers have been parsed by custom parsers. There is only
2438 // one exception to this. $zero (and it's alias $0) will reach this point
2439 // for div, divu, and similar instructions because it is not an operand
2440 // to the instruction definition but an explicit register. Special case
2441 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00002442 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00002443 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002444
Jack Carterd0bd6422013-04-18 00:41:53 +00002445 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00002446 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002447 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00002448 return true;
2449
Jack Carter873c7242013-01-12 01:03:14 +00002450 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00002451 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00002452 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00002453 const MCExpr *Res =
2454 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00002455
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002456 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002457 return false;
2458 }
Vladimir Medic4c299852013-11-06 11:27:05 +00002459 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00002460 case AsmToken::LParen:
2461 case AsmToken::Minus:
2462 case AsmToken::Plus:
2463 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002464 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00002465 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002466 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002467 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002468 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00002469 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00002470 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002471 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002472 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002473 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00002474 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00002475 return true;
2476
Jack Carter873c7242013-01-12 01:03:14 +00002477 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2478
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002479 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00002480 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002481 } // case AsmToken::Percent
2482 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00002483 return true;
2484}
2485
Vladimir Medic4c299852013-11-06 11:27:05 +00002486const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00002487 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00002488 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00002489 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002490 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00002491 // It's a constant, evaluate reloc value.
2492 int16_t Val;
2493 switch (getVariantKind(RelocStr)) {
2494 case MCSymbolRefExpr::VK_Mips_ABS_LO:
2495 // Get the 1st 16-bits.
2496 Val = MCE->getValue() & 0xffff;
2497 break;
2498 case MCSymbolRefExpr::VK_Mips_ABS_HI:
2499 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2500 // 16 bits being negative.
2501 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2502 break;
2503 case MCSymbolRefExpr::VK_Mips_HIGHER:
2504 // Get the 3rd 16-bits.
2505 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2506 break;
2507 case MCSymbolRefExpr::VK_Mips_HIGHEST:
2508 // Get the 4th 16-bits.
2509 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2510 break;
2511 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00002512 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00002513 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00002514 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002515 }
2516
Jack Carterb5cf5902013-04-17 00:18:04 +00002517 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002518 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00002519 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00002520 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00002521 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002522 return Res;
2523 }
2524
2525 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00002526 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2527
Sasa Stankovic06c47802014-04-03 10:37:45 +00002528 // Try to create target expression.
2529 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
2530 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002531
Jack Carterd0bd6422013-04-18 00:41:53 +00002532 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2533 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00002534 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
2535 return Res;
2536 }
2537
2538 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002539 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
2540 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
2541 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002542 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002543 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002544 return Expr;
2545}
2546
2547bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2548
2549 switch (Expr->getKind()) {
2550 case MCExpr::Constant:
2551 return true;
2552 case MCExpr::SymbolRef:
2553 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2554 case MCExpr::Binary:
2555 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2556 if (!isEvaluated(BE->getLHS()))
2557 return false;
2558 return isEvaluated(BE->getRHS());
2559 }
2560 case MCExpr::Unary:
2561 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002562 case MCExpr::Target:
2563 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002564 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002565 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002566}
Jack Carterd0bd6422013-04-18 00:41:53 +00002567
Jack Carterb5cf5902013-04-17 00:18:04 +00002568bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002569 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00002570 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002571 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002572 if (Tok.isNot(AsmToken::Identifier))
2573 return true;
2574
Yaron Keren075759a2015-03-30 15:42:36 +00002575 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00002576
Jack Carterd0bd6422013-04-18 00:41:53 +00002577 Parser.Lex(); // Eat the identifier.
2578 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002579 const MCExpr *IdVal;
2580 SMLoc EndLoc;
2581
2582 if (getLexer().getKind() == AsmToken::LParen) {
2583 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002584 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002585 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002586 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002587 const AsmToken &nextTok = Parser.getTok();
2588 if (nextTok.isNot(AsmToken::Identifier))
2589 return true;
2590 Str += "(%";
2591 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002592 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002593 if (getLexer().getKind() != AsmToken::LParen)
2594 return true;
2595 } else
2596 break;
2597 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002598 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002599 return true;
2600
2601 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002602 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002603
2604 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002605 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002606
Jack Carterd0bd6422013-04-18 00:41:53 +00002607 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002608 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002609}
2610
Jack Carterb4dbc172012-09-05 23:34:03 +00002611bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2612 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002613 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002614 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002615 if (ResTy == MatchOperand_Success) {
2616 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002617 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002618 StartLoc = Operand.getStartLoc();
2619 EndLoc = Operand.getEndLoc();
2620
2621 // AFAIK, we only support numeric registers and named GPR's in CFI
2622 // directives.
2623 // Don't worry about eating tokens before failing. Using an unrecognised
2624 // register is a parse error.
2625 if (Operand.isGPRAsmReg()) {
2626 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002627 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002628 }
2629
2630 return (RegNo == (unsigned)-1);
2631 }
2632
2633 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002634 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002635}
2636
Jack Carterb5cf5902013-04-17 00:18:04 +00002637bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002638 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00002639 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002640 bool Result = true;
2641
2642 while (getLexer().getKind() == AsmToken::LParen)
2643 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002644
Jack Carterd0bd6422013-04-18 00:41:53 +00002645 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002646 default:
2647 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002648 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002649 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002650 case AsmToken::Integer:
2651 case AsmToken::Minus:
2652 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002653 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002654 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002655 else
2656 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002657 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002658 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002659 break;
Jack Carter873c7242013-01-12 01:03:14 +00002660 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002661 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002662 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002663 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002664}
2665
David Blaikie960ea3f2014-06-08 16:18:35 +00002666MipsAsmParser::OperandMatchResultTy
2667MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002668 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002669 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002670 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002671 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002672 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002673 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002674 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002675 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002676
Jack Carterb5cf5902013-04-17 00:18:04 +00002677 if (getLexer().getKind() == AsmToken::LParen) {
2678 Parser.Lex();
2679 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002680 }
2681
Jack Carterb5cf5902013-04-17 00:18:04 +00002682 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002683 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002684 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002685
Jack Carterd0bd6422013-04-18 00:41:53 +00002686 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002687 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002688 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2689 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002690 SMLoc E =
2691 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002692 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002693 return MatchOperand_Success;
2694 }
2695 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002696 SMLoc E =
2697 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002698
Jack Carterd0bd6422013-04-18 00:41:53 +00002699 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002700 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002701 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002702 S, E, *this);
2703 Operands.push_back(
2704 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002705 return MatchOperand_Success;
2706 }
2707 Error(Parser.getTok().getLoc(), "'(' expected");
2708 return MatchOperand_ParseFail;
2709 }
2710
Jack Carterd0bd6422013-04-18 00:41:53 +00002711 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002712 }
2713
Toma Tabacu13964452014-09-04 13:23:44 +00002714 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002715 if (Res != MatchOperand_Success)
2716 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002717
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002718 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002719 Error(Parser.getTok().getLoc(), "')' expected");
2720 return MatchOperand_ParseFail;
2721 }
2722
Jack Carter873c7242013-01-12 01:03:14 +00002723 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2724
Jack Carterd0bd6422013-04-18 00:41:53 +00002725 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002726
Craig Topper062a2ba2014-04-25 05:30:21 +00002727 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002728 IdVal = MCConstantExpr::Create(0, getContext());
2729
Jack Carterd0bd6422013-04-18 00:41:53 +00002730 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002731 std::unique_ptr<MipsOperand> op(
2732 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002733 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002734 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002735 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002736 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002737 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2738 int64_t Imm;
2739 if (IdVal->EvaluateAsAbsolute(Imm))
2740 IdVal = MCConstantExpr::Create(Imm, getContext());
2741 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2742 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2743 getContext());
2744 }
2745
David Blaikie960ea3f2014-06-08 16:18:35 +00002746 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002747 return MatchOperand_Success;
2748}
2749
David Blaikie960ea3f2014-06-08 16:18:35 +00002750bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002751 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00002752 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2753 if (Sym) {
2754 SMLoc S = Parser.getTok().getLoc();
2755 const MCExpr *Expr;
2756 if (Sym->isVariable())
2757 Expr = Sym->getVariableValue();
2758 else
2759 return false;
2760 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002761 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002762 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002763 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002764 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002765 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002766 if (ResTy == MatchOperand_Success) {
2767 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002768 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002769 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002770 llvm_unreachable("Should never ParseFail");
2771 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002772 }
2773 } else if (Expr->getKind() == MCExpr::Constant) {
2774 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002775 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002776 Operands.push_back(
2777 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002778 return true;
2779 }
2780 }
2781 return false;
2782}
Jack Carterd0bd6422013-04-18 00:41:53 +00002783
Jack Carter873c7242013-01-12 01:03:14 +00002784MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002785MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002786 StringRef Identifier,
2787 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002788 int Index = matchCPURegisterName(Identifier);
2789 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002790 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002791 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2792 return MatchOperand_Success;
2793 }
2794
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002795 Index = matchHWRegsRegisterName(Identifier);
2796 if (Index != -1) {
2797 Operands.push_back(MipsOperand::createHWRegsReg(
2798 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2799 return MatchOperand_Success;
2800 }
2801
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002802 Index = matchFPURegisterName(Identifier);
2803 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002804 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002805 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2806 return MatchOperand_Success;
2807 }
2808
2809 Index = matchFCCRegisterName(Identifier);
2810 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002811 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002812 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2813 return MatchOperand_Success;
2814 }
2815
2816 Index = matchACRegisterName(Identifier);
2817 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002818 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002819 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2820 return MatchOperand_Success;
2821 }
2822
2823 Index = matchMSA128RegisterName(Identifier);
2824 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002825 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002826 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2827 return MatchOperand_Success;
2828 }
2829
2830 Index = matchMSA128CtrlRegisterName(Identifier);
2831 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002832 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002833 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2834 return MatchOperand_Success;
2835 }
2836
2837 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002838}
2839
2840MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002841MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002842 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00002843 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002844
2845 if (Token.is(AsmToken::Identifier)) {
2846 DEBUG(dbgs() << ".. identifier\n");
2847 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002848 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002849 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002850 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002851 } else if (Token.is(AsmToken::Integer)) {
2852 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002853 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002854 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2855 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002856 return MatchOperand_Success;
2857 }
2858
2859 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2860
2861 return MatchOperand_NoMatch;
2862}
2863
David Blaikie960ea3f2014-06-08 16:18:35 +00002864MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002865MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002866 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002867 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002868
2869 auto Token = Parser.getTok();
2870
2871 SMLoc S = Token.getLoc();
2872
2873 if (Token.isNot(AsmToken::Dollar)) {
2874 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2875 if (Token.is(AsmToken::Identifier)) {
2876 if (searchSymbolAlias(Operands))
2877 return MatchOperand_Success;
2878 }
2879 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2880 return MatchOperand_NoMatch;
2881 }
2882 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002883
Toma Tabacu13964452014-09-04 13:23:44 +00002884 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002885 if (ResTy == MatchOperand_Success) {
2886 Parser.Lex(); // $
2887 Parser.Lex(); // identifier
2888 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002889 return ResTy;
2890}
2891
2892MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002893MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002894 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002895 switch (getLexer().getKind()) {
2896 default:
2897 return MatchOperand_NoMatch;
2898 case AsmToken::LParen:
2899 case AsmToken::Minus:
2900 case AsmToken::Plus:
2901 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002902 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002903 case AsmToken::String:
2904 break;
2905 }
2906
2907 const MCExpr *IdVal;
2908 SMLoc S = Parser.getTok().getLoc();
2909 if (getParser().parseExpression(IdVal))
2910 return MatchOperand_ParseFail;
2911
2912 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2913 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2914 return MatchOperand_Success;
2915}
2916
David Blaikie960ea3f2014-06-08 16:18:35 +00002917MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002918MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002919 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002920 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002921
2922 SMLoc S = getLexer().getLoc();
2923
2924 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002925 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002926 if (ResTy != MatchOperand_NoMatch)
2927 return ResTy;
2928
Daniel Sanders315386c2014-04-01 10:40:14 +00002929 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002930 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002931 if (ResTy != MatchOperand_NoMatch)
2932 return ResTy;
2933
Daniel Sandersffd84362014-04-01 10:41:48 +00002934 const MCExpr *Expr = nullptr;
2935 if (Parser.parseExpression(Expr)) {
2936 // We have no way of knowing if a symbol was consumed so we must ParseFail
2937 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002938 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002939 Operands.push_back(
2940 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002941 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002942}
2943
Vladimir Medic2b953d02013-10-01 09:48:56 +00002944MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002945MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002946 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00002947 const MCExpr *IdVal;
2948 // If the first token is '$' we may have register operand.
2949 if (Parser.getTok().is(AsmToken::Dollar))
2950 return MatchOperand_NoMatch;
2951 SMLoc S = Parser.getTok().getLoc();
2952 if (getParser().parseExpression(IdVal))
2953 return MatchOperand_ParseFail;
2954 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002955 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002956 int64_t Val = MCE->getValue();
2957 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2958 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002959 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002960 return MatchOperand_Success;
2961}
2962
Matheus Almeida779c5932013-11-18 12:32:49 +00002963MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002964MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002965 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00002966 switch (getLexer().getKind()) {
2967 default:
2968 return MatchOperand_NoMatch;
2969 case AsmToken::LParen:
2970 case AsmToken::Plus:
2971 case AsmToken::Minus:
2972 case AsmToken::Integer:
2973 break;
2974 }
2975
2976 const MCExpr *Expr;
2977 SMLoc S = Parser.getTok().getLoc();
2978
2979 if (getParser().parseExpression(Expr))
2980 return MatchOperand_ParseFail;
2981
2982 int64_t Val;
2983 if (!Expr->EvaluateAsAbsolute(Val)) {
2984 Error(S, "expected immediate value");
2985 return MatchOperand_ParseFail;
2986 }
2987
2988 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2989 // and because the CPU always adds one to the immediate field, the allowed
2990 // range becomes 1..4. We'll only check the range here and will deal
2991 // with the addition/subtraction when actually decoding/encoding
2992 // the instruction.
2993 if (Val < 1 || Val > 4) {
2994 Error(S, "immediate not in range (1..4)");
2995 return MatchOperand_ParseFail;
2996 }
2997
Jack Carter3b2c96e2014-01-22 23:31:38 +00002998 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002999 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00003000 return MatchOperand_Success;
3001}
3002
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00003003MipsAsmParser::OperandMatchResultTy
3004MipsAsmParser::parseRegisterList(OperandVector &Operands) {
3005 MCAsmParser &Parser = getParser();
3006 SmallVector<unsigned, 10> Regs;
3007 unsigned RegNo;
3008 unsigned PrevReg = Mips::NoRegister;
3009 bool RegRange = false;
3010 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3011
3012 if (Parser.getTok().isNot(AsmToken::Dollar))
3013 return MatchOperand_ParseFail;
3014
3015 SMLoc S = Parser.getTok().getLoc();
3016 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
3017 SMLoc E = getLexer().getLoc();
3018 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
3019 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
3020 if (RegRange) {
3021 // Remove last register operand because registers from register range
3022 // should be inserted first.
3023 if (RegNo == Mips::RA) {
3024 Regs.push_back(RegNo);
3025 } else {
3026 unsigned TmpReg = PrevReg + 1;
3027 while (TmpReg <= RegNo) {
3028 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
3029 Error(E, "invalid register operand");
3030 return MatchOperand_ParseFail;
3031 }
3032
3033 PrevReg = TmpReg;
3034 Regs.push_back(TmpReg++);
3035 }
3036 }
3037
3038 RegRange = false;
3039 } else {
3040 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
3041 (RegNo != Mips::RA)) {
3042 Error(E, "$16 or $31 expected");
3043 return MatchOperand_ParseFail;
3044 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
3045 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3046 Error(E, "invalid register operand");
3047 return MatchOperand_ParseFail;
3048 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
3049 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3050 Error(E, "consecutive register numbers expected");
3051 return MatchOperand_ParseFail;
3052 }
3053
3054 Regs.push_back(RegNo);
3055 }
3056
3057 if (Parser.getTok().is(AsmToken::Minus))
3058 RegRange = true;
3059
3060 if (!Parser.getTok().isNot(AsmToken::Minus) &&
3061 !Parser.getTok().isNot(AsmToken::Comma)) {
3062 Error(E, "',' or '-' expected");
3063 return MatchOperand_ParseFail;
3064 }
3065
3066 Lex(); // Consume comma or minus
3067 if (Parser.getTok().isNot(AsmToken::Dollar))
3068 break;
3069
3070 PrevReg = RegNo;
3071 }
3072
3073 SMLoc E = Parser.getTok().getLoc();
3074 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3075 parseMemOperand(Operands);
3076 return MatchOperand_Success;
3077}
3078
Zoran Jovanovic2deca342014-12-16 14:59:10 +00003079MipsAsmParser::OperandMatchResultTy
3080MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
3081 MCAsmParser &Parser = getParser();
3082
3083 SMLoc S = Parser.getTok().getLoc();
3084 if (parseAnyRegister(Operands) != MatchOperand_Success)
3085 return MatchOperand_ParseFail;
3086
3087 SMLoc E = Parser.getTok().getLoc();
3088 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
3089 unsigned Reg = Op.getGPR32Reg();
3090 Operands.pop_back();
3091 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
3092 return MatchOperand_Success;
3093}
3094
Zoran Jovanovic41688672015-02-10 16:36:20 +00003095MipsAsmParser::OperandMatchResultTy
3096MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
3097 MCAsmParser &Parser = getParser();
3098 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3099 SmallVector<unsigned, 10> Regs;
3100
3101 if (Parser.getTok().isNot(AsmToken::Dollar))
3102 return MatchOperand_ParseFail;
3103
3104 SMLoc S = Parser.getTok().getLoc();
3105
3106 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3107 return MatchOperand_ParseFail;
3108
3109 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3110 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3111 Regs.push_back(RegNo);
3112
3113 SMLoc E = Parser.getTok().getLoc();
3114 if (Parser.getTok().isNot(AsmToken::Comma)) {
3115 Error(E, "',' expected");
3116 return MatchOperand_ParseFail;
3117 }
3118
3119 // Remove comma.
3120 Parser.Lex();
3121
3122 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3123 return MatchOperand_ParseFail;
3124
3125 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3126 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3127 Regs.push_back(RegNo);
3128
3129 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3130
3131 return MatchOperand_Success;
3132}
3133
Jack Carterdc1e35d2012-09-06 20:00:02 +00003134MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
3135
Vladimir Medic4c299852013-11-06 11:27:05 +00003136 MCSymbolRefExpr::VariantKind VK =
3137 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
3138 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
3139 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
3140 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
3141 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
3142 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
3143 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
3144 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
3145 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
3146 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
3147 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
3148 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
3149 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
3150 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
3151 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
3152 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
3153 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
3154 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00003155 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
3156 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
3157 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
3158 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
3159 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
3160 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00003161 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
3162 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00003163 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003164
Matheus Almeida2852af82014-04-22 10:15:54 +00003165 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00003166
Jack Carterdc1e35d2012-09-06 20:00:02 +00003167 return VK;
3168}
Jack Cartera63b16a2012-09-07 00:23:42 +00003169
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003170/// Sometimes (i.e. load/stores) the operand may be followed immediately by
3171/// either this.
3172/// ::= '(', register, ')'
3173/// handle it before we iterate so we don't get tripped up by the lack of
3174/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003175bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003176 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003177 if (getLexer().is(AsmToken::LParen)) {
3178 Operands.push_back(
3179 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
3180 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003181 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003182 SMLoc Loc = getLexer().getLoc();
3183 Parser.eatToEndOfStatement();
3184 return Error(Loc, "unexpected token in argument list");
3185 }
3186 if (Parser.getTok().isNot(AsmToken::RParen)) {
3187 SMLoc Loc = getLexer().getLoc();
3188 Parser.eatToEndOfStatement();
3189 return Error(Loc, "unexpected token, expected ')'");
3190 }
3191 Operands.push_back(
3192 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
3193 Parser.Lex();
3194 }
3195 return false;
3196}
3197
3198/// Sometimes (i.e. in MSA) the operand may be followed immediately by
3199/// either one of these.
3200/// ::= '[', register, ']'
3201/// ::= '[', integer, ']'
3202/// handle it before we iterate so we don't get tripped up by the lack of
3203/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003204bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00003205 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003206 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003207 if (getLexer().is(AsmToken::LBrac)) {
3208 Operands.push_back(
3209 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
3210 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003211 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003212 SMLoc Loc = getLexer().getLoc();
3213 Parser.eatToEndOfStatement();
3214 return Error(Loc, "unexpected token in argument list");
3215 }
3216 if (Parser.getTok().isNot(AsmToken::RBrac)) {
3217 SMLoc Loc = getLexer().getLoc();
3218 Parser.eatToEndOfStatement();
3219 return Error(Loc, "unexpected token, expected ']'");
3220 }
3221 Operands.push_back(
3222 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
3223 Parser.Lex();
3224 }
3225 return false;
3226}
3227
David Blaikie960ea3f2014-06-08 16:18:35 +00003228bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
3229 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003230 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003231 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003232
3233 // We have reached first instruction, module directive are now forbidden.
3234 getTargetStreamer().forbidModuleDirective();
3235
Vladimir Medic74593e62013-07-17 15:00:42 +00003236 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00003237 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00003238 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00003239 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00003240 }
Vladimir Medic64828a12013-07-16 10:07:14 +00003241 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003242 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003243
3244 // Read the remaining operands.
3245 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3246 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003247 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003248 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003249 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003250 return Error(Loc, "unexpected token in argument list");
3251 }
Toma Tabacu13964452014-09-04 13:23:44 +00003252 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003253 return true;
3254 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00003255
Jack Carterd0bd6422013-04-18 00:41:53 +00003256 while (getLexer().is(AsmToken::Comma)) {
3257 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00003258 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003259 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003260 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003261 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003262 return Error(Loc, "unexpected token in argument list");
3263 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003264 // Parse bracket and parenthesis suffixes before we iterate
3265 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00003266 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003267 return true;
3268 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00003269 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003270 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003271 }
3272 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003273 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3274 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003275 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003276 return Error(Loc, "unexpected token in argument list");
3277 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003278 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00003279 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00003280}
3281
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003282bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003283 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003284 SMLoc Loc = getLexer().getLoc();
3285 Parser.eatToEndOfStatement();
3286 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00003287}
3288
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003289bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003290 return Error(Loc, ErrorMsg);
3291}
3292
Jack Carter0b744b32012-10-04 02:29:46 +00003293bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003294 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003295 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00003296
3297 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00003298 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00003299
3300 Parser.Lex(); // Eat "noat".
3301
Jack Carterd0bd6422013-04-18 00:41:53 +00003302 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003303 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003304 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003305 return false;
3306 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003307
3308 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003309 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003310 return false;
3311}
Jack Carterd0bd6422013-04-18 00:41:53 +00003312
Jack Carter0b744b32012-10-04 02:29:46 +00003313bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00003314 // Line can be: ".set at", which sets $at to $1
3315 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00003316 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00003317 Parser.Lex(); // Eat "at".
3318
Jack Carter0b744b32012-10-04 02:29:46 +00003319 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003320 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00003321 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00003322
3323 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003324 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003325 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00003326 }
3327
3328 if (getLexer().isNot(AsmToken::Equal)) {
3329 reportParseError("unexpected token, expected equals sign");
3330 return false;
3331 }
3332 Parser.Lex(); // Eat "=".
3333
3334 if (getLexer().isNot(AsmToken::Dollar)) {
3335 if (getLexer().is(AsmToken::EndOfStatement)) {
3336 reportParseError("no register specified");
3337 return false;
3338 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00003339 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00003340 return false;
3341 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003342 }
3343 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00003344
Toma Tabacu16a74492015-02-13 10:30:57 +00003345 // Find out what "reg" is.
3346 unsigned AtRegNo;
3347 const AsmToken &Reg = Parser.getTok();
3348 if (Reg.is(AsmToken::Identifier)) {
3349 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
3350 } else if (Reg.is(AsmToken::Integer)) {
3351 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00003352 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00003353 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00003354 return false;
3355 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003356
3357 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00003358 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003359 reportParseError("invalid register");
3360 return false;
3361 }
3362 Parser.Lex(); // Eat "reg".
3363
3364 // If this is not the end of the statement, report an error.
3365 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3366 reportParseError("unexpected token, expected end of statement");
3367 return false;
3368 }
3369
3370 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
3371
3372 Parser.Lex(); // Consume the EndOfStatement.
3373 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003374}
3375
3376bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003377 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003378 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003379 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003380 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003381 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003382 return false;
3383 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003384 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00003385 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003386 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003387 return false;
3388}
3389
3390bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003391 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003392 Parser.Lex();
3393 // If this is not the end of the statement, report an error.
3394 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003395 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003396 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003397 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003398 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00003399 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003400 Parser.Lex(); // Consume the EndOfStatement.
3401 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003402}
3403
3404bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003405 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003406 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003407 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003408 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003409 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003410 return false;
3411 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003412 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003413 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003414 return false;
3415}
3416
3417bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003418 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003419 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003420 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003421 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003422 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003423 return false;
3424 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003425 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00003426 reportParseError("`noreorder' must be set before `nomacro'");
3427 return false;
3428 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003429 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003430 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003431 return false;
3432}
Jack Carterd76b2372013-03-21 21:44:16 +00003433
Daniel Sanders44934432014-08-07 12:03:36 +00003434bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003435 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003436 Parser.Lex();
3437
3438 // If this is not the end of the statement, report an error.
3439 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003440 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003441
3442 setFeatureBits(Mips::FeatureMSA, "msa");
3443 getTargetStreamer().emitDirectiveSetMsa();
3444 return false;
3445}
3446
3447bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003448 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003449 Parser.Lex();
3450
3451 // If this is not the end of the statement, report an error.
3452 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003453 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003454
3455 clearFeatureBits(Mips::FeatureMSA, "msa");
3456 getTargetStreamer().emitDirectiveSetNoMsa();
3457 return false;
3458}
3459
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003460bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003461 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003462 Parser.Lex(); // Eat "nodsp".
3463
3464 // If this is not the end of the statement, report an error.
3465 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3466 reportParseError("unexpected token, expected end of statement");
3467 return false;
3468 }
3469
3470 clearFeatureBits(Mips::FeatureDSP, "dsp");
3471 getTargetStreamer().emitDirectiveSetNoDsp();
3472 return false;
3473}
3474
Toma Tabacucc2502d2014-11-04 17:18:07 +00003475bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003476 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003477 Parser.Lex(); // Eat "mips16".
3478
Jack Carter39536722014-01-22 23:08:42 +00003479 // If this is not the end of the statement, report an error.
3480 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003481 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00003482 return false;
3483 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00003484
3485 setFeatureBits(Mips::FeatureMips16, "mips16");
3486 getTargetStreamer().emitDirectiveSetMips16();
3487 Parser.Lex(); // Consume the EndOfStatement.
3488 return false;
3489}
3490
3491bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003492 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003493 Parser.Lex(); // Eat "nomips16".
3494
3495 // If this is not the end of the statement, report an error.
3496 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3497 reportParseError("unexpected token, expected end of statement");
3498 return false;
3499 }
3500
3501 clearFeatureBits(Mips::FeatureMips16, "mips16");
3502 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00003503 Parser.Lex(); // Consume the EndOfStatement.
3504 return false;
3505}
3506
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003507bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003508 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003509 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003510 // Line can be: .set fp=32
3511 // .set fp=xx
3512 // .set fp=64
3513 Parser.Lex(); // Eat fp token
3514 AsmToken Tok = Parser.getTok();
3515 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003516 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003517 return false;
3518 }
3519 Parser.Lex(); // Eat '=' token.
3520 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003521
3522 if (!parseFpABIValue(FpAbiVal, ".set"))
3523 return false;
3524
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003525 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003526 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003527 return false;
3528 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003529 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003530 Parser.Lex(); // Consume the EndOfStatement.
3531 return false;
3532}
3533
Toma Tabacu9db22db2014-09-09 10:15:38 +00003534bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003535 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003536 SMLoc Loc = getLexer().getLoc();
3537
3538 Parser.Lex();
3539 if (getLexer().isNot(AsmToken::EndOfStatement))
3540 return reportParseError("unexpected token, expected end of statement");
3541
3542 // Always keep an element on the options "stack" to prevent the user
3543 // from changing the initial options. This is how we remember them.
3544 if (AssemblerOptions.size() == 2)
3545 return reportParseError(Loc, ".set pop with no .set push");
3546
3547 AssemblerOptions.pop_back();
3548 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
3549
3550 getTargetStreamer().emitDirectiveSetPop();
3551 return false;
3552}
3553
3554bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003555 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003556 Parser.Lex();
3557 if (getLexer().isNot(AsmToken::EndOfStatement))
3558 return reportParseError("unexpected token, expected end of statement");
3559
3560 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00003561 AssemblerOptions.push_back(
3562 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00003563
3564 getTargetStreamer().emitDirectiveSetPush();
3565 return false;
3566}
3567
Jack Carterd76b2372013-03-21 21:44:16 +00003568bool MipsAsmParser::parseSetAssignment() {
3569 StringRef Name;
3570 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00003571 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00003572
3573 if (Parser.parseIdentifier(Name))
3574 reportParseError("expected identifier after .set");
3575
3576 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003577 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00003578 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00003579
Jack Carter3b2c96e2014-01-22 23:31:38 +00003580 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00003581 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00003582
Toma Tabacuf25949b2015-04-07 13:59:39 +00003583 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00003584 Sym->setVariableValue(Value);
3585
3586 return false;
3587}
Jack Carterd0bd6422013-04-18 00:41:53 +00003588
Toma Tabacu26647792014-09-09 12:52:14 +00003589bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003590 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00003591 Parser.Lex();
3592 if (getLexer().isNot(AsmToken::EndOfStatement))
3593 return reportParseError("unexpected token, expected end of statement");
3594
3595 // Reset assembler options to their initial values.
3596 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
3597 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
3598
3599 getTargetStreamer().emitDirectiveSetMips0();
3600 return false;
3601}
3602
Toma Tabacu85618b32014-08-19 14:22:52 +00003603bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003604 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00003605 Parser.Lex();
3606 if (getLexer().isNot(AsmToken::Equal))
3607 return reportParseError("unexpected token, expected equals sign");
3608
3609 Parser.Lex();
3610 StringRef Arch;
3611 if (Parser.parseIdentifier(Arch))
3612 return reportParseError("expected arch identifier");
3613
3614 StringRef ArchFeatureName =
3615 StringSwitch<StringRef>(Arch)
3616 .Case("mips1", "mips1")
3617 .Case("mips2", "mips2")
3618 .Case("mips3", "mips3")
3619 .Case("mips4", "mips4")
3620 .Case("mips5", "mips5")
3621 .Case("mips32", "mips32")
3622 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003623 .Case("mips32r3", "mips32r3")
3624 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003625 .Case("mips32r6", "mips32r6")
3626 .Case("mips64", "mips64")
3627 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003628 .Case("mips64r3", "mips64r3")
3629 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003630 .Case("mips64r6", "mips64r6")
3631 .Case("cnmips", "cnmips")
3632 .Case("r4000", "mips3") // This is an implementation of Mips3.
3633 .Default("");
3634
3635 if (ArchFeatureName.empty())
3636 return reportParseError("unsupported architecture");
3637
3638 selectArch(ArchFeatureName);
3639 getTargetStreamer().emitDirectiveSetArch(Arch);
3640 return false;
3641}
3642
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003643bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003644 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003645 Parser.Lex();
3646 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003647 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003648
Matheus Almeida2852af82014-04-22 10:15:54 +00003649 switch (Feature) {
3650 default:
3651 llvm_unreachable("Unimplemented feature");
3652 case Mips::FeatureDSP:
3653 setFeatureBits(Mips::FeatureDSP, "dsp");
3654 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003655 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003656 case Mips::FeatureMicroMips:
3657 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003658 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003659 case Mips::FeatureMips1:
3660 selectArch("mips1");
3661 getTargetStreamer().emitDirectiveSetMips1();
3662 break;
3663 case Mips::FeatureMips2:
3664 selectArch("mips2");
3665 getTargetStreamer().emitDirectiveSetMips2();
3666 break;
3667 case Mips::FeatureMips3:
3668 selectArch("mips3");
3669 getTargetStreamer().emitDirectiveSetMips3();
3670 break;
3671 case Mips::FeatureMips4:
3672 selectArch("mips4");
3673 getTargetStreamer().emitDirectiveSetMips4();
3674 break;
3675 case Mips::FeatureMips5:
3676 selectArch("mips5");
3677 getTargetStreamer().emitDirectiveSetMips5();
3678 break;
3679 case Mips::FeatureMips32:
3680 selectArch("mips32");
3681 getTargetStreamer().emitDirectiveSetMips32();
3682 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003683 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003684 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003685 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003686 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003687 case Mips::FeatureMips32r3:
3688 selectArch("mips32r3");
3689 getTargetStreamer().emitDirectiveSetMips32R3();
3690 break;
3691 case Mips::FeatureMips32r5:
3692 selectArch("mips32r5");
3693 getTargetStreamer().emitDirectiveSetMips32R5();
3694 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003695 case Mips::FeatureMips32r6:
3696 selectArch("mips32r6");
3697 getTargetStreamer().emitDirectiveSetMips32R6();
3698 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003699 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003700 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00003701 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003702 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003703 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003704 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003705 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003706 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003707 case Mips::FeatureMips64r3:
3708 selectArch("mips64r3");
3709 getTargetStreamer().emitDirectiveSetMips64R3();
3710 break;
3711 case Mips::FeatureMips64r5:
3712 selectArch("mips64r5");
3713 getTargetStreamer().emitDirectiveSetMips64R5();
3714 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003715 case Mips::FeatureMips64r6:
3716 selectArch("mips64r6");
3717 getTargetStreamer().emitDirectiveSetMips64R6();
3718 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003719 }
3720 return false;
3721}
3722
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003723bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003724 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003725 if (getLexer().isNot(AsmToken::Comma)) {
3726 SMLoc Loc = getLexer().getLoc();
3727 Parser.eatToEndOfStatement();
3728 return Error(Loc, ErrorStr);
3729 }
3730
Matheus Almeida2852af82014-04-22 10:15:54 +00003731 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003732 return true;
3733}
3734
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003735bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003736 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00003737 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003738
Toma Tabacudde4c462014-11-06 10:02:45 +00003739 if (inMips16Mode()) {
3740 reportParseError(".cpload is not supported in Mips16 mode");
3741 return false;
3742 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003743
David Blaikie960ea3f2014-06-08 16:18:35 +00003744 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00003745 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003746 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3747 reportParseError("expected register containing function address");
3748 return false;
3749 }
3750
David Blaikie960ea3f2014-06-08 16:18:35 +00003751 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
3752 if (!RegOpnd.isGPRAsmReg()) {
3753 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003754 return false;
3755 }
3756
Toma Tabacudde4c462014-11-06 10:02:45 +00003757 // If this is not the end of the statement, report an error.
3758 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3759 reportParseError("unexpected token, expected end of statement");
3760 return false;
3761 }
3762
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003763 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003764 return false;
3765}
3766
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003767bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003768 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003769 unsigned FuncReg;
3770 unsigned Save;
3771 bool SaveIsReg = true;
3772
Matheus Almeida7e815762014-06-18 13:08:59 +00003773 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003774 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003775 if (ResTy == MatchOperand_NoMatch) {
3776 reportParseError("expected register containing function address");
3777 Parser.eatToEndOfStatement();
3778 return false;
3779 }
3780
3781 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3782 if (!FuncRegOpnd.isGPRAsmReg()) {
3783 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3784 Parser.eatToEndOfStatement();
3785 return false;
3786 }
3787
3788 FuncReg = FuncRegOpnd.getGPR32Reg();
3789 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003790
Toma Tabacu65f10572014-09-16 15:00:52 +00003791 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003792 return true;
3793
Toma Tabacu13964452014-09-04 13:23:44 +00003794 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003795 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003796 const AsmToken &Tok = Parser.getTok();
3797 if (Tok.is(AsmToken::Integer)) {
3798 Save = Tok.getIntVal();
3799 SaveIsReg = false;
3800 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003801 } else {
3802 reportParseError("expected save register or stack offset");
3803 Parser.eatToEndOfStatement();
3804 return false;
3805 }
3806 } else {
3807 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3808 if (!SaveOpnd.isGPRAsmReg()) {
3809 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3810 Parser.eatToEndOfStatement();
3811 return false;
3812 }
3813 Save = SaveOpnd.getGPR32Reg();
3814 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003815
Toma Tabacu65f10572014-09-16 15:00:52 +00003816 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003817 return true;
3818
Toma Tabacu8874eac2015-02-18 13:46:53 +00003819 const MCExpr *Expr;
3820 if (Parser.parseExpression(Expr)) {
3821 reportParseError("expected expression");
3822 return false;
3823 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003824
Toma Tabacu8874eac2015-02-18 13:46:53 +00003825 if (Expr->getKind() != MCExpr::SymbolRef) {
3826 reportParseError("expected symbol");
3827 return false;
3828 }
3829 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
3830
3831 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
3832 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003833 return false;
3834}
3835
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003836bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003837 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003838 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3839 const AsmToken &Tok = Parser.getTok();
3840
3841 if (Tok.getString() == "2008") {
3842 Parser.Lex();
3843 getTargetStreamer().emitDirectiveNaN2008();
3844 return false;
3845 } else if (Tok.getString() == "legacy") {
3846 Parser.Lex();
3847 getTargetStreamer().emitDirectiveNaNLegacy();
3848 return false;
3849 }
3850 }
3851 // If we don't recognize the option passed to the .nan
3852 // directive (e.g. no option or unknown option), emit an error.
3853 reportParseError("invalid option in .nan directive");
3854 return false;
3855}
3856
Jack Carter0b744b32012-10-04 02:29:46 +00003857bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003858 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003859 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003860 const AsmToken &Tok = Parser.getTok();
3861
3862 if (Tok.getString() == "noat") {
3863 return parseSetNoAtDirective();
3864 } else if (Tok.getString() == "at") {
3865 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003866 } else if (Tok.getString() == "arch") {
3867 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003868 } else if (Tok.getString() == "fp") {
3869 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003870 } else if (Tok.getString() == "pop") {
3871 return parseSetPopDirective();
3872 } else if (Tok.getString() == "push") {
3873 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003874 } else if (Tok.getString() == "reorder") {
3875 return parseSetReorderDirective();
3876 } else if (Tok.getString() == "noreorder") {
3877 return parseSetNoReorderDirective();
3878 } else if (Tok.getString() == "macro") {
3879 return parseSetMacroDirective();
3880 } else if (Tok.getString() == "nomacro") {
3881 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003882 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00003883 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003884 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003885 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003886 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003887 getTargetStreamer().emitDirectiveSetNoMicroMips();
3888 Parser.eatToEndOfStatement();
3889 return false;
3890 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003891 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003892 } else if (Tok.getString() == "mips0") {
3893 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003894 } else if (Tok.getString() == "mips1") {
3895 return parseSetFeature(Mips::FeatureMips1);
3896 } else if (Tok.getString() == "mips2") {
3897 return parseSetFeature(Mips::FeatureMips2);
3898 } else if (Tok.getString() == "mips3") {
3899 return parseSetFeature(Mips::FeatureMips3);
3900 } else if (Tok.getString() == "mips4") {
3901 return parseSetFeature(Mips::FeatureMips4);
3902 } else if (Tok.getString() == "mips5") {
3903 return parseSetFeature(Mips::FeatureMips5);
3904 } else if (Tok.getString() == "mips32") {
3905 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003906 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003907 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003908 } else if (Tok.getString() == "mips32r3") {
3909 return parseSetFeature(Mips::FeatureMips32r3);
3910 } else if (Tok.getString() == "mips32r5") {
3911 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003912 } else if (Tok.getString() == "mips32r6") {
3913 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003914 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003915 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003916 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003917 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003918 } else if (Tok.getString() == "mips64r3") {
3919 return parseSetFeature(Mips::FeatureMips64r3);
3920 } else if (Tok.getString() == "mips64r5") {
3921 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003922 } else if (Tok.getString() == "mips64r6") {
3923 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003924 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003925 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003926 } else if (Tok.getString() == "nodsp") {
3927 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003928 } else if (Tok.getString() == "msa") {
3929 return parseSetMsaDirective();
3930 } else if (Tok.getString() == "nomsa") {
3931 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003932 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003933 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003934 parseSetAssignment();
3935 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003936 }
Jack Carter07c818d2013-01-25 01:31:34 +00003937
Jack Carter0b744b32012-10-04 02:29:46 +00003938 return true;
3939}
3940
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003941/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003942/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003943bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003944 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003945 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3946 for (;;) {
3947 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003948 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003949 return true;
3950
3951 getParser().getStreamer().EmitValue(Value, Size);
3952
3953 if (getLexer().is(AsmToken::EndOfStatement))
3954 break;
3955
Jack Carter07c818d2013-01-25 01:31:34 +00003956 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003957 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00003958 Parser.Lex();
3959 }
3960 }
3961
3962 Parser.Lex();
3963 return false;
3964}
3965
Vladimir Medic4c299852013-11-06 11:27:05 +00003966/// parseDirectiveGpWord
3967/// ::= .gpword local_sym
3968bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003969 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003970 const MCExpr *Value;
3971 // EmitGPRel32Value requires an expression, so we are using base class
3972 // method to evaluate the expression.
3973 if (getParser().parseExpression(Value))
3974 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00003975 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00003976
Vladimir Medice10c1122013-11-13 13:18:04 +00003977 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003978 return Error(getLexer().getLoc(),
3979 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00003980 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00003981 return false;
3982}
3983
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003984/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00003985/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003986bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003987 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003988 const MCExpr *Value;
3989 // EmitGPRel64Value requires an expression, so we are using base class
3990 // method to evaluate the expression.
3991 if (getParser().parseExpression(Value))
3992 return true;
3993 getParser().getStreamer().EmitGPRel64Value(Value);
3994
3995 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003996 return Error(getLexer().getLoc(),
3997 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00003998 Parser.Lex(); // Eat EndOfStatement token.
3999 return false;
4000}
4001
Jack Carter0cd3c192014-01-06 23:27:31 +00004002bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004003 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00004004 // Get the option token.
4005 AsmToken Tok = Parser.getTok();
4006 // At the moment only identifiers are supported.
4007 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004008 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00004009 Parser.eatToEndOfStatement();
4010 return false;
4011 }
4012
4013 StringRef Option = Tok.getIdentifier();
4014
4015 if (Option == "pic0") {
4016 getTargetStreamer().emitDirectiveOptionPic0();
4017 Parser.Lex();
4018 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4019 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004020 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004021 Parser.eatToEndOfStatement();
4022 }
4023 return false;
4024 }
4025
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004026 if (Option == "pic2") {
4027 getTargetStreamer().emitDirectiveOptionPic2();
4028 Parser.Lex();
4029 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4030 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004031 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004032 Parser.eatToEndOfStatement();
4033 }
4034 return false;
4035 }
4036
Jack Carter0cd3c192014-01-06 23:27:31 +00004037 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00004038 Warning(Parser.getTok().getLoc(),
4039 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00004040 Parser.eatToEndOfStatement();
4041 return false;
4042}
4043
Toma Tabacu9ca50962015-04-16 09:53:47 +00004044/// parseInsnDirective
4045/// ::= .insn
4046bool MipsAsmParser::parseInsnDirective() {
4047 // If this is not the end of the statement, report an error.
4048 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4049 reportParseError("unexpected token, expected end of statement");
4050 return false;
4051 }
4052
4053 // The actual label marking happens in
4054 // MipsELFStreamer::createPendingLabelRelocs().
4055 getTargetStreamer().emitDirectiveInsn();
4056
4057 getParser().Lex(); // Eat EndOfStatement token.
4058 return false;
4059}
4060
Daniel Sanders7e527422014-07-10 13:38:23 +00004061/// parseDirectiveModule
4062/// ::= .module oddspreg
4063/// ::= .module nooddspreg
4064/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004065bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004066 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004067 MCAsmLexer &Lexer = getLexer();
4068 SMLoc L = Lexer.getLoc();
4069
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004070 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004071 // TODO : get a better message.
4072 reportParseError(".module directive must appear before any code");
4073 return false;
4074 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004075
Toma Tabacuc405c822015-01-23 10:40:19 +00004076 StringRef Option;
4077 if (Parser.parseIdentifier(Option)) {
4078 reportParseError("expected .module option identifier");
4079 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004080 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004081
Toma Tabacuc405c822015-01-23 10:40:19 +00004082 if (Option == "oddspreg") {
4083 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
4084 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4085
4086 // If this is not the end of the statement, report an error.
4087 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4088 reportParseError("unexpected token, expected end of statement");
4089 return false;
4090 }
4091
4092 return false; // parseDirectiveModule has finished successfully.
4093 } else if (Option == "nooddspreg") {
4094 if (!isABI_O32()) {
4095 Error(L, "'.module nooddspreg' requires the O32 ABI");
4096 return false;
4097 }
4098
4099 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
4100 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4101
4102 // If this is not the end of the statement, report an error.
4103 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4104 reportParseError("unexpected token, expected end of statement");
4105 return false;
4106 }
4107
4108 return false; // parseDirectiveModule has finished successfully.
4109 } else if (Option == "fp") {
4110 return parseDirectiveModuleFP();
4111 } else {
4112 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
4113 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004114}
4115
4116/// parseDirectiveModuleFP
4117/// ::= =32
4118/// ::= =xx
4119/// ::= =64
4120bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004121 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004122 MCAsmLexer &Lexer = getLexer();
4123
4124 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004125 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004126 return false;
4127 }
4128 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004129
Daniel Sanders7e527422014-07-10 13:38:23 +00004130 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004131 if (!parseFpABIValue(FpABI, ".module"))
4132 return false;
4133
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004134 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004135 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004136 return false;
4137 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004138
Daniel Sanders7201a3e2014-07-08 10:35:52 +00004139 // Emit appropriate flags.
4140 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00004141 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004142 return false;
4143}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004144
Daniel Sanders7e527422014-07-10 13:38:23 +00004145bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004146 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004147 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004148 MCAsmLexer &Lexer = getLexer();
4149
4150 if (Lexer.is(AsmToken::Identifier)) {
4151 StringRef Value = Parser.getTok().getString();
4152 Parser.Lex();
4153
4154 if (Value != "xx") {
4155 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4156 return false;
4157 }
4158
4159 if (!isABI_O32()) {
4160 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
4161 return false;
4162 }
4163
Daniel Sanders7e527422014-07-10 13:38:23 +00004164 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004165 return true;
4166 }
4167
4168 if (Lexer.is(AsmToken::Integer)) {
4169 unsigned Value = Parser.getTok().getIntVal();
4170 Parser.Lex();
4171
4172 if (Value != 32 && Value != 64) {
4173 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4174 return false;
4175 }
4176
4177 if (Value == 32) {
4178 if (!isABI_O32()) {
4179 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
4180 return false;
4181 }
4182
Daniel Sanders7e527422014-07-10 13:38:23 +00004183 FpABI = MipsABIFlagsSection::FpABIKind::S32;
4184 } else
4185 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004186
Daniel Sanders7e527422014-07-10 13:38:23 +00004187 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004188 }
4189
4190 return false;
4191}
4192
Jack Carter0b744b32012-10-04 02:29:46 +00004193bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004194 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004195 StringRef IDVal = DirectiveID.getString();
4196
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004197 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004198 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00004199 if (IDVal == ".dword") {
4200 parseDataDirective(8, DirectiveID.getLoc());
4201 return false;
4202 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004203 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004204 StringRef SymbolName;
4205
4206 if (Parser.parseIdentifier(SymbolName)) {
4207 reportParseError("expected identifier after .ent");
4208 return false;
4209 }
4210
4211 // There's an undocumented extension that allows an integer to
4212 // follow the name of the procedure which AFAICS is ignored by GAS.
4213 // Example: .ent foo,2
4214 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4215 if (getLexer().isNot(AsmToken::Comma)) {
4216 // Even though we accept this undocumented extension for compatibility
4217 // reasons, the additional integer argument does not actually change
4218 // the behaviour of the '.ent' directive, so we would like to discourage
4219 // its use. We do this by not referring to the extended version in
4220 // error messages which are not directly related to its use.
4221 reportParseError("unexpected token, expected end of statement");
4222 return false;
4223 }
4224 Parser.Lex(); // Eat the comma.
4225 const MCExpr *DummyNumber;
4226 int64_t DummyNumberVal;
4227 // If the user was explicitly trying to use the extended version,
4228 // we still give helpful extension-related error messages.
4229 if (Parser.parseExpression(DummyNumber)) {
4230 reportParseError("expected number after comma");
4231 return false;
4232 }
4233 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
4234 reportParseError("expected an absolute expression after comma");
4235 return false;
4236 }
4237 }
4238
4239 // If this is not the end of the statement, report an error.
4240 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4241 reportParseError("unexpected token, expected end of statement");
4242 return false;
4243 }
4244
4245 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
4246
4247 getTargetStreamer().emitDirectiveEnt(*Sym);
4248 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00004249 return false;
4250 }
4251
Jack Carter07c818d2013-01-25 01:31:34 +00004252 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004253 StringRef SymbolName;
4254
4255 if (Parser.parseIdentifier(SymbolName)) {
4256 reportParseError("expected identifier after .end");
4257 return false;
4258 }
4259
4260 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4261 reportParseError("unexpected token, expected end of statement");
4262 return false;
4263 }
4264
4265 if (CurrentFn == nullptr) {
4266 reportParseError(".end used without .ent");
4267 return false;
4268 }
4269
4270 if ((SymbolName != CurrentFn->getName())) {
4271 reportParseError(".end symbol does not match .ent symbol");
4272 return false;
4273 }
4274
4275 getTargetStreamer().emitDirectiveEnd(SymbolName);
4276 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00004277 return false;
4278 }
4279
Jack Carter07c818d2013-01-25 01:31:34 +00004280 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004281 // .frame $stack_reg, frame_size_in_bytes, $return_reg
4282 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004283 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004284 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4285 reportParseError("expected stack register");
4286 return false;
4287 }
4288
4289 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4290 if (!StackRegOpnd.isGPRAsmReg()) {
4291 reportParseError(StackRegOpnd.getStartLoc(),
4292 "expected general purpose register");
4293 return false;
4294 }
4295 unsigned StackReg = StackRegOpnd.getGPR32Reg();
4296
4297 if (Parser.getTok().is(AsmToken::Comma))
4298 Parser.Lex();
4299 else {
4300 reportParseError("unexpected token, expected comma");
4301 return false;
4302 }
4303
4304 // Parse the frame size.
4305 const MCExpr *FrameSize;
4306 int64_t FrameSizeVal;
4307
4308 if (Parser.parseExpression(FrameSize)) {
4309 reportParseError("expected frame size value");
4310 return false;
4311 }
4312
4313 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
4314 reportParseError("frame size not an absolute expression");
4315 return false;
4316 }
4317
4318 if (Parser.getTok().is(AsmToken::Comma))
4319 Parser.Lex();
4320 else {
4321 reportParseError("unexpected token, expected comma");
4322 return false;
4323 }
4324
4325 // Parse the return register.
4326 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00004327 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004328 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4329 reportParseError("expected return register");
4330 return false;
4331 }
4332
4333 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4334 if (!ReturnRegOpnd.isGPRAsmReg()) {
4335 reportParseError(ReturnRegOpnd.getStartLoc(),
4336 "expected general purpose register");
4337 return false;
4338 }
4339
4340 // If this is not the end of the statement, report an error.
4341 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4342 reportParseError("unexpected token, expected end of statement");
4343 return false;
4344 }
4345
4346 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
4347 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00004348 return false;
4349 }
4350
Jack Carter07c818d2013-01-25 01:31:34 +00004351 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00004352 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00004353 }
4354
Daniel Sandersd97a6342014-08-13 10:07:34 +00004355 if (IDVal == ".mask" || IDVal == ".fmask") {
4356 // .mask bitmask, frame_offset
4357 // bitmask: One bit for each register used.
4358 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
4359 // first register is expected to be saved.
4360 // Examples:
4361 // .mask 0x80000000, -4
4362 // .fmask 0x80000000, -4
4363 //
Jack Carterbe332172012-09-07 00:48:02 +00004364
Daniel Sandersd97a6342014-08-13 10:07:34 +00004365 // Parse the bitmask
4366 const MCExpr *BitMask;
4367 int64_t BitMaskVal;
4368
4369 if (Parser.parseExpression(BitMask)) {
4370 reportParseError("expected bitmask value");
4371 return false;
4372 }
4373
4374 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
4375 reportParseError("bitmask not an absolute expression");
4376 return false;
4377 }
4378
4379 if (Parser.getTok().is(AsmToken::Comma))
4380 Parser.Lex();
4381 else {
4382 reportParseError("unexpected token, expected comma");
4383 return false;
4384 }
4385
4386 // Parse the frame_offset
4387 const MCExpr *FrameOffset;
4388 int64_t FrameOffsetVal;
4389
4390 if (Parser.parseExpression(FrameOffset)) {
4391 reportParseError("expected frame offset value");
4392 return false;
4393 }
4394
4395 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
4396 reportParseError("frame offset not an absolute expression");
4397 return false;
4398 }
4399
4400 // If this is not the end of the statement, report an error.
4401 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4402 reportParseError("unexpected token, expected end of statement");
4403 return false;
4404 }
4405
4406 if (IDVal == ".mask")
4407 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
4408 else
4409 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00004410 return false;
4411 }
4412
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004413 if (IDVal == ".nan")
4414 return parseDirectiveNaN();
4415
Jack Carter07c818d2013-01-25 01:31:34 +00004416 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004417 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00004418 return false;
4419 }
4420
Rafael Espindolab59fb732014-03-28 18:50:26 +00004421 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004422 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004423 return false;
4424 }
4425
Jack Carter07c818d2013-01-25 01:31:34 +00004426 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004427 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00004428 return false;
4429 }
4430
Jack Carter0cd3c192014-01-06 23:27:31 +00004431 if (IDVal == ".option")
4432 return parseDirectiveOption();
4433
4434 if (IDVal == ".abicalls") {
4435 getTargetStreamer().emitDirectiveAbiCalls();
4436 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004437 Error(Parser.getTok().getLoc(),
4438 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004439 // Clear line
4440 Parser.eatToEndOfStatement();
4441 }
4442 return false;
4443 }
4444
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004445 if (IDVal == ".cpsetup")
4446 return parseDirectiveCPSetup();
4447
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004448 if (IDVal == ".module")
4449 return parseDirectiveModule();
4450
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004451 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
4452 return parseInternalDirectiveReallowModule();
4453
Toma Tabacu9ca50962015-04-16 09:53:47 +00004454 if (IDVal == ".insn")
4455 return parseInsnDirective();
4456
Rafael Espindola870c4e92012-01-11 03:56:41 +00004457 return true;
4458}
4459
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004460bool MipsAsmParser::parseInternalDirectiveReallowModule() {
4461 // If this is not the end of the statement, report an error.
4462 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4463 reportParseError("unexpected token, expected end of statement");
4464 return false;
4465 }
4466
4467 getTargetStreamer().reallowModuleDirective();
4468
4469 getParser().Lex(); // Eat EndOfStatement token.
4470 return false;
4471}
4472
Rafael Espindola870c4e92012-01-11 03:56:41 +00004473extern "C" void LLVMInitializeMipsAsmParser() {
4474 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
4475 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
4476 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
4477 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
4478}
Jack Carterb4dbc172012-09-05 23:34:03 +00004479
4480#define GET_REGISTER_MATCHER
4481#define GET_MATCHER_IMPLEMENTATION
4482#include "MipsGenAsmMatcher.inc"