blob: ed6e8ebe0484eb2ff0ee00e1fe0001a035024c76 [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 Tabacua2861db2015-05-01 10:26:47 +00001635template <unsigned ShiftAmount>
Toma Tabacu61145652015-04-28 13:16:06 +00001636void createLShiftOri(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001637 SmallVectorImpl<MCInst> &Instructions) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001638 MCInst tmpInst;
Toma Tabacua2861db2015-05-01 10:26:47 +00001639 if (ShiftAmount >= 32) {
1640 tmpInst.setOpcode(Mips::DSLL32);
1641 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1642 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1643 tmpInst.addOperand(MCOperand::CreateImm(ShiftAmount - 32));
1644 tmpInst.setLoc(IDLoc);
1645 Instructions.push_back(tmpInst);
1646 tmpInst.clear();
1647 } else if (ShiftAmount > 0) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001648 tmpInst.setOpcode(Mips::DSLL);
1649 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1650 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacua2861db2015-05-01 10:26:47 +00001651 tmpInst.addOperand(MCOperand::CreateImm(ShiftAmount));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001652 tmpInst.setLoc(IDLoc);
1653 Instructions.push_back(tmpInst);
1654 tmpInst.clear();
1655 }
Toma Tabacu7dea2e32015-04-28 14:06:35 +00001656 // There's no need for an ORi if the immediate is 0.
1657 if (Operand.isImm() && Operand.getImm() == 0)
1658 return;
1659
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001660 tmpInst.setOpcode(Mips::ORi);
1661 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1662 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001663 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001664 tmpInst.setLoc(IDLoc);
1665 Instructions.push_back(tmpInst);
1666}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001667
Toma Tabacua2861db2015-05-01 10:26:47 +00001668template <unsigned ShiftAmount>
Toma Tabacu61145652015-04-28 13:16:06 +00001669void createLShiftOri(int64_t Value, unsigned RegNo, SMLoc IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001670 SmallVectorImpl<MCInst> &Instructions) {
1671 createLShiftOri<ShiftAmount>(MCOperand::CreateImm(Value), RegNo, IDLoc,
1672 Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001673}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001674}
1675
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001676bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
1677 SmallVectorImpl<MCInst> &Instructions) {
1678 // Create a JALR instruction which is going to replace the pseudo-JAL.
1679 MCInst JalrInst;
1680 JalrInst.setLoc(IDLoc);
1681 const MCOperand FirstRegOp = Inst.getOperand(0);
1682 const unsigned Opcode = Inst.getOpcode();
1683
1684 if (Opcode == Mips::JalOneReg) {
1685 // jal $rs => jalr $rs
1686 if (inMicroMipsMode()) {
1687 JalrInst.setOpcode(Mips::JALR16_MM);
1688 JalrInst.addOperand(FirstRegOp);
1689 } else {
1690 JalrInst.setOpcode(Mips::JALR);
1691 JalrInst.addOperand(MCOperand::CreateReg(Mips::RA));
1692 JalrInst.addOperand(FirstRegOp);
1693 }
1694 } else if (Opcode == Mips::JalTwoReg) {
1695 // jal $rd, $rs => jalr $rd, $rs
1696 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
1697 JalrInst.addOperand(FirstRegOp);
1698 const MCOperand SecondRegOp = Inst.getOperand(1);
1699 JalrInst.addOperand(SecondRegOp);
1700 }
1701 Instructions.push_back(JalrInst);
1702
1703 // If .set reorder is active, emit a NOP after it.
1704 if (AssemblerOptions.back()->isReorder()) {
1705 // This is a 32-bit NOP because these 2 pseudo-instructions
1706 // do not have a short delay slot.
1707 MCInst NopInst;
1708 NopInst.setOpcode(Mips::SLL);
1709 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1710 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1711 NopInst.addOperand(MCOperand::CreateImm(0));
1712 Instructions.push_back(NopInst);
1713 }
1714
1715 return false;
1716}
1717
Matheus Almeida3813d572014-06-19 14:39:14 +00001718bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001719 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001720 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001721 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001722 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001723 const MCOperand &RegOp = Inst.getOperand(0);
1724 assert(RegOp.isReg() && "expected register operand kind");
1725
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001726 int64_t ImmValue = ImmOp.getImm();
Toma Tabacu137d90a2015-04-28 12:04:53 +00001727 unsigned Reg = RegOp.getReg();
Jack Carter92995f12012-10-06 00:53:28 +00001728 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001729 // FIXME: gas has a special case for values that are 000...1111, which
1730 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001731 if (0 <= ImmValue && ImmValue <= 65535) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001732 // For unsigned and positive signed 16-bit values (0 <= j <= 65535):
Jack Carter30a59822012-10-04 04:03:53 +00001733 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001734 tmpInst.setOpcode(Mips::ORi);
Toma Tabacu137d90a2015-04-28 12:04:53 +00001735 tmpInst.addOperand(MCOperand::CreateReg(Reg));
Jack Carterd0bd6422013-04-18 00:41:53 +00001736 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001737 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001738 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001739 } else if (ImmValue < 0 && ImmValue >= -32768) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001740 // For negative signed 16-bit values (-32768 <= j < 0):
Jack Carter30a59822012-10-04 04:03:53 +00001741 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001742 tmpInst.setOpcode(Mips::ADDiu);
Toma Tabacu137d90a2015-04-28 12:04:53 +00001743 tmpInst.addOperand(MCOperand::CreateReg(Reg));
Jack Carterd0bd6422013-04-18 00:41:53 +00001744 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001745 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001746 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001747 } else if ((ImmValue & 0xffffffff) == ImmValue) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001748 // For all other values which are representable as a 32-bit integer:
Jack Carter30a59822012-10-04 04:03:53 +00001749 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001750 // ori d,d,lo16(j)
Toma Tabacu79588102015-04-29 10:19:56 +00001751 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1752 uint16_t Bits15To0 = ImmValue & 0xffff;
1753
Jack Carter873c7242013-01-12 01:03:14 +00001754 tmpInst.setOpcode(Mips::LUi);
Toma Tabacu137d90a2015-04-28 12:04:53 +00001755 tmpInst.addOperand(MCOperand::CreateReg(Reg));
Toma Tabacu79588102015-04-29 10:19:56 +00001756 tmpInst.addOperand(MCOperand::CreateImm(Bits31To16));
Jack Carter30a59822012-10-04 04:03:53 +00001757 Instructions.push_back(tmpInst);
Toma Tabacua2861db2015-05-01 10:26:47 +00001758 createLShiftOri<0>(Bits15To0, Reg, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001759 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001760 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001761 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001762 return true;
1763 }
1764
1765 // <------- lo32 ------>
1766 // <------- hi32 ------>
1767 // <- hi16 -> <- lo16 ->
1768 // _________________________________
1769 // | | | |
Toma Tabacubda745f2015-04-27 15:21:38 +00001770 // | 16-bits | 16-bits | 16-bits |
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001771 // |__________|__________|__________|
1772 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001773 // For any 64-bit value that is representable as a 48-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001774 // li d,j => lui d,hi16(j)
1775 // ori d,d,hi16(lo32(j))
1776 // dsll d,d,16
1777 // ori d,d,lo16(lo32(j))
Toma Tabacu79588102015-04-29 10:19:56 +00001778 uint16_t Bits47To32 = (ImmValue >> 32) & 0xffff;
1779 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1780 uint16_t Bits15To0 = ImmValue & 0xffff;
1781
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001782 tmpInst.setOpcode(Mips::LUi);
Toma Tabacu137d90a2015-04-28 12:04:53 +00001783 tmpInst.addOperand(MCOperand::CreateReg(Reg));
Toma Tabacu79588102015-04-29 10:19:56 +00001784 tmpInst.addOperand(MCOperand::CreateImm(Bits47To32));
Jack Carter30a59822012-10-04 04:03:53 +00001785 Instructions.push_back(tmpInst);
Toma Tabacua2861db2015-05-01 10:26:47 +00001786 createLShiftOri<0>(Bits31To16, Reg, IDLoc, Instructions);
1787 createLShiftOri<16>(Bits15To0, Reg, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001788 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001789 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001790 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001791 return true;
1792 }
1793
1794 // <------- hi32 ------> <------- lo32 ------>
1795 // <- hi16 -> <- lo16 ->
1796 // ___________________________________________
1797 // | | | | |
Toma Tabacubda745f2015-04-27 15:21:38 +00001798 // | 16-bits | 16-bits | 16-bits | 16-bits |
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001799 // |__________|__________|__________|__________|
1800 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001801 // For all other values which are representable as a 64-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001802 // li d,j => lui d,hi16(j)
1803 // ori d,d,lo16(hi32(j))
1804 // dsll d,d,16
1805 // ori d,d,hi16(lo32(j))
1806 // dsll d,d,16
1807 // ori d,d,lo16(lo32(j))
Toma Tabacu79588102015-04-29 10:19:56 +00001808 uint16_t Bits63To48 = (ImmValue >> 48) & 0xffff;
1809 uint16_t Bits47To32 = (ImmValue >> 32) & 0xffff;
1810 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1811 uint16_t Bits15To0 = ImmValue & 0xffff;
1812
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001813 tmpInst.setOpcode(Mips::LUi);
Toma Tabacu137d90a2015-04-28 12:04:53 +00001814 tmpInst.addOperand(MCOperand::CreateReg(Reg));
Toma Tabacu79588102015-04-29 10:19:56 +00001815 tmpInst.addOperand(MCOperand::CreateImm(Bits63To48));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001816 Instructions.push_back(tmpInst);
Toma Tabacua2861db2015-05-01 10:26:47 +00001817 createLShiftOri<0>(Bits47To32, Reg, IDLoc, Instructions);
1818
1819 // When Bits31To16 is 0, do a left shift of 32 bits instead of doing
1820 // two left shifts of 16 bits.
1821 if (Bits31To16 == 0) {
1822 createLShiftOri<32>(Bits15To0, Reg, IDLoc, Instructions);
1823 } else {
1824 createLShiftOri<16>(Bits31To16, Reg, IDLoc, Instructions);
1825 createLShiftOri<16>(Bits15To0, Reg, IDLoc, Instructions);
1826 }
Jack Carter30a59822012-10-04 04:03:53 +00001827 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001828 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001829}
Jack Carter92995f12012-10-06 00:53:28 +00001830
Matheus Almeida3813d572014-06-19 14:39:14 +00001831bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001832MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1833 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001834 MCInst tmpInst;
1835 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001836 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1837 "expected immediate operand kind");
1838 if (!ImmOp.isImm()) {
1839 expandLoadAddressSym(Inst, IDLoc, Instructions);
1840 return false;
1841 }
Jack Carter543fdf82012-10-09 23:29:45 +00001842 const MCOperand &SrcRegOp = Inst.getOperand(1);
1843 assert(SrcRegOp.isReg() && "expected register operand kind");
1844 const MCOperand &DstRegOp = Inst.getOperand(0);
1845 assert(DstRegOp.isReg() && "expected register operand kind");
1846 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001847 if (-32768 <= ImmValue && ImmValue <= 65535) {
1848 // For -32768 <= j <= 65535.
1849 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001850 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001851 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1852 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1853 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1854 Instructions.push_back(tmpInst);
1855 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001856 // For any other value of j that is representable as a 32-bit integer.
1857 // la d,j(s) => lui d,hi16(j)
1858 // ori d,d,lo16(j)
1859 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001860 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001861 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1862 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1863 Instructions.push_back(tmpInst);
1864 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001865 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001866 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1867 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1868 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1869 Instructions.push_back(tmpInst);
1870 tmpInst.clear();
1871 tmpInst.setOpcode(Mips::ADDu);
1872 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1873 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1874 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1875 Instructions.push_back(tmpInst);
1876 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001877 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001878}
1879
Matheus Almeida3813d572014-06-19 14:39:14 +00001880bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001881MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1882 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001883 MCInst tmpInst;
1884 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001885 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1886 "expected immediate operand kind");
1887 if (!ImmOp.isImm()) {
1888 expandLoadAddressSym(Inst, IDLoc, Instructions);
1889 return false;
1890 }
Jack Carter543fdf82012-10-09 23:29:45 +00001891 const MCOperand &RegOp = Inst.getOperand(0);
1892 assert(RegOp.isReg() && "expected register operand kind");
1893 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001894 if (-32768 <= ImmValue && ImmValue <= 65535) {
1895 // For -32768 <= j <= 65535.
1896 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001897 tmpInst.setOpcode(Mips::ADDiu);
1898 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001899 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001900 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1901 Instructions.push_back(tmpInst);
1902 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001903 // For any other value of j that is representable as a 32-bit integer.
1904 // la d,j => lui d,hi16(j)
1905 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001906 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001907 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1908 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1909 Instructions.push_back(tmpInst);
1910 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001911 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001912 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1913 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1914 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1915 Instructions.push_back(tmpInst);
1916 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001917 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001918}
1919
Toma Tabacu0d64b202014-08-14 10:29:17 +00001920void
1921MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1922 SmallVectorImpl<MCInst> &Instructions) {
1923 // FIXME: If we do have a valid at register to use, we should generate a
1924 // slightly shorter sequence here.
1925 MCInst tmpInst;
1926 int ExprOperandNo = 1;
1927 // Sometimes the assembly parser will get the immediate expression as
1928 // a $zero + an immediate.
1929 if (Inst.getNumOperands() == 3) {
1930 assert(Inst.getOperand(1).getReg() ==
1931 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1932 ExprOperandNo = 2;
1933 }
1934 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1935 assert(SymOp.isExpr() && "expected symbol operand kind");
1936 const MCOperand &RegOp = Inst.getOperand(0);
1937 unsigned RegNo = RegOp.getReg();
1938 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1939 const MCSymbolRefExpr *HiExpr =
1940 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1941 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1942 const MCSymbolRefExpr *LoExpr =
1943 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1944 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1945 if (isGP64bit()) {
1946 // If it's a 64-bit architecture, expand to:
1947 // la d,sym => lui d,highest(sym)
1948 // ori d,d,higher(sym)
1949 // dsll d,d,16
1950 // ori d,d,hi16(sym)
1951 // dsll d,d,16
1952 // ori d,d,lo16(sym)
1953 const MCSymbolRefExpr *HighestExpr =
1954 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1955 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1956 const MCSymbolRefExpr *HigherExpr =
1957 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1958 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1959
1960 tmpInst.setOpcode(Mips::LUi);
1961 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1962 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1963 Instructions.push_back(tmpInst);
1964
Toma Tabacua2861db2015-05-01 10:26:47 +00001965 createLShiftOri<0>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1966 Instructions);
1967 createLShiftOri<16>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00001968 Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001969 createLShiftOri<16>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00001970 Instructions);
1971 } else {
1972 // Otherwise, expand to:
1973 // la d,sym => lui d,hi16(sym)
1974 // ori d,d,lo16(sym)
1975 tmpInst.setOpcode(Mips::LUi);
1976 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1977 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1978 Instructions.push_back(tmpInst);
1979
Toma Tabacua2861db2015-05-01 10:26:47 +00001980 createLShiftOri<0>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1981 Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001982 }
1983}
1984
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00001985bool MipsAsmParser::expandUncondBranchMMPseudo(
1986 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00001987 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
1988 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001989
1990 MCOperand Offset = Inst.getOperand(0);
1991 if (Offset.isExpr()) {
1992 Inst.clear();
1993 Inst.setOpcode(Mips::BEQ_MM);
1994 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1995 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1996 Inst.addOperand(MCOperand::CreateExpr(Offset.getExpr()));
1997 } else {
1998 assert(Offset.isImm() && "expected immediate operand kind");
1999 if (isIntN(11, Offset.getImm())) {
2000 // If offset fits into 11 bits then this instruction becomes microMIPS
2001 // 16-bit unconditional branch instruction.
2002 Inst.setOpcode(Mips::B16_MM);
2003 } else {
2004 if (!isIntN(17, Offset.getImm()))
2005 Error(IDLoc, "branch target out of range");
2006 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2007 Error(IDLoc, "branch to misaligned address");
2008 Inst.clear();
2009 Inst.setOpcode(Mips::BEQ_MM);
2010 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2011 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2012 Inst.addOperand(MCOperand::CreateImm(Offset.getImm()));
2013 }
2014 }
2015 Instructions.push_back(Inst);
2016
Toma Tabacu234482a2015-03-16 12:03:39 +00002017 // If .set reorder is active, emit a NOP after the branch instruction.
2018 if (AssemblerOptions.back()->isReorder())
2019 createNop(true, IDLoc, Instructions);
2020
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002021 return false;
2022}
2023
Jack Carter9e65aa32013-03-22 00:05:30 +00002024void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002025 SmallVectorImpl<MCInst> &Instructions,
2026 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002027 const MCSymbolRefExpr *SR;
2028 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00002029 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002030 const MCExpr *ExprOffset;
2031 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002032 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002033 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2034 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002035 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002036 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2037 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002038 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002039 if (isImmOpnd) {
2040 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2041 ImmOffset = Inst.getOperand(2).getImm();
2042 LoOffset = ImmOffset & 0x0000ffff;
2043 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002044 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002045 if (LoOffset & 0x8000)
2046 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002047 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002048 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002049 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002050 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002051 // These are some of the types of expansions we perform here:
2052 // 1) lw $8, sym => lui $8, %hi(sym)
2053 // lw $8, %lo(sym)($8)
2054 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2055 // add $8, $8, $9
2056 // lw $8, %lo(offset)($9)
2057 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2058 // add $at, $at, $8
2059 // lw $8, %lo(offset)($at)
2060 // 4) sw $8, sym => lui $at, %hi(sym)
2061 // sw $8, %lo(sym)($at)
2062 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2063 // add $at, $at, $8
2064 // sw $8, %lo(offset)($at)
2065 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2066 // ldc1 $f0, %lo(sym)($at)
2067 //
2068 // For load instructions we can use the destination register as a temporary
2069 // if base and dst are different (examples 1 and 2) and if the base register
2070 // is general purpose otherwise we must use $at (example 6) and error if it's
2071 // not available. For stores we must use $at (examples 4 and 5) because we
2072 // must not clobber the source register setting up the offset.
2073 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2074 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2075 unsigned RegClassIDOp0 =
2076 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2077 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2078 (RegClassIDOp0 == Mips::GPR64RegClassID);
2079 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002080 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002081 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002082 // At this point we need AT to perform the expansions and we exit if it is
2083 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002084 TmpRegNum = getATReg(IDLoc);
2085 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002086 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002087 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002088
Jack Carter9e65aa32013-03-22 00:05:30 +00002089 TempInst.setOpcode(Mips::LUi);
2090 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2091 if (isImmOpnd)
2092 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
2093 else {
2094 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002095 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00002096 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
2097 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
2098 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00002099 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002100 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002101 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00002102 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002103 }
2104 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002105 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002106 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002107 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002108 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002109 // Add temp register to base.
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002110 if (BaseRegNum != Mips::ZERO) {
2111 TempInst.setOpcode(Mips::ADDu);
2112 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2113 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2114 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
2115 Instructions.push_back(TempInst);
2116 TempInst.clear();
2117 }
Alp Tokercb402912014-01-24 17:20:08 +00002118 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002119 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002120 TempInst.setOpcode(Inst.getOpcode());
2121 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
2122 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2123 if (isImmOpnd)
2124 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
2125 else {
2126 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002127 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
2128 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
2129 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00002130 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002131 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002132 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00002133 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002134 }
2135 }
2136 Instructions.push_back(TempInst);
2137 TempInst.clear();
2138}
2139
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002140bool
2141MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2142 SmallVectorImpl<MCInst> &Instructions) {
2143 unsigned OpNum = Inst.getNumOperands();
2144 unsigned Opcode = Inst.getOpcode();
2145 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2146
2147 assert (Inst.getOperand(OpNum - 1).isImm() &&
2148 Inst.getOperand(OpNum - 2).isReg() &&
2149 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2150
2151 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2152 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2153 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2154 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2155 // It can be implemented as SWM16 or LWM16 instruction.
2156 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2157
2158 Inst.setOpcode(NewOpcode);
2159 Instructions.push_back(Inst);
2160 return false;
2161}
2162
Toma Tabacu234482a2015-03-16 12:03:39 +00002163void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
2164 SmallVectorImpl<MCInst> &Instructions) {
2165 MCInst NopInst;
2166 if (hasShortDelaySlot) {
2167 NopInst.setOpcode(Mips::MOVE16_MM);
2168 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2169 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2170 } else {
2171 NopInst.setOpcode(Mips::SLL);
2172 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2173 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2174 NopInst.addOperand(MCOperand::CreateImm(0));
2175 }
2176 Instructions.push_back(NopInst);
2177}
2178
Matheus Almeida595fcab2014-06-11 15:05:56 +00002179unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
2180 // As described by the Mips32r2 spec, the registers Rd and Rs for
2181 // jalr.hb must be different.
2182 unsigned Opcode = Inst.getOpcode();
2183
2184 if (Opcode == Mips::JALR_HB &&
2185 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
2186 return Match_RequiresDifferentSrcAndDst;
2187
2188 return Match_Success;
2189}
2190
David Blaikie960ea3f2014-06-08 16:18:35 +00002191bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
2192 OperandVector &Operands,
2193 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00002194 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00002195 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00002196
Jack Carterb4dbc172012-09-05 23:34:03 +00002197 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00002198 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00002199 unsigned MatchResult =
2200 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00002201
2202 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002203 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002204 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00002205 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00002206 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00002207 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00002208 return false;
2209 }
2210 case Match_MissingFeature:
2211 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
2212 return true;
2213 case Match_InvalidOperand: {
2214 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00002215 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002216 if (ErrorInfo >= Operands.size())
2217 return Error(IDLoc, "too few operands for instruction");
2218
David Blaikie960ea3f2014-06-08 16:18:35 +00002219 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00002220 if (ErrorLoc == SMLoc())
2221 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00002222 }
2223
2224 return Error(ErrorLoc, "invalid operand for instruction");
2225 }
2226 case Match_MnemonicFail:
2227 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00002228 case Match_RequiresDifferentSrcAndDst:
2229 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00002230 }
Craig Topper589ceee2015-01-03 08:16:34 +00002231
2232 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00002233}
2234
Toma Tabacud9d344b2015-04-27 14:05:04 +00002235void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
2236 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
2237 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
2238 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002239}
2240
Daniel Sandersef638fe2014-10-03 15:37:37 +00002241void
2242MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
2243 SMRange Range, bool ShowColors) {
2244 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00002245 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00002246 ShowColors);
2247}
2248
Jack Carter1ac53222013-02-20 23:11:17 +00002249int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002250 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002251
Vladimir Medic4c299852013-11-06 11:27:05 +00002252 CC = StringSwitch<unsigned>(Name)
2253 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002254 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00002255 .Case("a0", 4)
2256 .Case("a1", 5)
2257 .Case("a2", 6)
2258 .Case("a3", 7)
2259 .Case("v0", 2)
2260 .Case("v1", 3)
2261 .Case("s0", 16)
2262 .Case("s1", 17)
2263 .Case("s2", 18)
2264 .Case("s3", 19)
2265 .Case("s4", 20)
2266 .Case("s5", 21)
2267 .Case("s6", 22)
2268 .Case("s7", 23)
2269 .Case("k0", 26)
2270 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002271 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00002272 .Case("sp", 29)
2273 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002274 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00002275 .Case("ra", 31)
2276 .Case("t0", 8)
2277 .Case("t1", 9)
2278 .Case("t2", 10)
2279 .Case("t3", 11)
2280 .Case("t4", 12)
2281 .Case("t5", 13)
2282 .Case("t6", 14)
2283 .Case("t7", 15)
2284 .Case("t8", 24)
2285 .Case("t9", 25)
2286 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002287
Toma Tabacufda445c2014-09-15 15:33:01 +00002288 if (!(isABI_N32() || isABI_N64()))
2289 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002290
Daniel Sandersef638fe2014-10-03 15:37:37 +00002291 if (12 <= CC && CC <= 15) {
2292 // Name is one of t4-t7
2293 AsmToken RegTok = getLexer().peekTok();
2294 SMRange RegRange = RegTok.getLocRange();
2295
2296 StringRef FixedName = StringSwitch<StringRef>(Name)
2297 .Case("t4", "t0")
2298 .Case("t5", "t1")
2299 .Case("t6", "t2")
2300 .Case("t7", "t3")
2301 .Default("");
2302 assert(FixedName != "" && "Register name is not one of t4-t7.");
2303
2304 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
2305 "Did you mean $" + FixedName + "?", RegRange);
2306 }
2307
Toma Tabacufda445c2014-09-15 15:33:01 +00002308 // Although SGI documentation just cuts out t0-t3 for n32/n64,
2309 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
2310 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
2311 if (8 <= CC && CC <= 11)
2312 CC += 4;
2313
2314 if (CC == -1)
2315 CC = StringSwitch<unsigned>(Name)
2316 .Case("a4", 8)
2317 .Case("a5", 9)
2318 .Case("a6", 10)
2319 .Case("a7", 11)
2320 .Case("kt0", 26)
2321 .Case("kt1", 27)
2322 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002323
2324 return CC;
2325}
Jack Carterd0bd6422013-04-18 00:41:53 +00002326
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002327int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
2328 int CC;
2329
2330 CC = StringSwitch<unsigned>(Name)
2331 .Case("hwr_cpunum", 0)
2332 .Case("hwr_synci_step", 1)
2333 .Case("hwr_cc", 2)
2334 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00002335 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002336 .Default(-1);
2337
2338 return CC;
2339}
2340
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002341int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002342
Jack Cartera63b16a2012-09-07 00:23:42 +00002343 if (Name[0] == 'f') {
2344 StringRef NumString = Name.substr(1);
2345 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002346 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002347 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002348 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00002349 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002350 return IntVal;
2351 }
2352 return -1;
2353}
Jack Cartera63b16a2012-09-07 00:23:42 +00002354
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002355int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
2356
2357 if (Name.startswith("fcc")) {
2358 StringRef NumString = Name.substr(3);
2359 unsigned IntVal;
2360 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002361 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002362 if (IntVal > 7) // There are only 8 fcc registers.
2363 return -1;
2364 return IntVal;
2365 }
2366 return -1;
2367}
2368
2369int MipsAsmParser::matchACRegisterName(StringRef Name) {
2370
Akira Hatanaka274d24c2013-08-14 01:15:52 +00002371 if (Name.startswith("ac")) {
2372 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002373 unsigned IntVal;
2374 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002375 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002376 if (IntVal > 3) // There are only 3 acc registers.
2377 return -1;
2378 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00002379 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002380 return -1;
2381}
Jack Carterd0bd6422013-04-18 00:41:53 +00002382
Jack Carter5dc8ac92013-09-25 23:50:44 +00002383int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
2384 unsigned IntVal;
2385
2386 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2387 return -1;
2388
2389 if (IntVal > 31)
2390 return -1;
2391
2392 return IntVal;
2393}
2394
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002395int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
2396 int CC;
2397
2398 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00002399 .Case("msair", 0)
2400 .Case("msacsr", 1)
2401 .Case("msaaccess", 2)
2402 .Case("msasave", 3)
2403 .Case("msamodify", 4)
2404 .Case("msarequest", 5)
2405 .Case("msamap", 6)
2406 .Case("msaunmap", 7)
2407 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002408
2409 return CC;
2410}
2411
Toma Tabacu89a712b2015-04-15 10:48:56 +00002412unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00002413 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00002414 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002415 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00002416 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00002417 return 0;
2418 }
2419 unsigned AT = getReg(
2420 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00002421 return AT;
2422}
Jack Carter0b744b32012-10-04 02:29:46 +00002423
Jack Carterd0bd6422013-04-18 00:41:53 +00002424unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00002425 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00002426}
2427
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002428unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002429 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00002430 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002431}
2432
Jack Carter873c7242013-01-12 01:03:14 +00002433int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002434 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00002435 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00002436 return -1;
2437
Jack Carter873c7242013-01-12 01:03:14 +00002438 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00002439}
2440
Toma Tabacu13964452014-09-04 13:23:44 +00002441bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002442 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002443 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002444
Jack Carter30a59822012-10-04 04:03:53 +00002445 // Check if the current operand has a custom associated parser, if so, try to
2446 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00002447 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2448 if (ResTy == MatchOperand_Success)
2449 return false;
2450 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2451 // there was a match, but an error occurred, in which case, just return that
2452 // the operand parsing failed.
2453 if (ResTy == MatchOperand_ParseFail)
2454 return true;
2455
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002456 DEBUG(dbgs() << ".. Generic Parser\n");
2457
Jack Carterb4dbc172012-09-05 23:34:03 +00002458 switch (getLexer().getKind()) {
2459 default:
2460 Error(Parser.getTok().getLoc(), "unexpected token in operand");
2461 return true;
2462 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002463 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00002464 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00002465
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002466 // Almost all registers have been parsed by custom parsers. There is only
2467 // one exception to this. $zero (and it's alias $0) will reach this point
2468 // for div, divu, and similar instructions because it is not an operand
2469 // to the instruction definition but an explicit register. Special case
2470 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00002471 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00002472 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002473
Jack Carterd0bd6422013-04-18 00:41:53 +00002474 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00002475 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002476 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00002477 return true;
2478
Jack Carter873c7242013-01-12 01:03:14 +00002479 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00002480 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00002481 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00002482 const MCExpr *Res =
2483 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00002484
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002485 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002486 return false;
2487 }
Vladimir Medic4c299852013-11-06 11:27:05 +00002488 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00002489 case AsmToken::LParen:
2490 case AsmToken::Minus:
2491 case AsmToken::Plus:
2492 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002493 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00002494 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002495 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002496 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002497 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00002498 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00002499 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002500 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002501 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002502 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00002503 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00002504 return true;
2505
Jack Carter873c7242013-01-12 01:03:14 +00002506 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2507
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002508 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00002509 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002510 } // case AsmToken::Percent
2511 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00002512 return true;
2513}
2514
Vladimir Medic4c299852013-11-06 11:27:05 +00002515const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00002516 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00002517 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00002518 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002519 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00002520 // It's a constant, evaluate reloc value.
2521 int16_t Val;
2522 switch (getVariantKind(RelocStr)) {
2523 case MCSymbolRefExpr::VK_Mips_ABS_LO:
2524 // Get the 1st 16-bits.
2525 Val = MCE->getValue() & 0xffff;
2526 break;
2527 case MCSymbolRefExpr::VK_Mips_ABS_HI:
2528 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2529 // 16 bits being negative.
2530 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2531 break;
2532 case MCSymbolRefExpr::VK_Mips_HIGHER:
2533 // Get the 3rd 16-bits.
2534 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2535 break;
2536 case MCSymbolRefExpr::VK_Mips_HIGHEST:
2537 // Get the 4th 16-bits.
2538 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2539 break;
2540 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00002541 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00002542 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00002543 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002544 }
2545
Jack Carterb5cf5902013-04-17 00:18:04 +00002546 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002547 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00002548 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00002549 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00002550 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002551 return Res;
2552 }
2553
2554 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00002555 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2556
Sasa Stankovic06c47802014-04-03 10:37:45 +00002557 // Try to create target expression.
2558 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
2559 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002560
Jack Carterd0bd6422013-04-18 00:41:53 +00002561 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2562 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00002563 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
2564 return Res;
2565 }
2566
2567 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002568 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
2569 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
2570 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002571 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002572 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002573 return Expr;
2574}
2575
2576bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2577
2578 switch (Expr->getKind()) {
2579 case MCExpr::Constant:
2580 return true;
2581 case MCExpr::SymbolRef:
2582 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2583 case MCExpr::Binary:
2584 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2585 if (!isEvaluated(BE->getLHS()))
2586 return false;
2587 return isEvaluated(BE->getRHS());
2588 }
2589 case MCExpr::Unary:
2590 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002591 case MCExpr::Target:
2592 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002593 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002594 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002595}
Jack Carterd0bd6422013-04-18 00:41:53 +00002596
Jack Carterb5cf5902013-04-17 00:18:04 +00002597bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002598 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00002599 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002600 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002601 if (Tok.isNot(AsmToken::Identifier))
2602 return true;
2603
Yaron Keren075759a2015-03-30 15:42:36 +00002604 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00002605
Jack Carterd0bd6422013-04-18 00:41:53 +00002606 Parser.Lex(); // Eat the identifier.
2607 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002608 const MCExpr *IdVal;
2609 SMLoc EndLoc;
2610
2611 if (getLexer().getKind() == AsmToken::LParen) {
2612 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002613 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002614 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002615 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002616 const AsmToken &nextTok = Parser.getTok();
2617 if (nextTok.isNot(AsmToken::Identifier))
2618 return true;
2619 Str += "(%";
2620 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002621 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002622 if (getLexer().getKind() != AsmToken::LParen)
2623 return true;
2624 } else
2625 break;
2626 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002627 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002628 return true;
2629
2630 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002631 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002632
2633 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002634 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002635
Jack Carterd0bd6422013-04-18 00:41:53 +00002636 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002637 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002638}
2639
Jack Carterb4dbc172012-09-05 23:34:03 +00002640bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2641 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002642 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002643 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002644 if (ResTy == MatchOperand_Success) {
2645 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002646 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002647 StartLoc = Operand.getStartLoc();
2648 EndLoc = Operand.getEndLoc();
2649
2650 // AFAIK, we only support numeric registers and named GPR's in CFI
2651 // directives.
2652 // Don't worry about eating tokens before failing. Using an unrecognised
2653 // register is a parse error.
2654 if (Operand.isGPRAsmReg()) {
2655 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002656 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002657 }
2658
2659 return (RegNo == (unsigned)-1);
2660 }
2661
2662 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002663 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002664}
2665
Jack Carterb5cf5902013-04-17 00:18:04 +00002666bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002667 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00002668 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002669 bool Result = true;
2670
2671 while (getLexer().getKind() == AsmToken::LParen)
2672 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002673
Jack Carterd0bd6422013-04-18 00:41:53 +00002674 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002675 default:
2676 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002677 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002678 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002679 case AsmToken::Integer:
2680 case AsmToken::Minus:
2681 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002682 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002683 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002684 else
2685 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002686 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002687 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002688 break;
Jack Carter873c7242013-01-12 01:03:14 +00002689 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002690 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002691 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002692 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002693}
2694
David Blaikie960ea3f2014-06-08 16:18:35 +00002695MipsAsmParser::OperandMatchResultTy
2696MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002697 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002698 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002699 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002700 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002701 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002702 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002703 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002704 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002705
Jack Carterb5cf5902013-04-17 00:18:04 +00002706 if (getLexer().getKind() == AsmToken::LParen) {
2707 Parser.Lex();
2708 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002709 }
2710
Jack Carterb5cf5902013-04-17 00:18:04 +00002711 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002712 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002713 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002714
Jack Carterd0bd6422013-04-18 00:41:53 +00002715 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002716 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002717 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2718 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002719 SMLoc E =
2720 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002721 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002722 return MatchOperand_Success;
2723 }
2724 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002725 SMLoc E =
2726 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002727
Jack Carterd0bd6422013-04-18 00:41:53 +00002728 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002729 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002730 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002731 S, E, *this);
2732 Operands.push_back(
2733 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002734 return MatchOperand_Success;
2735 }
2736 Error(Parser.getTok().getLoc(), "'(' expected");
2737 return MatchOperand_ParseFail;
2738 }
2739
Jack Carterd0bd6422013-04-18 00:41:53 +00002740 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002741 }
2742
Toma Tabacu13964452014-09-04 13:23:44 +00002743 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002744 if (Res != MatchOperand_Success)
2745 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002746
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002747 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002748 Error(Parser.getTok().getLoc(), "')' expected");
2749 return MatchOperand_ParseFail;
2750 }
2751
Jack Carter873c7242013-01-12 01:03:14 +00002752 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2753
Jack Carterd0bd6422013-04-18 00:41:53 +00002754 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002755
Craig Topper062a2ba2014-04-25 05:30:21 +00002756 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002757 IdVal = MCConstantExpr::Create(0, getContext());
2758
Jack Carterd0bd6422013-04-18 00:41:53 +00002759 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002760 std::unique_ptr<MipsOperand> op(
2761 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002762 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002763 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002764 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002765 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002766 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2767 int64_t Imm;
2768 if (IdVal->EvaluateAsAbsolute(Imm))
2769 IdVal = MCConstantExpr::Create(Imm, getContext());
2770 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2771 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2772 getContext());
2773 }
2774
David Blaikie960ea3f2014-06-08 16:18:35 +00002775 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002776 return MatchOperand_Success;
2777}
2778
David Blaikie960ea3f2014-06-08 16:18:35 +00002779bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002780 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00002781 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2782 if (Sym) {
2783 SMLoc S = Parser.getTok().getLoc();
2784 const MCExpr *Expr;
2785 if (Sym->isVariable())
2786 Expr = Sym->getVariableValue();
2787 else
2788 return false;
2789 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002790 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002791 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002792 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002793 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002794 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002795 if (ResTy == MatchOperand_Success) {
2796 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002797 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002798 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002799 llvm_unreachable("Should never ParseFail");
2800 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002801 }
2802 } else if (Expr->getKind() == MCExpr::Constant) {
2803 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002804 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002805 Operands.push_back(
2806 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002807 return true;
2808 }
2809 }
2810 return false;
2811}
Jack Carterd0bd6422013-04-18 00:41:53 +00002812
Jack Carter873c7242013-01-12 01:03:14 +00002813MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002814MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002815 StringRef Identifier,
2816 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002817 int Index = matchCPURegisterName(Identifier);
2818 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002819 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002820 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2821 return MatchOperand_Success;
2822 }
2823
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002824 Index = matchHWRegsRegisterName(Identifier);
2825 if (Index != -1) {
2826 Operands.push_back(MipsOperand::createHWRegsReg(
2827 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2828 return MatchOperand_Success;
2829 }
2830
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002831 Index = matchFPURegisterName(Identifier);
2832 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002833 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002834 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2835 return MatchOperand_Success;
2836 }
2837
2838 Index = matchFCCRegisterName(Identifier);
2839 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002840 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002841 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2842 return MatchOperand_Success;
2843 }
2844
2845 Index = matchACRegisterName(Identifier);
2846 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002847 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002848 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2849 return MatchOperand_Success;
2850 }
2851
2852 Index = matchMSA128RegisterName(Identifier);
2853 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002854 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002855 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2856 return MatchOperand_Success;
2857 }
2858
2859 Index = matchMSA128CtrlRegisterName(Identifier);
2860 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002861 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002862 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2863 return MatchOperand_Success;
2864 }
2865
2866 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002867}
2868
2869MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002870MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002871 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00002872 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002873
2874 if (Token.is(AsmToken::Identifier)) {
2875 DEBUG(dbgs() << ".. identifier\n");
2876 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002877 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002878 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002879 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002880 } else if (Token.is(AsmToken::Integer)) {
2881 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002882 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002883 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2884 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002885 return MatchOperand_Success;
2886 }
2887
2888 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2889
2890 return MatchOperand_NoMatch;
2891}
2892
David Blaikie960ea3f2014-06-08 16:18:35 +00002893MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002894MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002895 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002896 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002897
2898 auto Token = Parser.getTok();
2899
2900 SMLoc S = Token.getLoc();
2901
2902 if (Token.isNot(AsmToken::Dollar)) {
2903 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2904 if (Token.is(AsmToken::Identifier)) {
2905 if (searchSymbolAlias(Operands))
2906 return MatchOperand_Success;
2907 }
2908 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2909 return MatchOperand_NoMatch;
2910 }
2911 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002912
Toma Tabacu13964452014-09-04 13:23:44 +00002913 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002914 if (ResTy == MatchOperand_Success) {
2915 Parser.Lex(); // $
2916 Parser.Lex(); // identifier
2917 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002918 return ResTy;
2919}
2920
2921MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002922MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002923 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002924 switch (getLexer().getKind()) {
2925 default:
2926 return MatchOperand_NoMatch;
2927 case AsmToken::LParen:
2928 case AsmToken::Minus:
2929 case AsmToken::Plus:
2930 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002931 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002932 case AsmToken::String:
2933 break;
2934 }
2935
2936 const MCExpr *IdVal;
2937 SMLoc S = Parser.getTok().getLoc();
2938 if (getParser().parseExpression(IdVal))
2939 return MatchOperand_ParseFail;
2940
2941 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2942 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2943 return MatchOperand_Success;
2944}
2945
David Blaikie960ea3f2014-06-08 16:18:35 +00002946MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002947MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002948 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002949 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002950
2951 SMLoc S = getLexer().getLoc();
2952
2953 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002954 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002955 if (ResTy != MatchOperand_NoMatch)
2956 return ResTy;
2957
Daniel Sanders315386c2014-04-01 10:40:14 +00002958 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002959 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002960 if (ResTy != MatchOperand_NoMatch)
2961 return ResTy;
2962
Daniel Sandersffd84362014-04-01 10:41:48 +00002963 const MCExpr *Expr = nullptr;
2964 if (Parser.parseExpression(Expr)) {
2965 // We have no way of knowing if a symbol was consumed so we must ParseFail
2966 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002967 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002968 Operands.push_back(
2969 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002970 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002971}
2972
Vladimir Medic2b953d02013-10-01 09:48:56 +00002973MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002974MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002975 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00002976 const MCExpr *IdVal;
2977 // If the first token is '$' we may have register operand.
2978 if (Parser.getTok().is(AsmToken::Dollar))
2979 return MatchOperand_NoMatch;
2980 SMLoc S = Parser.getTok().getLoc();
2981 if (getParser().parseExpression(IdVal))
2982 return MatchOperand_ParseFail;
2983 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002984 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002985 int64_t Val = MCE->getValue();
2986 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2987 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002988 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002989 return MatchOperand_Success;
2990}
2991
Matheus Almeida779c5932013-11-18 12:32:49 +00002992MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002993MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002994 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00002995 switch (getLexer().getKind()) {
2996 default:
2997 return MatchOperand_NoMatch;
2998 case AsmToken::LParen:
2999 case AsmToken::Plus:
3000 case AsmToken::Minus:
3001 case AsmToken::Integer:
3002 break;
3003 }
3004
3005 const MCExpr *Expr;
3006 SMLoc S = Parser.getTok().getLoc();
3007
3008 if (getParser().parseExpression(Expr))
3009 return MatchOperand_ParseFail;
3010
3011 int64_t Val;
3012 if (!Expr->EvaluateAsAbsolute(Val)) {
3013 Error(S, "expected immediate value");
3014 return MatchOperand_ParseFail;
3015 }
3016
3017 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
3018 // and because the CPU always adds one to the immediate field, the allowed
3019 // range becomes 1..4. We'll only check the range here and will deal
3020 // with the addition/subtraction when actually decoding/encoding
3021 // the instruction.
3022 if (Val < 1 || Val > 4) {
3023 Error(S, "immediate not in range (1..4)");
3024 return MatchOperand_ParseFail;
3025 }
3026
Jack Carter3b2c96e2014-01-22 23:31:38 +00003027 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003028 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00003029 return MatchOperand_Success;
3030}
3031
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00003032MipsAsmParser::OperandMatchResultTy
3033MipsAsmParser::parseRegisterList(OperandVector &Operands) {
3034 MCAsmParser &Parser = getParser();
3035 SmallVector<unsigned, 10> Regs;
3036 unsigned RegNo;
3037 unsigned PrevReg = Mips::NoRegister;
3038 bool RegRange = false;
3039 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3040
3041 if (Parser.getTok().isNot(AsmToken::Dollar))
3042 return MatchOperand_ParseFail;
3043
3044 SMLoc S = Parser.getTok().getLoc();
3045 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
3046 SMLoc E = getLexer().getLoc();
3047 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
3048 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
3049 if (RegRange) {
3050 // Remove last register operand because registers from register range
3051 // should be inserted first.
3052 if (RegNo == Mips::RA) {
3053 Regs.push_back(RegNo);
3054 } else {
3055 unsigned TmpReg = PrevReg + 1;
3056 while (TmpReg <= RegNo) {
3057 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
3058 Error(E, "invalid register operand");
3059 return MatchOperand_ParseFail;
3060 }
3061
3062 PrevReg = TmpReg;
3063 Regs.push_back(TmpReg++);
3064 }
3065 }
3066
3067 RegRange = false;
3068 } else {
3069 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
3070 (RegNo != Mips::RA)) {
3071 Error(E, "$16 or $31 expected");
3072 return MatchOperand_ParseFail;
3073 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
3074 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3075 Error(E, "invalid register operand");
3076 return MatchOperand_ParseFail;
3077 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
3078 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3079 Error(E, "consecutive register numbers expected");
3080 return MatchOperand_ParseFail;
3081 }
3082
3083 Regs.push_back(RegNo);
3084 }
3085
3086 if (Parser.getTok().is(AsmToken::Minus))
3087 RegRange = true;
3088
3089 if (!Parser.getTok().isNot(AsmToken::Minus) &&
3090 !Parser.getTok().isNot(AsmToken::Comma)) {
3091 Error(E, "',' or '-' expected");
3092 return MatchOperand_ParseFail;
3093 }
3094
3095 Lex(); // Consume comma or minus
3096 if (Parser.getTok().isNot(AsmToken::Dollar))
3097 break;
3098
3099 PrevReg = RegNo;
3100 }
3101
3102 SMLoc E = Parser.getTok().getLoc();
3103 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3104 parseMemOperand(Operands);
3105 return MatchOperand_Success;
3106}
3107
Zoran Jovanovic2deca342014-12-16 14:59:10 +00003108MipsAsmParser::OperandMatchResultTy
3109MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
3110 MCAsmParser &Parser = getParser();
3111
3112 SMLoc S = Parser.getTok().getLoc();
3113 if (parseAnyRegister(Operands) != MatchOperand_Success)
3114 return MatchOperand_ParseFail;
3115
3116 SMLoc E = Parser.getTok().getLoc();
3117 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
3118 unsigned Reg = Op.getGPR32Reg();
3119 Operands.pop_back();
3120 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
3121 return MatchOperand_Success;
3122}
3123
Zoran Jovanovic41688672015-02-10 16:36:20 +00003124MipsAsmParser::OperandMatchResultTy
3125MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
3126 MCAsmParser &Parser = getParser();
3127 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3128 SmallVector<unsigned, 10> Regs;
3129
3130 if (Parser.getTok().isNot(AsmToken::Dollar))
3131 return MatchOperand_ParseFail;
3132
3133 SMLoc S = Parser.getTok().getLoc();
3134
3135 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3136 return MatchOperand_ParseFail;
3137
3138 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3139 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3140 Regs.push_back(RegNo);
3141
3142 SMLoc E = Parser.getTok().getLoc();
3143 if (Parser.getTok().isNot(AsmToken::Comma)) {
3144 Error(E, "',' expected");
3145 return MatchOperand_ParseFail;
3146 }
3147
3148 // Remove comma.
3149 Parser.Lex();
3150
3151 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3152 return MatchOperand_ParseFail;
3153
3154 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3155 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3156 Regs.push_back(RegNo);
3157
3158 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3159
3160 return MatchOperand_Success;
3161}
3162
Jack Carterdc1e35d2012-09-06 20:00:02 +00003163MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
3164
Vladimir Medic4c299852013-11-06 11:27:05 +00003165 MCSymbolRefExpr::VariantKind VK =
3166 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
3167 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
3168 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
3169 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
3170 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
3171 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
3172 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
3173 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
3174 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
3175 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
3176 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
3177 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
3178 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
3179 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
3180 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
3181 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
3182 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
3183 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00003184 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
3185 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
3186 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
3187 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
3188 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
3189 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00003190 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
3191 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00003192 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003193
Matheus Almeida2852af82014-04-22 10:15:54 +00003194 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00003195
Jack Carterdc1e35d2012-09-06 20:00:02 +00003196 return VK;
3197}
Jack Cartera63b16a2012-09-07 00:23:42 +00003198
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003199/// Sometimes (i.e. load/stores) the operand may be followed immediately by
3200/// either this.
3201/// ::= '(', register, ')'
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::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003205 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003206 if (getLexer().is(AsmToken::LParen)) {
3207 Operands.push_back(
3208 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
3209 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003210 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003211 SMLoc Loc = getLexer().getLoc();
3212 Parser.eatToEndOfStatement();
3213 return Error(Loc, "unexpected token in argument list");
3214 }
3215 if (Parser.getTok().isNot(AsmToken::RParen)) {
3216 SMLoc Loc = getLexer().getLoc();
3217 Parser.eatToEndOfStatement();
3218 return Error(Loc, "unexpected token, expected ')'");
3219 }
3220 Operands.push_back(
3221 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
3222 Parser.Lex();
3223 }
3224 return false;
3225}
3226
3227/// Sometimes (i.e. in MSA) the operand may be followed immediately by
3228/// either one of these.
3229/// ::= '[', register, ']'
3230/// ::= '[', integer, ']'
3231/// handle it before we iterate so we don't get tripped up by the lack of
3232/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003233bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00003234 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003235 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003236 if (getLexer().is(AsmToken::LBrac)) {
3237 Operands.push_back(
3238 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
3239 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003240 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003241 SMLoc Loc = getLexer().getLoc();
3242 Parser.eatToEndOfStatement();
3243 return Error(Loc, "unexpected token in argument list");
3244 }
3245 if (Parser.getTok().isNot(AsmToken::RBrac)) {
3246 SMLoc Loc = getLexer().getLoc();
3247 Parser.eatToEndOfStatement();
3248 return Error(Loc, "unexpected token, expected ']'");
3249 }
3250 Operands.push_back(
3251 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
3252 Parser.Lex();
3253 }
3254 return false;
3255}
3256
David Blaikie960ea3f2014-06-08 16:18:35 +00003257bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
3258 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003259 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003260 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003261
3262 // We have reached first instruction, module directive are now forbidden.
3263 getTargetStreamer().forbidModuleDirective();
3264
Vladimir Medic74593e62013-07-17 15:00:42 +00003265 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00003266 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00003267 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00003268 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00003269 }
Vladimir Medic64828a12013-07-16 10:07:14 +00003270 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003271 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003272
3273 // Read the remaining operands.
3274 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3275 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003276 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003277 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003278 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003279 return Error(Loc, "unexpected token in argument list");
3280 }
Toma Tabacu13964452014-09-04 13:23:44 +00003281 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003282 return true;
3283 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00003284
Jack Carterd0bd6422013-04-18 00:41:53 +00003285 while (getLexer().is(AsmToken::Comma)) {
3286 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00003287 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003288 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003289 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003290 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003291 return Error(Loc, "unexpected token in argument list");
3292 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003293 // Parse bracket and parenthesis suffixes before we iterate
3294 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00003295 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003296 return true;
3297 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00003298 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003299 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003300 }
3301 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003302 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3303 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003304 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003305 return Error(Loc, "unexpected token in argument list");
3306 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003307 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00003308 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00003309}
3310
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003311bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003312 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003313 SMLoc Loc = getLexer().getLoc();
3314 Parser.eatToEndOfStatement();
3315 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00003316}
3317
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003318bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003319 return Error(Loc, ErrorMsg);
3320}
3321
Jack Carter0b744b32012-10-04 02:29:46 +00003322bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003323 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003324 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00003325
3326 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00003327 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00003328
3329 Parser.Lex(); // Eat "noat".
3330
Jack Carterd0bd6422013-04-18 00:41:53 +00003331 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003332 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003333 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003334 return false;
3335 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003336
3337 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003338 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003339 return false;
3340}
Jack Carterd0bd6422013-04-18 00:41:53 +00003341
Jack Carter0b744b32012-10-04 02:29:46 +00003342bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00003343 // Line can be: ".set at", which sets $at to $1
3344 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00003345 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00003346 Parser.Lex(); // Eat "at".
3347
Jack Carter0b744b32012-10-04 02:29:46 +00003348 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003349 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00003350 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00003351
3352 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003353 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003354 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00003355 }
3356
3357 if (getLexer().isNot(AsmToken::Equal)) {
3358 reportParseError("unexpected token, expected equals sign");
3359 return false;
3360 }
3361 Parser.Lex(); // Eat "=".
3362
3363 if (getLexer().isNot(AsmToken::Dollar)) {
3364 if (getLexer().is(AsmToken::EndOfStatement)) {
3365 reportParseError("no register specified");
3366 return false;
3367 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00003368 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00003369 return false;
3370 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003371 }
3372 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00003373
Toma Tabacu16a74492015-02-13 10:30:57 +00003374 // Find out what "reg" is.
3375 unsigned AtRegNo;
3376 const AsmToken &Reg = Parser.getTok();
3377 if (Reg.is(AsmToken::Identifier)) {
3378 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
3379 } else if (Reg.is(AsmToken::Integer)) {
3380 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00003381 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00003382 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00003383 return false;
3384 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003385
3386 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00003387 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003388 reportParseError("invalid register");
3389 return false;
3390 }
3391 Parser.Lex(); // Eat "reg".
3392
3393 // If this is not the end of the statement, report an error.
3394 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3395 reportParseError("unexpected token, expected end of statement");
3396 return false;
3397 }
3398
3399 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
3400
3401 Parser.Lex(); // Consume the EndOfStatement.
3402 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003403}
3404
3405bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003406 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003407 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003408 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003409 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003410 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003411 return false;
3412 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003413 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00003414 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003415 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003416 return false;
3417}
3418
3419bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003420 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003421 Parser.Lex();
3422 // If this is not the end of the statement, report an error.
3423 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003424 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003425 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003426 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003427 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00003428 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003429 Parser.Lex(); // Consume the EndOfStatement.
3430 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003431}
3432
3433bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003434 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003435 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003436 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003437 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003438 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003439 return false;
3440 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003441 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003442 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003443 return false;
3444}
3445
3446bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003447 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003448 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003449 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003450 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003451 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003452 return false;
3453 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003454 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00003455 reportParseError("`noreorder' must be set before `nomacro'");
3456 return false;
3457 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003458 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003459 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003460 return false;
3461}
Jack Carterd76b2372013-03-21 21:44:16 +00003462
Daniel Sanders44934432014-08-07 12:03:36 +00003463bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003464 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003465 Parser.Lex();
3466
3467 // If this is not the end of the statement, report an error.
3468 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003469 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003470
3471 setFeatureBits(Mips::FeatureMSA, "msa");
3472 getTargetStreamer().emitDirectiveSetMsa();
3473 return false;
3474}
3475
3476bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003477 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003478 Parser.Lex();
3479
3480 // If this is not the end of the statement, report an error.
3481 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003482 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003483
3484 clearFeatureBits(Mips::FeatureMSA, "msa");
3485 getTargetStreamer().emitDirectiveSetNoMsa();
3486 return false;
3487}
3488
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003489bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003490 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003491 Parser.Lex(); // Eat "nodsp".
3492
3493 // If this is not the end of the statement, report an error.
3494 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3495 reportParseError("unexpected token, expected end of statement");
3496 return false;
3497 }
3498
3499 clearFeatureBits(Mips::FeatureDSP, "dsp");
3500 getTargetStreamer().emitDirectiveSetNoDsp();
3501 return false;
3502}
3503
Toma Tabacucc2502d2014-11-04 17:18:07 +00003504bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003505 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003506 Parser.Lex(); // Eat "mips16".
3507
Jack Carter39536722014-01-22 23:08:42 +00003508 // If this is not the end of the statement, report an error.
3509 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003510 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00003511 return false;
3512 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00003513
3514 setFeatureBits(Mips::FeatureMips16, "mips16");
3515 getTargetStreamer().emitDirectiveSetMips16();
3516 Parser.Lex(); // Consume the EndOfStatement.
3517 return false;
3518}
3519
3520bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003521 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003522 Parser.Lex(); // Eat "nomips16".
3523
3524 // If this is not the end of the statement, report an error.
3525 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3526 reportParseError("unexpected token, expected end of statement");
3527 return false;
3528 }
3529
3530 clearFeatureBits(Mips::FeatureMips16, "mips16");
3531 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00003532 Parser.Lex(); // Consume the EndOfStatement.
3533 return false;
3534}
3535
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003536bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003537 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003538 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003539 // Line can be: .set fp=32
3540 // .set fp=xx
3541 // .set fp=64
3542 Parser.Lex(); // Eat fp token
3543 AsmToken Tok = Parser.getTok();
3544 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003545 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003546 return false;
3547 }
3548 Parser.Lex(); // Eat '=' token.
3549 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003550
3551 if (!parseFpABIValue(FpAbiVal, ".set"))
3552 return false;
3553
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003554 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003555 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003556 return false;
3557 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003558 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003559 Parser.Lex(); // Consume the EndOfStatement.
3560 return false;
3561}
3562
Toma Tabacu9db22db2014-09-09 10:15:38 +00003563bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003564 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003565 SMLoc Loc = getLexer().getLoc();
3566
3567 Parser.Lex();
3568 if (getLexer().isNot(AsmToken::EndOfStatement))
3569 return reportParseError("unexpected token, expected end of statement");
3570
3571 // Always keep an element on the options "stack" to prevent the user
3572 // from changing the initial options. This is how we remember them.
3573 if (AssemblerOptions.size() == 2)
3574 return reportParseError(Loc, ".set pop with no .set push");
3575
3576 AssemblerOptions.pop_back();
3577 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
3578
3579 getTargetStreamer().emitDirectiveSetPop();
3580 return false;
3581}
3582
3583bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003584 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003585 Parser.Lex();
3586 if (getLexer().isNot(AsmToken::EndOfStatement))
3587 return reportParseError("unexpected token, expected end of statement");
3588
3589 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00003590 AssemblerOptions.push_back(
3591 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00003592
3593 getTargetStreamer().emitDirectiveSetPush();
3594 return false;
3595}
3596
Jack Carterd76b2372013-03-21 21:44:16 +00003597bool MipsAsmParser::parseSetAssignment() {
3598 StringRef Name;
3599 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00003600 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00003601
3602 if (Parser.parseIdentifier(Name))
3603 reportParseError("expected identifier after .set");
3604
3605 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003606 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00003607 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00003608
Jack Carter3b2c96e2014-01-22 23:31:38 +00003609 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00003610 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00003611
Toma Tabacuf25949b2015-04-07 13:59:39 +00003612 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00003613 Sym->setVariableValue(Value);
3614
3615 return false;
3616}
Jack Carterd0bd6422013-04-18 00:41:53 +00003617
Toma Tabacu26647792014-09-09 12:52:14 +00003618bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003619 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00003620 Parser.Lex();
3621 if (getLexer().isNot(AsmToken::EndOfStatement))
3622 return reportParseError("unexpected token, expected end of statement");
3623
3624 // Reset assembler options to their initial values.
3625 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
3626 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
3627
3628 getTargetStreamer().emitDirectiveSetMips0();
3629 return false;
3630}
3631
Toma Tabacu85618b32014-08-19 14:22:52 +00003632bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003633 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00003634 Parser.Lex();
3635 if (getLexer().isNot(AsmToken::Equal))
3636 return reportParseError("unexpected token, expected equals sign");
3637
3638 Parser.Lex();
3639 StringRef Arch;
3640 if (Parser.parseIdentifier(Arch))
3641 return reportParseError("expected arch identifier");
3642
3643 StringRef ArchFeatureName =
3644 StringSwitch<StringRef>(Arch)
3645 .Case("mips1", "mips1")
3646 .Case("mips2", "mips2")
3647 .Case("mips3", "mips3")
3648 .Case("mips4", "mips4")
3649 .Case("mips5", "mips5")
3650 .Case("mips32", "mips32")
3651 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003652 .Case("mips32r3", "mips32r3")
3653 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003654 .Case("mips32r6", "mips32r6")
3655 .Case("mips64", "mips64")
3656 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003657 .Case("mips64r3", "mips64r3")
3658 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003659 .Case("mips64r6", "mips64r6")
3660 .Case("cnmips", "cnmips")
3661 .Case("r4000", "mips3") // This is an implementation of Mips3.
3662 .Default("");
3663
3664 if (ArchFeatureName.empty())
3665 return reportParseError("unsupported architecture");
3666
3667 selectArch(ArchFeatureName);
3668 getTargetStreamer().emitDirectiveSetArch(Arch);
3669 return false;
3670}
3671
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003672bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003673 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003674 Parser.Lex();
3675 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003676 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003677
Matheus Almeida2852af82014-04-22 10:15:54 +00003678 switch (Feature) {
3679 default:
3680 llvm_unreachable("Unimplemented feature");
3681 case Mips::FeatureDSP:
3682 setFeatureBits(Mips::FeatureDSP, "dsp");
3683 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003684 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003685 case Mips::FeatureMicroMips:
3686 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003687 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003688 case Mips::FeatureMips1:
3689 selectArch("mips1");
3690 getTargetStreamer().emitDirectiveSetMips1();
3691 break;
3692 case Mips::FeatureMips2:
3693 selectArch("mips2");
3694 getTargetStreamer().emitDirectiveSetMips2();
3695 break;
3696 case Mips::FeatureMips3:
3697 selectArch("mips3");
3698 getTargetStreamer().emitDirectiveSetMips3();
3699 break;
3700 case Mips::FeatureMips4:
3701 selectArch("mips4");
3702 getTargetStreamer().emitDirectiveSetMips4();
3703 break;
3704 case Mips::FeatureMips5:
3705 selectArch("mips5");
3706 getTargetStreamer().emitDirectiveSetMips5();
3707 break;
3708 case Mips::FeatureMips32:
3709 selectArch("mips32");
3710 getTargetStreamer().emitDirectiveSetMips32();
3711 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003712 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003713 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003714 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003715 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003716 case Mips::FeatureMips32r3:
3717 selectArch("mips32r3");
3718 getTargetStreamer().emitDirectiveSetMips32R3();
3719 break;
3720 case Mips::FeatureMips32r5:
3721 selectArch("mips32r5");
3722 getTargetStreamer().emitDirectiveSetMips32R5();
3723 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003724 case Mips::FeatureMips32r6:
3725 selectArch("mips32r6");
3726 getTargetStreamer().emitDirectiveSetMips32R6();
3727 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003728 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003729 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00003730 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003731 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003732 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003733 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003734 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003735 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003736 case Mips::FeatureMips64r3:
3737 selectArch("mips64r3");
3738 getTargetStreamer().emitDirectiveSetMips64R3();
3739 break;
3740 case Mips::FeatureMips64r5:
3741 selectArch("mips64r5");
3742 getTargetStreamer().emitDirectiveSetMips64R5();
3743 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003744 case Mips::FeatureMips64r6:
3745 selectArch("mips64r6");
3746 getTargetStreamer().emitDirectiveSetMips64R6();
3747 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003748 }
3749 return false;
3750}
3751
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003752bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003753 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003754 if (getLexer().isNot(AsmToken::Comma)) {
3755 SMLoc Loc = getLexer().getLoc();
3756 Parser.eatToEndOfStatement();
3757 return Error(Loc, ErrorStr);
3758 }
3759
Matheus Almeida2852af82014-04-22 10:15:54 +00003760 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003761 return true;
3762}
3763
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003764bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003765 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00003766 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003767
Toma Tabacudde4c462014-11-06 10:02:45 +00003768 if (inMips16Mode()) {
3769 reportParseError(".cpload is not supported in Mips16 mode");
3770 return false;
3771 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003772
David Blaikie960ea3f2014-06-08 16:18:35 +00003773 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00003774 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003775 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3776 reportParseError("expected register containing function address");
3777 return false;
3778 }
3779
David Blaikie960ea3f2014-06-08 16:18:35 +00003780 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
3781 if (!RegOpnd.isGPRAsmReg()) {
3782 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003783 return false;
3784 }
3785
Toma Tabacudde4c462014-11-06 10:02:45 +00003786 // If this is not the end of the statement, report an error.
3787 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3788 reportParseError("unexpected token, expected end of statement");
3789 return false;
3790 }
3791
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003792 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003793 return false;
3794}
3795
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003796bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003797 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003798 unsigned FuncReg;
3799 unsigned Save;
3800 bool SaveIsReg = true;
3801
Matheus Almeida7e815762014-06-18 13:08:59 +00003802 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003803 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003804 if (ResTy == MatchOperand_NoMatch) {
3805 reportParseError("expected register containing function address");
3806 Parser.eatToEndOfStatement();
3807 return false;
3808 }
3809
3810 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3811 if (!FuncRegOpnd.isGPRAsmReg()) {
3812 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3813 Parser.eatToEndOfStatement();
3814 return false;
3815 }
3816
3817 FuncReg = FuncRegOpnd.getGPR32Reg();
3818 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003819
Toma Tabacu65f10572014-09-16 15:00:52 +00003820 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003821 return true;
3822
Toma Tabacu13964452014-09-04 13:23:44 +00003823 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003824 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003825 const AsmToken &Tok = Parser.getTok();
3826 if (Tok.is(AsmToken::Integer)) {
3827 Save = Tok.getIntVal();
3828 SaveIsReg = false;
3829 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003830 } else {
3831 reportParseError("expected save register or stack offset");
3832 Parser.eatToEndOfStatement();
3833 return false;
3834 }
3835 } else {
3836 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3837 if (!SaveOpnd.isGPRAsmReg()) {
3838 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3839 Parser.eatToEndOfStatement();
3840 return false;
3841 }
3842 Save = SaveOpnd.getGPR32Reg();
3843 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003844
Toma Tabacu65f10572014-09-16 15:00:52 +00003845 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003846 return true;
3847
Toma Tabacu8874eac2015-02-18 13:46:53 +00003848 const MCExpr *Expr;
3849 if (Parser.parseExpression(Expr)) {
3850 reportParseError("expected expression");
3851 return false;
3852 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003853
Toma Tabacu8874eac2015-02-18 13:46:53 +00003854 if (Expr->getKind() != MCExpr::SymbolRef) {
3855 reportParseError("expected symbol");
3856 return false;
3857 }
3858 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
3859
3860 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
3861 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003862 return false;
3863}
3864
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003865bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003866 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003867 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3868 const AsmToken &Tok = Parser.getTok();
3869
3870 if (Tok.getString() == "2008") {
3871 Parser.Lex();
3872 getTargetStreamer().emitDirectiveNaN2008();
3873 return false;
3874 } else if (Tok.getString() == "legacy") {
3875 Parser.Lex();
3876 getTargetStreamer().emitDirectiveNaNLegacy();
3877 return false;
3878 }
3879 }
3880 // If we don't recognize the option passed to the .nan
3881 // directive (e.g. no option or unknown option), emit an error.
3882 reportParseError("invalid option in .nan directive");
3883 return false;
3884}
3885
Jack Carter0b744b32012-10-04 02:29:46 +00003886bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003887 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003888 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003889 const AsmToken &Tok = Parser.getTok();
3890
3891 if (Tok.getString() == "noat") {
3892 return parseSetNoAtDirective();
3893 } else if (Tok.getString() == "at") {
3894 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003895 } else if (Tok.getString() == "arch") {
3896 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003897 } else if (Tok.getString() == "fp") {
3898 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003899 } else if (Tok.getString() == "pop") {
3900 return parseSetPopDirective();
3901 } else if (Tok.getString() == "push") {
3902 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003903 } else if (Tok.getString() == "reorder") {
3904 return parseSetReorderDirective();
3905 } else if (Tok.getString() == "noreorder") {
3906 return parseSetNoReorderDirective();
3907 } else if (Tok.getString() == "macro") {
3908 return parseSetMacroDirective();
3909 } else if (Tok.getString() == "nomacro") {
3910 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003911 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00003912 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003913 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003914 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003915 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003916 getTargetStreamer().emitDirectiveSetNoMicroMips();
3917 Parser.eatToEndOfStatement();
3918 return false;
3919 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003920 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003921 } else if (Tok.getString() == "mips0") {
3922 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003923 } else if (Tok.getString() == "mips1") {
3924 return parseSetFeature(Mips::FeatureMips1);
3925 } else if (Tok.getString() == "mips2") {
3926 return parseSetFeature(Mips::FeatureMips2);
3927 } else if (Tok.getString() == "mips3") {
3928 return parseSetFeature(Mips::FeatureMips3);
3929 } else if (Tok.getString() == "mips4") {
3930 return parseSetFeature(Mips::FeatureMips4);
3931 } else if (Tok.getString() == "mips5") {
3932 return parseSetFeature(Mips::FeatureMips5);
3933 } else if (Tok.getString() == "mips32") {
3934 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003935 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003936 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003937 } else if (Tok.getString() == "mips32r3") {
3938 return parseSetFeature(Mips::FeatureMips32r3);
3939 } else if (Tok.getString() == "mips32r5") {
3940 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003941 } else if (Tok.getString() == "mips32r6") {
3942 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003943 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003944 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003945 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003946 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003947 } else if (Tok.getString() == "mips64r3") {
3948 return parseSetFeature(Mips::FeatureMips64r3);
3949 } else if (Tok.getString() == "mips64r5") {
3950 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003951 } else if (Tok.getString() == "mips64r6") {
3952 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003953 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003954 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003955 } else if (Tok.getString() == "nodsp") {
3956 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003957 } else if (Tok.getString() == "msa") {
3958 return parseSetMsaDirective();
3959 } else if (Tok.getString() == "nomsa") {
3960 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003961 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003962 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003963 parseSetAssignment();
3964 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003965 }
Jack Carter07c818d2013-01-25 01:31:34 +00003966
Jack Carter0b744b32012-10-04 02:29:46 +00003967 return true;
3968}
3969
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003970/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003971/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003972bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003973 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003974 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3975 for (;;) {
3976 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003977 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003978 return true;
3979
3980 getParser().getStreamer().EmitValue(Value, Size);
3981
3982 if (getLexer().is(AsmToken::EndOfStatement))
3983 break;
3984
Jack Carter07c818d2013-01-25 01:31:34 +00003985 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003986 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00003987 Parser.Lex();
3988 }
3989 }
3990
3991 Parser.Lex();
3992 return false;
3993}
3994
Vladimir Medic4c299852013-11-06 11:27:05 +00003995/// parseDirectiveGpWord
3996/// ::= .gpword local_sym
3997bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003998 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003999 const MCExpr *Value;
4000 // EmitGPRel32Value requires an expression, so we are using base class
4001 // method to evaluate the expression.
4002 if (getParser().parseExpression(Value))
4003 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00004004 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00004005
Vladimir Medice10c1122013-11-13 13:18:04 +00004006 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004007 return Error(getLexer().getLoc(),
4008 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00004009 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00004010 return false;
4011}
4012
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004013/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00004014/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004015bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004016 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004017 const MCExpr *Value;
4018 // EmitGPRel64Value requires an expression, so we are using base class
4019 // method to evaluate the expression.
4020 if (getParser().parseExpression(Value))
4021 return true;
4022 getParser().getStreamer().EmitGPRel64Value(Value);
4023
4024 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004025 return Error(getLexer().getLoc(),
4026 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00004027 Parser.Lex(); // Eat EndOfStatement token.
4028 return false;
4029}
4030
Jack Carter0cd3c192014-01-06 23:27:31 +00004031bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004032 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00004033 // Get the option token.
4034 AsmToken Tok = Parser.getTok();
4035 // At the moment only identifiers are supported.
4036 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004037 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00004038 Parser.eatToEndOfStatement();
4039 return false;
4040 }
4041
4042 StringRef Option = Tok.getIdentifier();
4043
4044 if (Option == "pic0") {
4045 getTargetStreamer().emitDirectiveOptionPic0();
4046 Parser.Lex();
4047 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4048 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004049 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004050 Parser.eatToEndOfStatement();
4051 }
4052 return false;
4053 }
4054
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004055 if (Option == "pic2") {
4056 getTargetStreamer().emitDirectiveOptionPic2();
4057 Parser.Lex();
4058 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4059 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004060 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004061 Parser.eatToEndOfStatement();
4062 }
4063 return false;
4064 }
4065
Jack Carter0cd3c192014-01-06 23:27:31 +00004066 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00004067 Warning(Parser.getTok().getLoc(),
4068 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00004069 Parser.eatToEndOfStatement();
4070 return false;
4071}
4072
Toma Tabacu9ca50962015-04-16 09:53:47 +00004073/// parseInsnDirective
4074/// ::= .insn
4075bool MipsAsmParser::parseInsnDirective() {
4076 // If this is not the end of the statement, report an error.
4077 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4078 reportParseError("unexpected token, expected end of statement");
4079 return false;
4080 }
4081
4082 // The actual label marking happens in
4083 // MipsELFStreamer::createPendingLabelRelocs().
4084 getTargetStreamer().emitDirectiveInsn();
4085
4086 getParser().Lex(); // Eat EndOfStatement token.
4087 return false;
4088}
4089
Daniel Sanders7e527422014-07-10 13:38:23 +00004090/// parseDirectiveModule
4091/// ::= .module oddspreg
4092/// ::= .module nooddspreg
4093/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004094bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004095 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004096 MCAsmLexer &Lexer = getLexer();
4097 SMLoc L = Lexer.getLoc();
4098
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004099 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004100 // TODO : get a better message.
4101 reportParseError(".module directive must appear before any code");
4102 return false;
4103 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004104
Toma Tabacuc405c822015-01-23 10:40:19 +00004105 StringRef Option;
4106 if (Parser.parseIdentifier(Option)) {
4107 reportParseError("expected .module option identifier");
4108 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004109 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004110
Toma Tabacuc405c822015-01-23 10:40:19 +00004111 if (Option == "oddspreg") {
4112 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
4113 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4114
4115 // If this is not the end of the statement, report an error.
4116 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4117 reportParseError("unexpected token, expected end of statement");
4118 return false;
4119 }
4120
4121 return false; // parseDirectiveModule has finished successfully.
4122 } else if (Option == "nooddspreg") {
4123 if (!isABI_O32()) {
4124 Error(L, "'.module nooddspreg' requires the O32 ABI");
4125 return false;
4126 }
4127
4128 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
4129 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4130
4131 // If this is not the end of the statement, report an error.
4132 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4133 reportParseError("unexpected token, expected end of statement");
4134 return false;
4135 }
4136
4137 return false; // parseDirectiveModule has finished successfully.
4138 } else if (Option == "fp") {
4139 return parseDirectiveModuleFP();
4140 } else {
4141 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
4142 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004143}
4144
4145/// parseDirectiveModuleFP
4146/// ::= =32
4147/// ::= =xx
4148/// ::= =64
4149bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004150 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004151 MCAsmLexer &Lexer = getLexer();
4152
4153 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004154 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004155 return false;
4156 }
4157 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004158
Daniel Sanders7e527422014-07-10 13:38:23 +00004159 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004160 if (!parseFpABIValue(FpABI, ".module"))
4161 return false;
4162
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004163 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004164 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004165 return false;
4166 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004167
Daniel Sanders7201a3e2014-07-08 10:35:52 +00004168 // Emit appropriate flags.
4169 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00004170 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004171 return false;
4172}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004173
Daniel Sanders7e527422014-07-10 13:38:23 +00004174bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004175 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004176 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004177 MCAsmLexer &Lexer = getLexer();
4178
4179 if (Lexer.is(AsmToken::Identifier)) {
4180 StringRef Value = Parser.getTok().getString();
4181 Parser.Lex();
4182
4183 if (Value != "xx") {
4184 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4185 return false;
4186 }
4187
4188 if (!isABI_O32()) {
4189 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
4190 return false;
4191 }
4192
Daniel Sanders7e527422014-07-10 13:38:23 +00004193 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004194 return true;
4195 }
4196
4197 if (Lexer.is(AsmToken::Integer)) {
4198 unsigned Value = Parser.getTok().getIntVal();
4199 Parser.Lex();
4200
4201 if (Value != 32 && Value != 64) {
4202 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4203 return false;
4204 }
4205
4206 if (Value == 32) {
4207 if (!isABI_O32()) {
4208 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
4209 return false;
4210 }
4211
Daniel Sanders7e527422014-07-10 13:38:23 +00004212 FpABI = MipsABIFlagsSection::FpABIKind::S32;
4213 } else
4214 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004215
Daniel Sanders7e527422014-07-10 13:38:23 +00004216 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004217 }
4218
4219 return false;
4220}
4221
Jack Carter0b744b32012-10-04 02:29:46 +00004222bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004223 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004224 StringRef IDVal = DirectiveID.getString();
4225
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004226 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004227 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00004228 if (IDVal == ".dword") {
4229 parseDataDirective(8, DirectiveID.getLoc());
4230 return false;
4231 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004232 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004233 StringRef SymbolName;
4234
4235 if (Parser.parseIdentifier(SymbolName)) {
4236 reportParseError("expected identifier after .ent");
4237 return false;
4238 }
4239
4240 // There's an undocumented extension that allows an integer to
4241 // follow the name of the procedure which AFAICS is ignored by GAS.
4242 // Example: .ent foo,2
4243 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4244 if (getLexer().isNot(AsmToken::Comma)) {
4245 // Even though we accept this undocumented extension for compatibility
4246 // reasons, the additional integer argument does not actually change
4247 // the behaviour of the '.ent' directive, so we would like to discourage
4248 // its use. We do this by not referring to the extended version in
4249 // error messages which are not directly related to its use.
4250 reportParseError("unexpected token, expected end of statement");
4251 return false;
4252 }
4253 Parser.Lex(); // Eat the comma.
4254 const MCExpr *DummyNumber;
4255 int64_t DummyNumberVal;
4256 // If the user was explicitly trying to use the extended version,
4257 // we still give helpful extension-related error messages.
4258 if (Parser.parseExpression(DummyNumber)) {
4259 reportParseError("expected number after comma");
4260 return false;
4261 }
4262 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
4263 reportParseError("expected an absolute expression after comma");
4264 return false;
4265 }
4266 }
4267
4268 // If this is not the end of the statement, report an error.
4269 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4270 reportParseError("unexpected token, expected end of statement");
4271 return false;
4272 }
4273
4274 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
4275
4276 getTargetStreamer().emitDirectiveEnt(*Sym);
4277 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00004278 return false;
4279 }
4280
Jack Carter07c818d2013-01-25 01:31:34 +00004281 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004282 StringRef SymbolName;
4283
4284 if (Parser.parseIdentifier(SymbolName)) {
4285 reportParseError("expected identifier after .end");
4286 return false;
4287 }
4288
4289 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4290 reportParseError("unexpected token, expected end of statement");
4291 return false;
4292 }
4293
4294 if (CurrentFn == nullptr) {
4295 reportParseError(".end used without .ent");
4296 return false;
4297 }
4298
4299 if ((SymbolName != CurrentFn->getName())) {
4300 reportParseError(".end symbol does not match .ent symbol");
4301 return false;
4302 }
4303
4304 getTargetStreamer().emitDirectiveEnd(SymbolName);
4305 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00004306 return false;
4307 }
4308
Jack Carter07c818d2013-01-25 01:31:34 +00004309 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004310 // .frame $stack_reg, frame_size_in_bytes, $return_reg
4311 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004312 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004313 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4314 reportParseError("expected stack register");
4315 return false;
4316 }
4317
4318 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4319 if (!StackRegOpnd.isGPRAsmReg()) {
4320 reportParseError(StackRegOpnd.getStartLoc(),
4321 "expected general purpose register");
4322 return false;
4323 }
4324 unsigned StackReg = StackRegOpnd.getGPR32Reg();
4325
4326 if (Parser.getTok().is(AsmToken::Comma))
4327 Parser.Lex();
4328 else {
4329 reportParseError("unexpected token, expected comma");
4330 return false;
4331 }
4332
4333 // Parse the frame size.
4334 const MCExpr *FrameSize;
4335 int64_t FrameSizeVal;
4336
4337 if (Parser.parseExpression(FrameSize)) {
4338 reportParseError("expected frame size value");
4339 return false;
4340 }
4341
4342 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
4343 reportParseError("frame size not an absolute expression");
4344 return false;
4345 }
4346
4347 if (Parser.getTok().is(AsmToken::Comma))
4348 Parser.Lex();
4349 else {
4350 reportParseError("unexpected token, expected comma");
4351 return false;
4352 }
4353
4354 // Parse the return register.
4355 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00004356 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004357 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4358 reportParseError("expected return register");
4359 return false;
4360 }
4361
4362 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4363 if (!ReturnRegOpnd.isGPRAsmReg()) {
4364 reportParseError(ReturnRegOpnd.getStartLoc(),
4365 "expected general purpose register");
4366 return false;
4367 }
4368
4369 // If this is not the end of the statement, report an error.
4370 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4371 reportParseError("unexpected token, expected end of statement");
4372 return false;
4373 }
4374
4375 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
4376 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00004377 return false;
4378 }
4379
Jack Carter07c818d2013-01-25 01:31:34 +00004380 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00004381 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00004382 }
4383
Daniel Sandersd97a6342014-08-13 10:07:34 +00004384 if (IDVal == ".mask" || IDVal == ".fmask") {
4385 // .mask bitmask, frame_offset
4386 // bitmask: One bit for each register used.
4387 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
4388 // first register is expected to be saved.
4389 // Examples:
4390 // .mask 0x80000000, -4
4391 // .fmask 0x80000000, -4
4392 //
Jack Carterbe332172012-09-07 00:48:02 +00004393
Daniel Sandersd97a6342014-08-13 10:07:34 +00004394 // Parse the bitmask
4395 const MCExpr *BitMask;
4396 int64_t BitMaskVal;
4397
4398 if (Parser.parseExpression(BitMask)) {
4399 reportParseError("expected bitmask value");
4400 return false;
4401 }
4402
4403 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
4404 reportParseError("bitmask not an absolute expression");
4405 return false;
4406 }
4407
4408 if (Parser.getTok().is(AsmToken::Comma))
4409 Parser.Lex();
4410 else {
4411 reportParseError("unexpected token, expected comma");
4412 return false;
4413 }
4414
4415 // Parse the frame_offset
4416 const MCExpr *FrameOffset;
4417 int64_t FrameOffsetVal;
4418
4419 if (Parser.parseExpression(FrameOffset)) {
4420 reportParseError("expected frame offset value");
4421 return false;
4422 }
4423
4424 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
4425 reportParseError("frame offset not an absolute expression");
4426 return false;
4427 }
4428
4429 // If this is not the end of the statement, report an error.
4430 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4431 reportParseError("unexpected token, expected end of statement");
4432 return false;
4433 }
4434
4435 if (IDVal == ".mask")
4436 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
4437 else
4438 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00004439 return false;
4440 }
4441
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004442 if (IDVal == ".nan")
4443 return parseDirectiveNaN();
4444
Jack Carter07c818d2013-01-25 01:31:34 +00004445 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004446 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00004447 return false;
4448 }
4449
Rafael Espindolab59fb732014-03-28 18:50:26 +00004450 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004451 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004452 return false;
4453 }
4454
Jack Carter07c818d2013-01-25 01:31:34 +00004455 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004456 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00004457 return false;
4458 }
4459
Jack Carter0cd3c192014-01-06 23:27:31 +00004460 if (IDVal == ".option")
4461 return parseDirectiveOption();
4462
4463 if (IDVal == ".abicalls") {
4464 getTargetStreamer().emitDirectiveAbiCalls();
4465 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004466 Error(Parser.getTok().getLoc(),
4467 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004468 // Clear line
4469 Parser.eatToEndOfStatement();
4470 }
4471 return false;
4472 }
4473
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004474 if (IDVal == ".cpsetup")
4475 return parseDirectiveCPSetup();
4476
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004477 if (IDVal == ".module")
4478 return parseDirectiveModule();
4479
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004480 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
4481 return parseInternalDirectiveReallowModule();
4482
Toma Tabacu9ca50962015-04-16 09:53:47 +00004483 if (IDVal == ".insn")
4484 return parseInsnDirective();
4485
Rafael Espindola870c4e92012-01-11 03:56:41 +00004486 return true;
4487}
4488
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004489bool MipsAsmParser::parseInternalDirectiveReallowModule() {
4490 // If this is not the end of the statement, report an error.
4491 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4492 reportParseError("unexpected token, expected end of statement");
4493 return false;
4494 }
4495
4496 getTargetStreamer().reallowModuleDirective();
4497
4498 getParser().Lex(); // Eat EndOfStatement token.
4499 return false;
4500}
4501
Rafael Espindola870c4e92012-01-11 03:56:41 +00004502extern "C" void LLVMInitializeMipsAsmParser() {
4503 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
4504 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
4505 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
4506 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
4507}
Jack Carterb4dbc172012-09-05 23:34:03 +00004508
4509#define GET_REGISTER_MATCHER
4510#define GET_MATCHER_IMPLEMENTATION
4511#include "MipsGenAsmMatcher.inc"