blob: 7046b7053e8247c20c4b93ee6e916c81797ff8ed [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
Toma Tabacu00e98672015-05-01 12:19:27 +0000182 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, 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:
Toma Tabacu00e98672015-05-01 12:19:27 +00001612 return expandLoadImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001613 case Mips::LoadImm64:
Toma Tabacu00e98672015-05-01 12:19:27 +00001614 return expandLoadImm(Inst, false, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001615 case Mips::LoadAddrImm32:
Jack Carterd0bd6422013-04-18 00:41:53 +00001616 return expandLoadAddressImm(Inst, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001617 case Mips::LoadAddrReg32:
Jack Carterd0bd6422013-04-18 00:41:53 +00001618 return expandLoadAddressReg(Inst, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001619 case Mips::B_MM_Pseudo:
1620 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001621 case Mips::SWM_MM:
1622 case Mips::LWM_MM:
1623 return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001624 case Mips::JalOneReg:
1625 case Mips::JalTwoReg:
1626 return expandJalWithRegs(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001627 }
Jack Carter30a59822012-10-04 04:03:53 +00001628}
Jack Carter92995f12012-10-06 00:53:28 +00001629
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001630namespace {
Toma Tabacua2861db2015-05-01 10:26:47 +00001631template <unsigned ShiftAmount>
Toma Tabacu61145652015-04-28 13:16:06 +00001632void createLShiftOri(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001633 SmallVectorImpl<MCInst> &Instructions) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001634 MCInst tmpInst;
Toma Tabacua2861db2015-05-01 10:26:47 +00001635 if (ShiftAmount >= 32) {
1636 tmpInst.setOpcode(Mips::DSLL32);
1637 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1638 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1639 tmpInst.addOperand(MCOperand::CreateImm(ShiftAmount - 32));
1640 tmpInst.setLoc(IDLoc);
1641 Instructions.push_back(tmpInst);
1642 tmpInst.clear();
1643 } else if (ShiftAmount > 0) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001644 tmpInst.setOpcode(Mips::DSLL);
1645 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1646 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacua2861db2015-05-01 10:26:47 +00001647 tmpInst.addOperand(MCOperand::CreateImm(ShiftAmount));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001648 tmpInst.setLoc(IDLoc);
1649 Instructions.push_back(tmpInst);
1650 tmpInst.clear();
1651 }
Toma Tabacu7dea2e32015-04-28 14:06:35 +00001652 // There's no need for an ORi if the immediate is 0.
1653 if (Operand.isImm() && Operand.getImm() == 0)
1654 return;
1655
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001656 tmpInst.setOpcode(Mips::ORi);
1657 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1658 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001659 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001660 tmpInst.setLoc(IDLoc);
1661 Instructions.push_back(tmpInst);
1662}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001663
Toma Tabacua2861db2015-05-01 10:26:47 +00001664template <unsigned ShiftAmount>
Toma Tabacu61145652015-04-28 13:16:06 +00001665void createLShiftOri(int64_t Value, unsigned RegNo, SMLoc IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001666 SmallVectorImpl<MCInst> &Instructions) {
1667 createLShiftOri<ShiftAmount>(MCOperand::CreateImm(Value), RegNo, IDLoc,
1668 Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001669}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001670}
1671
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001672bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
1673 SmallVectorImpl<MCInst> &Instructions) {
1674 // Create a JALR instruction which is going to replace the pseudo-JAL.
1675 MCInst JalrInst;
1676 JalrInst.setLoc(IDLoc);
1677 const MCOperand FirstRegOp = Inst.getOperand(0);
1678 const unsigned Opcode = Inst.getOpcode();
1679
1680 if (Opcode == Mips::JalOneReg) {
1681 // jal $rs => jalr $rs
1682 if (inMicroMipsMode()) {
1683 JalrInst.setOpcode(Mips::JALR16_MM);
1684 JalrInst.addOperand(FirstRegOp);
1685 } else {
1686 JalrInst.setOpcode(Mips::JALR);
1687 JalrInst.addOperand(MCOperand::CreateReg(Mips::RA));
1688 JalrInst.addOperand(FirstRegOp);
1689 }
1690 } else if (Opcode == Mips::JalTwoReg) {
1691 // jal $rd, $rs => jalr $rd, $rs
1692 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
1693 JalrInst.addOperand(FirstRegOp);
1694 const MCOperand SecondRegOp = Inst.getOperand(1);
1695 JalrInst.addOperand(SecondRegOp);
1696 }
1697 Instructions.push_back(JalrInst);
1698
1699 // If .set reorder is active, emit a NOP after it.
1700 if (AssemblerOptions.back()->isReorder()) {
1701 // This is a 32-bit NOP because these 2 pseudo-instructions
1702 // do not have a short delay slot.
1703 MCInst NopInst;
1704 NopInst.setOpcode(Mips::SLL);
1705 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1706 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1707 NopInst.addOperand(MCOperand::CreateImm(0));
1708 Instructions.push_back(NopInst);
1709 }
1710
1711 return false;
1712}
1713
Toma Tabacu00e98672015-05-01 12:19:27 +00001714bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001715 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00001716 if (!Is32BitImm && !isGP64bit()) {
1717 Error(IDLoc, "instruction requires a 64-bit architecture");
1718 return true;
1719 }
1720
Jack Carter92995f12012-10-06 00:53:28 +00001721 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001722 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001723 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001724 const MCOperand &RegOp = Inst.getOperand(0);
1725 assert(RegOp.isReg() && "expected register operand kind");
1726
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001727 int64_t ImmValue = ImmOp.getImm();
Toma Tabacu137d90a2015-04-28 12:04:53 +00001728 unsigned Reg = RegOp.getReg();
Jack Carter92995f12012-10-06 00:53:28 +00001729 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001730 // FIXME: gas has a special case for values that are 000...1111, which
1731 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001732 if (0 <= ImmValue && ImmValue <= 65535) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001733 // For unsigned and positive signed 16-bit values (0 <= j <= 65535):
Jack Carter30a59822012-10-04 04:03:53 +00001734 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001735 tmpInst.setOpcode(Mips::ORi);
Toma Tabacu137d90a2015-04-28 12:04:53 +00001736 tmpInst.addOperand(MCOperand::CreateReg(Reg));
Jack Carterd0bd6422013-04-18 00:41:53 +00001737 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001738 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001739 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001740 } else if (ImmValue < 0 && ImmValue >= -32768) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001741 // For negative signed 16-bit values (-32768 <= j < 0):
Jack Carter30a59822012-10-04 04:03:53 +00001742 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001743 tmpInst.setOpcode(Mips::ADDiu);
Toma Tabacu137d90a2015-04-28 12:04:53 +00001744 tmpInst.addOperand(MCOperand::CreateReg(Reg));
Jack Carterd0bd6422013-04-18 00:41:53 +00001745 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001746 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001747 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001748 } else if ((ImmValue & 0xffffffff) == ImmValue) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001749 // For all other values which are representable as a 32-bit integer:
Jack Carter30a59822012-10-04 04:03:53 +00001750 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001751 // ori d,d,lo16(j)
Toma Tabacu79588102015-04-29 10:19:56 +00001752 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1753 uint16_t Bits15To0 = ImmValue & 0xffff;
1754
Jack Carter873c7242013-01-12 01:03:14 +00001755 tmpInst.setOpcode(Mips::LUi);
Toma Tabacu137d90a2015-04-28 12:04:53 +00001756 tmpInst.addOperand(MCOperand::CreateReg(Reg));
Toma Tabacu79588102015-04-29 10:19:56 +00001757 tmpInst.addOperand(MCOperand::CreateImm(Bits31To16));
Jack Carter30a59822012-10-04 04:03:53 +00001758 Instructions.push_back(tmpInst);
Toma Tabacua2861db2015-05-01 10:26:47 +00001759 createLShiftOri<0>(Bits15To0, Reg, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001760 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Toma Tabacu00e98672015-05-01 12:19:27 +00001761 if (Is32BitImm) {
1762 Error(IDLoc, "instruction requires a 32-bit immediate");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001763 return true;
1764 }
1765
1766 // <------- lo32 ------>
1767 // <------- hi32 ------>
1768 // <- hi16 -> <- lo16 ->
1769 // _________________________________
1770 // | | | |
Toma Tabacubda745f2015-04-27 15:21:38 +00001771 // | 16-bits | 16-bits | 16-bits |
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001772 // |__________|__________|__________|
1773 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001774 // For any 64-bit value that is representable as a 48-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001775 // li d,j => lui d,hi16(j)
1776 // ori d,d,hi16(lo32(j))
1777 // dsll d,d,16
1778 // ori d,d,lo16(lo32(j))
Toma Tabacu79588102015-04-29 10:19:56 +00001779 uint16_t Bits47To32 = (ImmValue >> 32) & 0xffff;
1780 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1781 uint16_t Bits15To0 = ImmValue & 0xffff;
1782
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001783 tmpInst.setOpcode(Mips::LUi);
Toma Tabacu137d90a2015-04-28 12:04:53 +00001784 tmpInst.addOperand(MCOperand::CreateReg(Reg));
Toma Tabacu79588102015-04-29 10:19:56 +00001785 tmpInst.addOperand(MCOperand::CreateImm(Bits47To32));
Jack Carter30a59822012-10-04 04:03:53 +00001786 Instructions.push_back(tmpInst);
Toma Tabacua2861db2015-05-01 10:26:47 +00001787 createLShiftOri<0>(Bits31To16, Reg, IDLoc, Instructions);
1788 createLShiftOri<16>(Bits15To0, Reg, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001789 } else {
Toma Tabacu00e98672015-05-01 12:19:27 +00001790 if (Is32BitImm) {
1791 Error(IDLoc, "instruction requires a 32-bit immediate");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001792 return true;
1793 }
1794
1795 // <------- hi32 ------> <------- lo32 ------>
1796 // <- hi16 -> <- lo16 ->
1797 // ___________________________________________
1798 // | | | | |
Toma Tabacubda745f2015-04-27 15:21:38 +00001799 // | 16-bits | 16-bits | 16-bits | 16-bits |
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001800 // |__________|__________|__________|__________|
1801 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001802 // For all other values which are representable as a 64-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001803 // li d,j => lui d,hi16(j)
1804 // ori d,d,lo16(hi32(j))
1805 // dsll d,d,16
1806 // ori d,d,hi16(lo32(j))
1807 // dsll d,d,16
1808 // ori d,d,lo16(lo32(j))
Toma Tabacu79588102015-04-29 10:19:56 +00001809 uint16_t Bits63To48 = (ImmValue >> 48) & 0xffff;
1810 uint16_t Bits47To32 = (ImmValue >> 32) & 0xffff;
1811 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1812 uint16_t Bits15To0 = ImmValue & 0xffff;
1813
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001814 tmpInst.setOpcode(Mips::LUi);
Toma Tabacu137d90a2015-04-28 12:04:53 +00001815 tmpInst.addOperand(MCOperand::CreateReg(Reg));
Toma Tabacu79588102015-04-29 10:19:56 +00001816 tmpInst.addOperand(MCOperand::CreateImm(Bits63To48));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001817 Instructions.push_back(tmpInst);
Toma Tabacua2861db2015-05-01 10:26:47 +00001818 createLShiftOri<0>(Bits47To32, Reg, IDLoc, Instructions);
1819
1820 // When Bits31To16 is 0, do a left shift of 32 bits instead of doing
1821 // two left shifts of 16 bits.
1822 if (Bits31To16 == 0) {
1823 createLShiftOri<32>(Bits15To0, Reg, IDLoc, Instructions);
1824 } else {
1825 createLShiftOri<16>(Bits31To16, Reg, IDLoc, Instructions);
1826 createLShiftOri<16>(Bits15To0, Reg, IDLoc, Instructions);
1827 }
Jack Carter30a59822012-10-04 04:03:53 +00001828 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001829 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001830}
Jack Carter92995f12012-10-06 00:53:28 +00001831
Matheus Almeida3813d572014-06-19 14:39:14 +00001832bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001833MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1834 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001835 MCInst tmpInst;
1836 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001837 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1838 "expected immediate operand kind");
1839 if (!ImmOp.isImm()) {
1840 expandLoadAddressSym(Inst, IDLoc, Instructions);
1841 return false;
1842 }
Jack Carter543fdf82012-10-09 23:29:45 +00001843 const MCOperand &SrcRegOp = Inst.getOperand(1);
1844 assert(SrcRegOp.isReg() && "expected register operand kind");
1845 const MCOperand &DstRegOp = Inst.getOperand(0);
1846 assert(DstRegOp.isReg() && "expected register operand kind");
1847 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001848 if (-32768 <= ImmValue && ImmValue <= 65535) {
1849 // For -32768 <= j <= 65535.
1850 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001851 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001852 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1853 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1854 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1855 Instructions.push_back(tmpInst);
1856 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001857 // For any other value of j that is representable as a 32-bit integer.
1858 // la d,j(s) => lui d,hi16(j)
1859 // ori d,d,lo16(j)
1860 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001861 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001862 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1863 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1864 Instructions.push_back(tmpInst);
1865 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001866 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001867 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1868 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1869 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1870 Instructions.push_back(tmpInst);
1871 tmpInst.clear();
1872 tmpInst.setOpcode(Mips::ADDu);
1873 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1874 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1875 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1876 Instructions.push_back(tmpInst);
1877 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001878 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001879}
1880
Matheus Almeida3813d572014-06-19 14:39:14 +00001881bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001882MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1883 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001884 MCInst tmpInst;
1885 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001886 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1887 "expected immediate operand kind");
1888 if (!ImmOp.isImm()) {
1889 expandLoadAddressSym(Inst, IDLoc, Instructions);
1890 return false;
1891 }
Jack Carter543fdf82012-10-09 23:29:45 +00001892 const MCOperand &RegOp = Inst.getOperand(0);
1893 assert(RegOp.isReg() && "expected register operand kind");
1894 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001895 if (-32768 <= ImmValue && ImmValue <= 65535) {
1896 // For -32768 <= j <= 65535.
1897 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001898 tmpInst.setOpcode(Mips::ADDiu);
1899 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001900 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001901 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1902 Instructions.push_back(tmpInst);
1903 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001904 // For any other value of j that is representable as a 32-bit integer.
1905 // la d,j => lui d,hi16(j)
1906 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001907 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001908 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1909 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1910 Instructions.push_back(tmpInst);
1911 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001912 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001913 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1914 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1915 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1916 Instructions.push_back(tmpInst);
1917 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001918 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001919}
1920
Toma Tabacu0d64b202014-08-14 10:29:17 +00001921void
1922MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1923 SmallVectorImpl<MCInst> &Instructions) {
1924 // FIXME: If we do have a valid at register to use, we should generate a
1925 // slightly shorter sequence here.
1926 MCInst tmpInst;
1927 int ExprOperandNo = 1;
1928 // Sometimes the assembly parser will get the immediate expression as
1929 // a $zero + an immediate.
1930 if (Inst.getNumOperands() == 3) {
1931 assert(Inst.getOperand(1).getReg() ==
1932 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1933 ExprOperandNo = 2;
1934 }
1935 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1936 assert(SymOp.isExpr() && "expected symbol operand kind");
1937 const MCOperand &RegOp = Inst.getOperand(0);
1938 unsigned RegNo = RegOp.getReg();
1939 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1940 const MCSymbolRefExpr *HiExpr =
1941 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1942 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1943 const MCSymbolRefExpr *LoExpr =
1944 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1945 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1946 if (isGP64bit()) {
1947 // If it's a 64-bit architecture, expand to:
1948 // la d,sym => lui d,highest(sym)
1949 // ori d,d,higher(sym)
1950 // dsll d,d,16
1951 // ori d,d,hi16(sym)
1952 // dsll d,d,16
1953 // ori d,d,lo16(sym)
1954 const MCSymbolRefExpr *HighestExpr =
1955 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1956 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1957 const MCSymbolRefExpr *HigherExpr =
1958 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1959 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1960
1961 tmpInst.setOpcode(Mips::LUi);
1962 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1963 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1964 Instructions.push_back(tmpInst);
1965
Toma Tabacua2861db2015-05-01 10:26:47 +00001966 createLShiftOri<0>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1967 Instructions);
1968 createLShiftOri<16>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00001969 Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001970 createLShiftOri<16>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00001971 Instructions);
1972 } else {
1973 // Otherwise, expand to:
1974 // la d,sym => lui d,hi16(sym)
1975 // ori d,d,lo16(sym)
1976 tmpInst.setOpcode(Mips::LUi);
1977 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1978 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1979 Instructions.push_back(tmpInst);
1980
Toma Tabacua2861db2015-05-01 10:26:47 +00001981 createLShiftOri<0>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1982 Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001983 }
1984}
1985
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00001986bool MipsAsmParser::expandUncondBranchMMPseudo(
1987 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00001988 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
1989 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001990
1991 MCOperand Offset = Inst.getOperand(0);
1992 if (Offset.isExpr()) {
1993 Inst.clear();
1994 Inst.setOpcode(Mips::BEQ_MM);
1995 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1996 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1997 Inst.addOperand(MCOperand::CreateExpr(Offset.getExpr()));
1998 } else {
1999 assert(Offset.isImm() && "expected immediate operand kind");
2000 if (isIntN(11, Offset.getImm())) {
2001 // If offset fits into 11 bits then this instruction becomes microMIPS
2002 // 16-bit unconditional branch instruction.
2003 Inst.setOpcode(Mips::B16_MM);
2004 } else {
2005 if (!isIntN(17, Offset.getImm()))
2006 Error(IDLoc, "branch target out of range");
2007 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2008 Error(IDLoc, "branch to misaligned address");
2009 Inst.clear();
2010 Inst.setOpcode(Mips::BEQ_MM);
2011 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2012 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2013 Inst.addOperand(MCOperand::CreateImm(Offset.getImm()));
2014 }
2015 }
2016 Instructions.push_back(Inst);
2017
Toma Tabacu234482a2015-03-16 12:03:39 +00002018 // If .set reorder is active, emit a NOP after the branch instruction.
2019 if (AssemblerOptions.back()->isReorder())
2020 createNop(true, IDLoc, Instructions);
2021
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002022 return false;
2023}
2024
Jack Carter9e65aa32013-03-22 00:05:30 +00002025void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002026 SmallVectorImpl<MCInst> &Instructions,
2027 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002028 const MCSymbolRefExpr *SR;
2029 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00002030 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002031 const MCExpr *ExprOffset;
2032 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002033 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002034 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2035 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002036 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002037 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2038 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002039 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002040 if (isImmOpnd) {
2041 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2042 ImmOffset = Inst.getOperand(2).getImm();
2043 LoOffset = ImmOffset & 0x0000ffff;
2044 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002045 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002046 if (LoOffset & 0x8000)
2047 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002048 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002049 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002050 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002051 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002052 // These are some of the types of expansions we perform here:
2053 // 1) lw $8, sym => lui $8, %hi(sym)
2054 // lw $8, %lo(sym)($8)
2055 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2056 // add $8, $8, $9
2057 // lw $8, %lo(offset)($9)
2058 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2059 // add $at, $at, $8
2060 // lw $8, %lo(offset)($at)
2061 // 4) sw $8, sym => lui $at, %hi(sym)
2062 // sw $8, %lo(sym)($at)
2063 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2064 // add $at, $at, $8
2065 // sw $8, %lo(offset)($at)
2066 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2067 // ldc1 $f0, %lo(sym)($at)
2068 //
2069 // For load instructions we can use the destination register as a temporary
2070 // if base and dst are different (examples 1 and 2) and if the base register
2071 // is general purpose otherwise we must use $at (example 6) and error if it's
2072 // not available. For stores we must use $at (examples 4 and 5) because we
2073 // must not clobber the source register setting up the offset.
2074 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2075 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2076 unsigned RegClassIDOp0 =
2077 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2078 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2079 (RegClassIDOp0 == Mips::GPR64RegClassID);
2080 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002081 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002082 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002083 // At this point we need AT to perform the expansions and we exit if it is
2084 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002085 TmpRegNum = getATReg(IDLoc);
2086 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002087 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002088 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002089
Jack Carter9e65aa32013-03-22 00:05:30 +00002090 TempInst.setOpcode(Mips::LUi);
2091 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2092 if (isImmOpnd)
2093 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
2094 else {
2095 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002096 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00002097 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
2098 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
2099 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00002100 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002101 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002102 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00002103 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002104 }
2105 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002106 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002107 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002108 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002109 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002110 // Add temp register to base.
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002111 if (BaseRegNum != Mips::ZERO) {
2112 TempInst.setOpcode(Mips::ADDu);
2113 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2114 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2115 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
2116 Instructions.push_back(TempInst);
2117 TempInst.clear();
2118 }
Alp Tokercb402912014-01-24 17:20:08 +00002119 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002120 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002121 TempInst.setOpcode(Inst.getOpcode());
2122 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
2123 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2124 if (isImmOpnd)
2125 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
2126 else {
2127 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002128 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
2129 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
2130 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00002131 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002132 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002133 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00002134 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002135 }
2136 }
2137 Instructions.push_back(TempInst);
2138 TempInst.clear();
2139}
2140
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002141bool
2142MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2143 SmallVectorImpl<MCInst> &Instructions) {
2144 unsigned OpNum = Inst.getNumOperands();
2145 unsigned Opcode = Inst.getOpcode();
2146 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2147
2148 assert (Inst.getOperand(OpNum - 1).isImm() &&
2149 Inst.getOperand(OpNum - 2).isReg() &&
2150 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2151
2152 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2153 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2154 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2155 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2156 // It can be implemented as SWM16 or LWM16 instruction.
2157 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2158
2159 Inst.setOpcode(NewOpcode);
2160 Instructions.push_back(Inst);
2161 return false;
2162}
2163
Toma Tabacu234482a2015-03-16 12:03:39 +00002164void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
2165 SmallVectorImpl<MCInst> &Instructions) {
2166 MCInst NopInst;
2167 if (hasShortDelaySlot) {
2168 NopInst.setOpcode(Mips::MOVE16_MM);
2169 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2170 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2171 } else {
2172 NopInst.setOpcode(Mips::SLL);
2173 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2174 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2175 NopInst.addOperand(MCOperand::CreateImm(0));
2176 }
2177 Instructions.push_back(NopInst);
2178}
2179
Matheus Almeida595fcab2014-06-11 15:05:56 +00002180unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
2181 // As described by the Mips32r2 spec, the registers Rd and Rs for
2182 // jalr.hb must be different.
2183 unsigned Opcode = Inst.getOpcode();
2184
2185 if (Opcode == Mips::JALR_HB &&
2186 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
2187 return Match_RequiresDifferentSrcAndDst;
2188
2189 return Match_Success;
2190}
2191
David Blaikie960ea3f2014-06-08 16:18:35 +00002192bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
2193 OperandVector &Operands,
2194 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00002195 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00002196 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00002197
Jack Carterb4dbc172012-09-05 23:34:03 +00002198 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00002199 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00002200 unsigned MatchResult =
2201 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00002202
2203 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002204 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002205 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00002206 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00002207 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00002208 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00002209 return false;
2210 }
2211 case Match_MissingFeature:
2212 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
2213 return true;
2214 case Match_InvalidOperand: {
2215 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00002216 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002217 if (ErrorInfo >= Operands.size())
2218 return Error(IDLoc, "too few operands for instruction");
2219
David Blaikie960ea3f2014-06-08 16:18:35 +00002220 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00002221 if (ErrorLoc == SMLoc())
2222 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00002223 }
2224
2225 return Error(ErrorLoc, "invalid operand for instruction");
2226 }
2227 case Match_MnemonicFail:
2228 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00002229 case Match_RequiresDifferentSrcAndDst:
2230 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00002231 }
Craig Topper589ceee2015-01-03 08:16:34 +00002232
2233 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00002234}
2235
Toma Tabacud9d344b2015-04-27 14:05:04 +00002236void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
2237 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
2238 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
2239 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002240}
2241
Daniel Sandersef638fe2014-10-03 15:37:37 +00002242void
2243MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
2244 SMRange Range, bool ShowColors) {
2245 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00002246 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00002247 ShowColors);
2248}
2249
Jack Carter1ac53222013-02-20 23:11:17 +00002250int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002251 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002252
Vladimir Medic4c299852013-11-06 11:27:05 +00002253 CC = StringSwitch<unsigned>(Name)
2254 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002255 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00002256 .Case("a0", 4)
2257 .Case("a1", 5)
2258 .Case("a2", 6)
2259 .Case("a3", 7)
2260 .Case("v0", 2)
2261 .Case("v1", 3)
2262 .Case("s0", 16)
2263 .Case("s1", 17)
2264 .Case("s2", 18)
2265 .Case("s3", 19)
2266 .Case("s4", 20)
2267 .Case("s5", 21)
2268 .Case("s6", 22)
2269 .Case("s7", 23)
2270 .Case("k0", 26)
2271 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002272 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00002273 .Case("sp", 29)
2274 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002275 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00002276 .Case("ra", 31)
2277 .Case("t0", 8)
2278 .Case("t1", 9)
2279 .Case("t2", 10)
2280 .Case("t3", 11)
2281 .Case("t4", 12)
2282 .Case("t5", 13)
2283 .Case("t6", 14)
2284 .Case("t7", 15)
2285 .Case("t8", 24)
2286 .Case("t9", 25)
2287 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002288
Toma Tabacufda445c2014-09-15 15:33:01 +00002289 if (!(isABI_N32() || isABI_N64()))
2290 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002291
Daniel Sandersef638fe2014-10-03 15:37:37 +00002292 if (12 <= CC && CC <= 15) {
2293 // Name is one of t4-t7
2294 AsmToken RegTok = getLexer().peekTok();
2295 SMRange RegRange = RegTok.getLocRange();
2296
2297 StringRef FixedName = StringSwitch<StringRef>(Name)
2298 .Case("t4", "t0")
2299 .Case("t5", "t1")
2300 .Case("t6", "t2")
2301 .Case("t7", "t3")
2302 .Default("");
2303 assert(FixedName != "" && "Register name is not one of t4-t7.");
2304
2305 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
2306 "Did you mean $" + FixedName + "?", RegRange);
2307 }
2308
Toma Tabacufda445c2014-09-15 15:33:01 +00002309 // Although SGI documentation just cuts out t0-t3 for n32/n64,
2310 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
2311 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
2312 if (8 <= CC && CC <= 11)
2313 CC += 4;
2314
2315 if (CC == -1)
2316 CC = StringSwitch<unsigned>(Name)
2317 .Case("a4", 8)
2318 .Case("a5", 9)
2319 .Case("a6", 10)
2320 .Case("a7", 11)
2321 .Case("kt0", 26)
2322 .Case("kt1", 27)
2323 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002324
2325 return CC;
2326}
Jack Carterd0bd6422013-04-18 00:41:53 +00002327
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002328int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
2329 int CC;
2330
2331 CC = StringSwitch<unsigned>(Name)
2332 .Case("hwr_cpunum", 0)
2333 .Case("hwr_synci_step", 1)
2334 .Case("hwr_cc", 2)
2335 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00002336 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002337 .Default(-1);
2338
2339 return CC;
2340}
2341
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002342int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002343
Jack Cartera63b16a2012-09-07 00:23:42 +00002344 if (Name[0] == 'f') {
2345 StringRef NumString = Name.substr(1);
2346 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002347 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002348 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002349 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00002350 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002351 return IntVal;
2352 }
2353 return -1;
2354}
Jack Cartera63b16a2012-09-07 00:23:42 +00002355
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002356int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
2357
2358 if (Name.startswith("fcc")) {
2359 StringRef NumString = Name.substr(3);
2360 unsigned IntVal;
2361 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002362 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002363 if (IntVal > 7) // There are only 8 fcc registers.
2364 return -1;
2365 return IntVal;
2366 }
2367 return -1;
2368}
2369
2370int MipsAsmParser::matchACRegisterName(StringRef Name) {
2371
Akira Hatanaka274d24c2013-08-14 01:15:52 +00002372 if (Name.startswith("ac")) {
2373 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002374 unsigned IntVal;
2375 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002376 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002377 if (IntVal > 3) // There are only 3 acc registers.
2378 return -1;
2379 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00002380 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002381 return -1;
2382}
Jack Carterd0bd6422013-04-18 00:41:53 +00002383
Jack Carter5dc8ac92013-09-25 23:50:44 +00002384int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
2385 unsigned IntVal;
2386
2387 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2388 return -1;
2389
2390 if (IntVal > 31)
2391 return -1;
2392
2393 return IntVal;
2394}
2395
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002396int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
2397 int CC;
2398
2399 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00002400 .Case("msair", 0)
2401 .Case("msacsr", 1)
2402 .Case("msaaccess", 2)
2403 .Case("msasave", 3)
2404 .Case("msamodify", 4)
2405 .Case("msarequest", 5)
2406 .Case("msamap", 6)
2407 .Case("msaunmap", 7)
2408 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002409
2410 return CC;
2411}
2412
Toma Tabacu89a712b2015-04-15 10:48:56 +00002413unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00002414 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00002415 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002416 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00002417 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00002418 return 0;
2419 }
2420 unsigned AT = getReg(
2421 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00002422 return AT;
2423}
Jack Carter0b744b32012-10-04 02:29:46 +00002424
Jack Carterd0bd6422013-04-18 00:41:53 +00002425unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00002426 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00002427}
2428
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002429unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002430 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00002431 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002432}
2433
Jack Carter873c7242013-01-12 01:03:14 +00002434int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002435 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00002436 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00002437 return -1;
2438
Jack Carter873c7242013-01-12 01:03:14 +00002439 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00002440}
2441
Toma Tabacu13964452014-09-04 13:23:44 +00002442bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002443 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002444 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002445
Jack Carter30a59822012-10-04 04:03:53 +00002446 // Check if the current operand has a custom associated parser, if so, try to
2447 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00002448 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2449 if (ResTy == MatchOperand_Success)
2450 return false;
2451 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2452 // there was a match, but an error occurred, in which case, just return that
2453 // the operand parsing failed.
2454 if (ResTy == MatchOperand_ParseFail)
2455 return true;
2456
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002457 DEBUG(dbgs() << ".. Generic Parser\n");
2458
Jack Carterb4dbc172012-09-05 23:34:03 +00002459 switch (getLexer().getKind()) {
2460 default:
2461 Error(Parser.getTok().getLoc(), "unexpected token in operand");
2462 return true;
2463 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002464 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00002465 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00002466
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002467 // Almost all registers have been parsed by custom parsers. There is only
2468 // one exception to this. $zero (and it's alias $0) will reach this point
2469 // for div, divu, and similar instructions because it is not an operand
2470 // to the instruction definition but an explicit register. Special case
2471 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00002472 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00002473 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002474
Jack Carterd0bd6422013-04-18 00:41:53 +00002475 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00002476 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002477 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00002478 return true;
2479
Jack Carter873c7242013-01-12 01:03:14 +00002480 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00002481 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00002482 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00002483 const MCExpr *Res =
2484 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00002485
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002486 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002487 return false;
2488 }
Vladimir Medic4c299852013-11-06 11:27:05 +00002489 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00002490 case AsmToken::LParen:
2491 case AsmToken::Minus:
2492 case AsmToken::Plus:
2493 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002494 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00002495 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002496 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002497 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002498 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00002499 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00002500 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002501 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002502 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002503 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00002504 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00002505 return true;
2506
Jack Carter873c7242013-01-12 01:03:14 +00002507 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2508
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002509 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00002510 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002511 } // case AsmToken::Percent
2512 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00002513 return true;
2514}
2515
Vladimir Medic4c299852013-11-06 11:27:05 +00002516const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00002517 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00002518 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00002519 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002520 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00002521 // It's a constant, evaluate reloc value.
2522 int16_t Val;
2523 switch (getVariantKind(RelocStr)) {
2524 case MCSymbolRefExpr::VK_Mips_ABS_LO:
2525 // Get the 1st 16-bits.
2526 Val = MCE->getValue() & 0xffff;
2527 break;
2528 case MCSymbolRefExpr::VK_Mips_ABS_HI:
2529 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2530 // 16 bits being negative.
2531 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2532 break;
2533 case MCSymbolRefExpr::VK_Mips_HIGHER:
2534 // Get the 3rd 16-bits.
2535 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2536 break;
2537 case MCSymbolRefExpr::VK_Mips_HIGHEST:
2538 // Get the 4th 16-bits.
2539 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2540 break;
2541 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00002542 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00002543 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00002544 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002545 }
2546
Jack Carterb5cf5902013-04-17 00:18:04 +00002547 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002548 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00002549 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00002550 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00002551 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002552 return Res;
2553 }
2554
2555 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00002556 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2557
Sasa Stankovic06c47802014-04-03 10:37:45 +00002558 // Try to create target expression.
2559 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
2560 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002561
Jack Carterd0bd6422013-04-18 00:41:53 +00002562 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2563 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00002564 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
2565 return Res;
2566 }
2567
2568 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002569 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
2570 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
2571 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002572 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002573 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002574 return Expr;
2575}
2576
2577bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2578
2579 switch (Expr->getKind()) {
2580 case MCExpr::Constant:
2581 return true;
2582 case MCExpr::SymbolRef:
2583 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2584 case MCExpr::Binary:
2585 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2586 if (!isEvaluated(BE->getLHS()))
2587 return false;
2588 return isEvaluated(BE->getRHS());
2589 }
2590 case MCExpr::Unary:
2591 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002592 case MCExpr::Target:
2593 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002594 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002595 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002596}
Jack Carterd0bd6422013-04-18 00:41:53 +00002597
Jack Carterb5cf5902013-04-17 00:18:04 +00002598bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002599 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00002600 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002601 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002602 if (Tok.isNot(AsmToken::Identifier))
2603 return true;
2604
Yaron Keren075759a2015-03-30 15:42:36 +00002605 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00002606
Jack Carterd0bd6422013-04-18 00:41:53 +00002607 Parser.Lex(); // Eat the identifier.
2608 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002609 const MCExpr *IdVal;
2610 SMLoc EndLoc;
2611
2612 if (getLexer().getKind() == AsmToken::LParen) {
2613 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002614 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002615 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002616 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002617 const AsmToken &nextTok = Parser.getTok();
2618 if (nextTok.isNot(AsmToken::Identifier))
2619 return true;
2620 Str += "(%";
2621 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002622 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002623 if (getLexer().getKind() != AsmToken::LParen)
2624 return true;
2625 } else
2626 break;
2627 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002628 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002629 return true;
2630
2631 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002632 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002633
2634 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002635 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002636
Jack Carterd0bd6422013-04-18 00:41:53 +00002637 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002638 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002639}
2640
Jack Carterb4dbc172012-09-05 23:34:03 +00002641bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2642 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002643 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002644 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002645 if (ResTy == MatchOperand_Success) {
2646 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002647 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002648 StartLoc = Operand.getStartLoc();
2649 EndLoc = Operand.getEndLoc();
2650
2651 // AFAIK, we only support numeric registers and named GPR's in CFI
2652 // directives.
2653 // Don't worry about eating tokens before failing. Using an unrecognised
2654 // register is a parse error.
2655 if (Operand.isGPRAsmReg()) {
2656 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002657 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002658 }
2659
2660 return (RegNo == (unsigned)-1);
2661 }
2662
2663 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002664 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002665}
2666
Jack Carterb5cf5902013-04-17 00:18:04 +00002667bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002668 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00002669 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002670 bool Result = true;
2671
2672 while (getLexer().getKind() == AsmToken::LParen)
2673 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002674
Jack Carterd0bd6422013-04-18 00:41:53 +00002675 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002676 default:
2677 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002678 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002679 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002680 case AsmToken::Integer:
2681 case AsmToken::Minus:
2682 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002683 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002684 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002685 else
2686 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002687 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002688 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002689 break;
Jack Carter873c7242013-01-12 01:03:14 +00002690 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002691 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002692 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002693 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002694}
2695
David Blaikie960ea3f2014-06-08 16:18:35 +00002696MipsAsmParser::OperandMatchResultTy
2697MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002698 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002699 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002700 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002701 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002702 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002703 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002704 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002705 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002706
Jack Carterb5cf5902013-04-17 00:18:04 +00002707 if (getLexer().getKind() == AsmToken::LParen) {
2708 Parser.Lex();
2709 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002710 }
2711
Jack Carterb5cf5902013-04-17 00:18:04 +00002712 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002713 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002714 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002715
Jack Carterd0bd6422013-04-18 00:41:53 +00002716 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002717 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002718 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2719 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002720 SMLoc E =
2721 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002722 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002723 return MatchOperand_Success;
2724 }
2725 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002726 SMLoc E =
2727 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002728
Jack Carterd0bd6422013-04-18 00:41:53 +00002729 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002730 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002731 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002732 S, E, *this);
2733 Operands.push_back(
2734 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002735 return MatchOperand_Success;
2736 }
2737 Error(Parser.getTok().getLoc(), "'(' expected");
2738 return MatchOperand_ParseFail;
2739 }
2740
Jack Carterd0bd6422013-04-18 00:41:53 +00002741 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002742 }
2743
Toma Tabacu13964452014-09-04 13:23:44 +00002744 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002745 if (Res != MatchOperand_Success)
2746 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002747
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002748 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002749 Error(Parser.getTok().getLoc(), "')' expected");
2750 return MatchOperand_ParseFail;
2751 }
2752
Jack Carter873c7242013-01-12 01:03:14 +00002753 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2754
Jack Carterd0bd6422013-04-18 00:41:53 +00002755 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002756
Craig Topper062a2ba2014-04-25 05:30:21 +00002757 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002758 IdVal = MCConstantExpr::Create(0, getContext());
2759
Jack Carterd0bd6422013-04-18 00:41:53 +00002760 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002761 std::unique_ptr<MipsOperand> op(
2762 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002763 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002764 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002765 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002766 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002767 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2768 int64_t Imm;
2769 if (IdVal->EvaluateAsAbsolute(Imm))
2770 IdVal = MCConstantExpr::Create(Imm, getContext());
2771 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2772 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2773 getContext());
2774 }
2775
David Blaikie960ea3f2014-06-08 16:18:35 +00002776 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002777 return MatchOperand_Success;
2778}
2779
David Blaikie960ea3f2014-06-08 16:18:35 +00002780bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002781 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00002782 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2783 if (Sym) {
2784 SMLoc S = Parser.getTok().getLoc();
2785 const MCExpr *Expr;
2786 if (Sym->isVariable())
2787 Expr = Sym->getVariableValue();
2788 else
2789 return false;
2790 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002791 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002792 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002793 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002794 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002795 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002796 if (ResTy == MatchOperand_Success) {
2797 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002798 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002799 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002800 llvm_unreachable("Should never ParseFail");
2801 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002802 }
2803 } else if (Expr->getKind() == MCExpr::Constant) {
2804 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002805 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002806 Operands.push_back(
2807 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002808 return true;
2809 }
2810 }
2811 return false;
2812}
Jack Carterd0bd6422013-04-18 00:41:53 +00002813
Jack Carter873c7242013-01-12 01:03:14 +00002814MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002815MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002816 StringRef Identifier,
2817 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002818 int Index = matchCPURegisterName(Identifier);
2819 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002820 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002821 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2822 return MatchOperand_Success;
2823 }
2824
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002825 Index = matchHWRegsRegisterName(Identifier);
2826 if (Index != -1) {
2827 Operands.push_back(MipsOperand::createHWRegsReg(
2828 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2829 return MatchOperand_Success;
2830 }
2831
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002832 Index = matchFPURegisterName(Identifier);
2833 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002834 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002835 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2836 return MatchOperand_Success;
2837 }
2838
2839 Index = matchFCCRegisterName(Identifier);
2840 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002841 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002842 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2843 return MatchOperand_Success;
2844 }
2845
2846 Index = matchACRegisterName(Identifier);
2847 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002848 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002849 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2850 return MatchOperand_Success;
2851 }
2852
2853 Index = matchMSA128RegisterName(Identifier);
2854 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002855 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002856 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2857 return MatchOperand_Success;
2858 }
2859
2860 Index = matchMSA128CtrlRegisterName(Identifier);
2861 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002862 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002863 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2864 return MatchOperand_Success;
2865 }
2866
2867 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002868}
2869
2870MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002871MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002872 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00002873 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002874
2875 if (Token.is(AsmToken::Identifier)) {
2876 DEBUG(dbgs() << ".. identifier\n");
2877 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002878 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002879 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002880 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002881 } else if (Token.is(AsmToken::Integer)) {
2882 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002883 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002884 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2885 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002886 return MatchOperand_Success;
2887 }
2888
2889 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2890
2891 return MatchOperand_NoMatch;
2892}
2893
David Blaikie960ea3f2014-06-08 16:18:35 +00002894MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002895MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002896 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002897 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002898
2899 auto Token = Parser.getTok();
2900
2901 SMLoc S = Token.getLoc();
2902
2903 if (Token.isNot(AsmToken::Dollar)) {
2904 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2905 if (Token.is(AsmToken::Identifier)) {
2906 if (searchSymbolAlias(Operands))
2907 return MatchOperand_Success;
2908 }
2909 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2910 return MatchOperand_NoMatch;
2911 }
2912 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002913
Toma Tabacu13964452014-09-04 13:23:44 +00002914 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002915 if (ResTy == MatchOperand_Success) {
2916 Parser.Lex(); // $
2917 Parser.Lex(); // identifier
2918 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002919 return ResTy;
2920}
2921
2922MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002923MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002924 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002925 switch (getLexer().getKind()) {
2926 default:
2927 return MatchOperand_NoMatch;
2928 case AsmToken::LParen:
2929 case AsmToken::Minus:
2930 case AsmToken::Plus:
2931 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002932 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002933 case AsmToken::String:
2934 break;
2935 }
2936
2937 const MCExpr *IdVal;
2938 SMLoc S = Parser.getTok().getLoc();
2939 if (getParser().parseExpression(IdVal))
2940 return MatchOperand_ParseFail;
2941
2942 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2943 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2944 return MatchOperand_Success;
2945}
2946
David Blaikie960ea3f2014-06-08 16:18:35 +00002947MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002948MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002949 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002950 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002951
2952 SMLoc S = getLexer().getLoc();
2953
2954 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002955 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002956 if (ResTy != MatchOperand_NoMatch)
2957 return ResTy;
2958
Daniel Sanders315386c2014-04-01 10:40:14 +00002959 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002960 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002961 if (ResTy != MatchOperand_NoMatch)
2962 return ResTy;
2963
Daniel Sandersffd84362014-04-01 10:41:48 +00002964 const MCExpr *Expr = nullptr;
2965 if (Parser.parseExpression(Expr)) {
2966 // We have no way of knowing if a symbol was consumed so we must ParseFail
2967 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002968 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002969 Operands.push_back(
2970 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002971 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002972}
2973
Vladimir Medic2b953d02013-10-01 09:48:56 +00002974MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002975MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002976 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00002977 const MCExpr *IdVal;
2978 // If the first token is '$' we may have register operand.
2979 if (Parser.getTok().is(AsmToken::Dollar))
2980 return MatchOperand_NoMatch;
2981 SMLoc S = Parser.getTok().getLoc();
2982 if (getParser().parseExpression(IdVal))
2983 return MatchOperand_ParseFail;
2984 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002985 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002986 int64_t Val = MCE->getValue();
2987 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2988 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002989 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002990 return MatchOperand_Success;
2991}
2992
Matheus Almeida779c5932013-11-18 12:32:49 +00002993MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002994MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002995 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00002996 switch (getLexer().getKind()) {
2997 default:
2998 return MatchOperand_NoMatch;
2999 case AsmToken::LParen:
3000 case AsmToken::Plus:
3001 case AsmToken::Minus:
3002 case AsmToken::Integer:
3003 break;
3004 }
3005
3006 const MCExpr *Expr;
3007 SMLoc S = Parser.getTok().getLoc();
3008
3009 if (getParser().parseExpression(Expr))
3010 return MatchOperand_ParseFail;
3011
3012 int64_t Val;
3013 if (!Expr->EvaluateAsAbsolute(Val)) {
3014 Error(S, "expected immediate value");
3015 return MatchOperand_ParseFail;
3016 }
3017
3018 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
3019 // and because the CPU always adds one to the immediate field, the allowed
3020 // range becomes 1..4. We'll only check the range here and will deal
3021 // with the addition/subtraction when actually decoding/encoding
3022 // the instruction.
3023 if (Val < 1 || Val > 4) {
3024 Error(S, "immediate not in range (1..4)");
3025 return MatchOperand_ParseFail;
3026 }
3027
Jack Carter3b2c96e2014-01-22 23:31:38 +00003028 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003029 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00003030 return MatchOperand_Success;
3031}
3032
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00003033MipsAsmParser::OperandMatchResultTy
3034MipsAsmParser::parseRegisterList(OperandVector &Operands) {
3035 MCAsmParser &Parser = getParser();
3036 SmallVector<unsigned, 10> Regs;
3037 unsigned RegNo;
3038 unsigned PrevReg = Mips::NoRegister;
3039 bool RegRange = false;
3040 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3041
3042 if (Parser.getTok().isNot(AsmToken::Dollar))
3043 return MatchOperand_ParseFail;
3044
3045 SMLoc S = Parser.getTok().getLoc();
3046 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
3047 SMLoc E = getLexer().getLoc();
3048 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
3049 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
3050 if (RegRange) {
3051 // Remove last register operand because registers from register range
3052 // should be inserted first.
3053 if (RegNo == Mips::RA) {
3054 Regs.push_back(RegNo);
3055 } else {
3056 unsigned TmpReg = PrevReg + 1;
3057 while (TmpReg <= RegNo) {
3058 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
3059 Error(E, "invalid register operand");
3060 return MatchOperand_ParseFail;
3061 }
3062
3063 PrevReg = TmpReg;
3064 Regs.push_back(TmpReg++);
3065 }
3066 }
3067
3068 RegRange = false;
3069 } else {
3070 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
3071 (RegNo != Mips::RA)) {
3072 Error(E, "$16 or $31 expected");
3073 return MatchOperand_ParseFail;
3074 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
3075 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3076 Error(E, "invalid register operand");
3077 return MatchOperand_ParseFail;
3078 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
3079 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3080 Error(E, "consecutive register numbers expected");
3081 return MatchOperand_ParseFail;
3082 }
3083
3084 Regs.push_back(RegNo);
3085 }
3086
3087 if (Parser.getTok().is(AsmToken::Minus))
3088 RegRange = true;
3089
3090 if (!Parser.getTok().isNot(AsmToken::Minus) &&
3091 !Parser.getTok().isNot(AsmToken::Comma)) {
3092 Error(E, "',' or '-' expected");
3093 return MatchOperand_ParseFail;
3094 }
3095
3096 Lex(); // Consume comma or minus
3097 if (Parser.getTok().isNot(AsmToken::Dollar))
3098 break;
3099
3100 PrevReg = RegNo;
3101 }
3102
3103 SMLoc E = Parser.getTok().getLoc();
3104 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3105 parseMemOperand(Operands);
3106 return MatchOperand_Success;
3107}
3108
Zoran Jovanovic2deca342014-12-16 14:59:10 +00003109MipsAsmParser::OperandMatchResultTy
3110MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
3111 MCAsmParser &Parser = getParser();
3112
3113 SMLoc S = Parser.getTok().getLoc();
3114 if (parseAnyRegister(Operands) != MatchOperand_Success)
3115 return MatchOperand_ParseFail;
3116
3117 SMLoc E = Parser.getTok().getLoc();
3118 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
3119 unsigned Reg = Op.getGPR32Reg();
3120 Operands.pop_back();
3121 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
3122 return MatchOperand_Success;
3123}
3124
Zoran Jovanovic41688672015-02-10 16:36:20 +00003125MipsAsmParser::OperandMatchResultTy
3126MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
3127 MCAsmParser &Parser = getParser();
3128 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3129 SmallVector<unsigned, 10> Regs;
3130
3131 if (Parser.getTok().isNot(AsmToken::Dollar))
3132 return MatchOperand_ParseFail;
3133
3134 SMLoc S = Parser.getTok().getLoc();
3135
3136 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3137 return MatchOperand_ParseFail;
3138
3139 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3140 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3141 Regs.push_back(RegNo);
3142
3143 SMLoc E = Parser.getTok().getLoc();
3144 if (Parser.getTok().isNot(AsmToken::Comma)) {
3145 Error(E, "',' expected");
3146 return MatchOperand_ParseFail;
3147 }
3148
3149 // Remove comma.
3150 Parser.Lex();
3151
3152 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3153 return MatchOperand_ParseFail;
3154
3155 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3156 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3157 Regs.push_back(RegNo);
3158
3159 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3160
3161 return MatchOperand_Success;
3162}
3163
Jack Carterdc1e35d2012-09-06 20:00:02 +00003164MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
3165
Vladimir Medic4c299852013-11-06 11:27:05 +00003166 MCSymbolRefExpr::VariantKind VK =
3167 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
3168 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
3169 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
3170 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
3171 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
3172 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
3173 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
3174 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
3175 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
3176 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
3177 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
3178 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
3179 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
3180 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
3181 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
3182 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
3183 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
3184 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00003185 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
3186 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
3187 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
3188 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
3189 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
3190 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00003191 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
3192 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00003193 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003194
Matheus Almeida2852af82014-04-22 10:15:54 +00003195 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00003196
Jack Carterdc1e35d2012-09-06 20:00:02 +00003197 return VK;
3198}
Jack Cartera63b16a2012-09-07 00:23:42 +00003199
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003200/// Sometimes (i.e. load/stores) the operand may be followed immediately by
3201/// either this.
3202/// ::= '(', register, ')'
3203/// handle it before we iterate so we don't get tripped up by the lack of
3204/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003205bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003206 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003207 if (getLexer().is(AsmToken::LParen)) {
3208 Operands.push_back(
3209 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
3210 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003211 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003212 SMLoc Loc = getLexer().getLoc();
3213 Parser.eatToEndOfStatement();
3214 return Error(Loc, "unexpected token in argument list");
3215 }
3216 if (Parser.getTok().isNot(AsmToken::RParen)) {
3217 SMLoc Loc = getLexer().getLoc();
3218 Parser.eatToEndOfStatement();
3219 return Error(Loc, "unexpected token, expected ')'");
3220 }
3221 Operands.push_back(
3222 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
3223 Parser.Lex();
3224 }
3225 return false;
3226}
3227
3228/// Sometimes (i.e. in MSA) the operand may be followed immediately by
3229/// either one of these.
3230/// ::= '[', register, ']'
3231/// ::= '[', integer, ']'
3232/// handle it before we iterate so we don't get tripped up by the lack of
3233/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003234bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00003235 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003236 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003237 if (getLexer().is(AsmToken::LBrac)) {
3238 Operands.push_back(
3239 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
3240 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003241 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003242 SMLoc Loc = getLexer().getLoc();
3243 Parser.eatToEndOfStatement();
3244 return Error(Loc, "unexpected token in argument list");
3245 }
3246 if (Parser.getTok().isNot(AsmToken::RBrac)) {
3247 SMLoc Loc = getLexer().getLoc();
3248 Parser.eatToEndOfStatement();
3249 return Error(Loc, "unexpected token, expected ']'");
3250 }
3251 Operands.push_back(
3252 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
3253 Parser.Lex();
3254 }
3255 return false;
3256}
3257
David Blaikie960ea3f2014-06-08 16:18:35 +00003258bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
3259 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003260 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003261 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003262
3263 // We have reached first instruction, module directive are now forbidden.
3264 getTargetStreamer().forbidModuleDirective();
3265
Vladimir Medic74593e62013-07-17 15:00:42 +00003266 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00003267 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00003268 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00003269 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00003270 }
Vladimir Medic64828a12013-07-16 10:07:14 +00003271 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003272 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003273
3274 // Read the remaining operands.
3275 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3276 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003277 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003278 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003279 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003280 return Error(Loc, "unexpected token in argument list");
3281 }
Toma Tabacu13964452014-09-04 13:23:44 +00003282 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003283 return true;
3284 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00003285
Jack Carterd0bd6422013-04-18 00:41:53 +00003286 while (getLexer().is(AsmToken::Comma)) {
3287 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00003288 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003289 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003290 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003291 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003292 return Error(Loc, "unexpected token in argument list");
3293 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003294 // Parse bracket and parenthesis suffixes before we iterate
3295 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00003296 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003297 return true;
3298 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00003299 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003300 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003301 }
3302 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003303 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3304 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003305 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003306 return Error(Loc, "unexpected token in argument list");
3307 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003308 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00003309 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00003310}
3311
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003312bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003313 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003314 SMLoc Loc = getLexer().getLoc();
3315 Parser.eatToEndOfStatement();
3316 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00003317}
3318
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003319bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003320 return Error(Loc, ErrorMsg);
3321}
3322
Jack Carter0b744b32012-10-04 02:29:46 +00003323bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003324 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003325 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00003326
3327 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00003328 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00003329
3330 Parser.Lex(); // Eat "noat".
3331
Jack Carterd0bd6422013-04-18 00:41:53 +00003332 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003333 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003334 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003335 return false;
3336 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003337
3338 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003339 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003340 return false;
3341}
Jack Carterd0bd6422013-04-18 00:41:53 +00003342
Jack Carter0b744b32012-10-04 02:29:46 +00003343bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00003344 // Line can be: ".set at", which sets $at to $1
3345 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00003346 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00003347 Parser.Lex(); // Eat "at".
3348
Jack Carter0b744b32012-10-04 02:29:46 +00003349 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003350 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00003351 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00003352
3353 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003354 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003355 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00003356 }
3357
3358 if (getLexer().isNot(AsmToken::Equal)) {
3359 reportParseError("unexpected token, expected equals sign");
3360 return false;
3361 }
3362 Parser.Lex(); // Eat "=".
3363
3364 if (getLexer().isNot(AsmToken::Dollar)) {
3365 if (getLexer().is(AsmToken::EndOfStatement)) {
3366 reportParseError("no register specified");
3367 return false;
3368 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00003369 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00003370 return false;
3371 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003372 }
3373 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00003374
Toma Tabacu16a74492015-02-13 10:30:57 +00003375 // Find out what "reg" is.
3376 unsigned AtRegNo;
3377 const AsmToken &Reg = Parser.getTok();
3378 if (Reg.is(AsmToken::Identifier)) {
3379 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
3380 } else if (Reg.is(AsmToken::Integer)) {
3381 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00003382 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00003383 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00003384 return false;
3385 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003386
3387 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00003388 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003389 reportParseError("invalid register");
3390 return false;
3391 }
3392 Parser.Lex(); // Eat "reg".
3393
3394 // If this is not the end of the statement, report an error.
3395 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3396 reportParseError("unexpected token, expected end of statement");
3397 return false;
3398 }
3399
3400 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
3401
3402 Parser.Lex(); // Consume the EndOfStatement.
3403 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003404}
3405
3406bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003407 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003408 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003409 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003410 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003411 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003412 return false;
3413 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003414 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00003415 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003416 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003417 return false;
3418}
3419
3420bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003421 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003422 Parser.Lex();
3423 // If this is not the end of the statement, report an error.
3424 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003425 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003426 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003427 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003428 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00003429 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003430 Parser.Lex(); // Consume the EndOfStatement.
3431 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003432}
3433
3434bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003435 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003436 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003437 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003438 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003439 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003440 return false;
3441 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003442 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003443 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003444 return false;
3445}
3446
3447bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003448 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003449 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003450 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003451 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003452 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003453 return false;
3454 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003455 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00003456 reportParseError("`noreorder' must be set before `nomacro'");
3457 return false;
3458 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003459 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003460 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003461 return false;
3462}
Jack Carterd76b2372013-03-21 21:44:16 +00003463
Daniel Sanders44934432014-08-07 12:03:36 +00003464bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003465 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003466 Parser.Lex();
3467
3468 // If this is not the end of the statement, report an error.
3469 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003470 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003471
3472 setFeatureBits(Mips::FeatureMSA, "msa");
3473 getTargetStreamer().emitDirectiveSetMsa();
3474 return false;
3475}
3476
3477bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003478 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003479 Parser.Lex();
3480
3481 // If this is not the end of the statement, report an error.
3482 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003483 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003484
3485 clearFeatureBits(Mips::FeatureMSA, "msa");
3486 getTargetStreamer().emitDirectiveSetNoMsa();
3487 return false;
3488}
3489
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003490bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003491 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003492 Parser.Lex(); // Eat "nodsp".
3493
3494 // If this is not the end of the statement, report an error.
3495 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3496 reportParseError("unexpected token, expected end of statement");
3497 return false;
3498 }
3499
3500 clearFeatureBits(Mips::FeatureDSP, "dsp");
3501 getTargetStreamer().emitDirectiveSetNoDsp();
3502 return false;
3503}
3504
Toma Tabacucc2502d2014-11-04 17:18:07 +00003505bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003506 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003507 Parser.Lex(); // Eat "mips16".
3508
Jack Carter39536722014-01-22 23:08:42 +00003509 // If this is not the end of the statement, report an error.
3510 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003511 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00003512 return false;
3513 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00003514
3515 setFeatureBits(Mips::FeatureMips16, "mips16");
3516 getTargetStreamer().emitDirectiveSetMips16();
3517 Parser.Lex(); // Consume the EndOfStatement.
3518 return false;
3519}
3520
3521bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003522 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003523 Parser.Lex(); // Eat "nomips16".
3524
3525 // If this is not the end of the statement, report an error.
3526 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3527 reportParseError("unexpected token, expected end of statement");
3528 return false;
3529 }
3530
3531 clearFeatureBits(Mips::FeatureMips16, "mips16");
3532 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00003533 Parser.Lex(); // Consume the EndOfStatement.
3534 return false;
3535}
3536
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003537bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003538 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003539 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003540 // Line can be: .set fp=32
3541 // .set fp=xx
3542 // .set fp=64
3543 Parser.Lex(); // Eat fp token
3544 AsmToken Tok = Parser.getTok();
3545 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003546 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003547 return false;
3548 }
3549 Parser.Lex(); // Eat '=' token.
3550 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003551
3552 if (!parseFpABIValue(FpAbiVal, ".set"))
3553 return false;
3554
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003555 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003556 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003557 return false;
3558 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003559 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003560 Parser.Lex(); // Consume the EndOfStatement.
3561 return false;
3562}
3563
Toma Tabacu9db22db2014-09-09 10:15:38 +00003564bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003565 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003566 SMLoc Loc = getLexer().getLoc();
3567
3568 Parser.Lex();
3569 if (getLexer().isNot(AsmToken::EndOfStatement))
3570 return reportParseError("unexpected token, expected end of statement");
3571
3572 // Always keep an element on the options "stack" to prevent the user
3573 // from changing the initial options. This is how we remember them.
3574 if (AssemblerOptions.size() == 2)
3575 return reportParseError(Loc, ".set pop with no .set push");
3576
3577 AssemblerOptions.pop_back();
3578 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
3579
3580 getTargetStreamer().emitDirectiveSetPop();
3581 return false;
3582}
3583
3584bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003585 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003586 Parser.Lex();
3587 if (getLexer().isNot(AsmToken::EndOfStatement))
3588 return reportParseError("unexpected token, expected end of statement");
3589
3590 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00003591 AssemblerOptions.push_back(
3592 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00003593
3594 getTargetStreamer().emitDirectiveSetPush();
3595 return false;
3596}
3597
Jack Carterd76b2372013-03-21 21:44:16 +00003598bool MipsAsmParser::parseSetAssignment() {
3599 StringRef Name;
3600 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00003601 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00003602
3603 if (Parser.parseIdentifier(Name))
3604 reportParseError("expected identifier after .set");
3605
3606 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003607 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00003608 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00003609
Jack Carter3b2c96e2014-01-22 23:31:38 +00003610 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00003611 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00003612
Toma Tabacuf25949b2015-04-07 13:59:39 +00003613 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00003614 Sym->setVariableValue(Value);
3615
3616 return false;
3617}
Jack Carterd0bd6422013-04-18 00:41:53 +00003618
Toma Tabacu26647792014-09-09 12:52:14 +00003619bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003620 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00003621 Parser.Lex();
3622 if (getLexer().isNot(AsmToken::EndOfStatement))
3623 return reportParseError("unexpected token, expected end of statement");
3624
3625 // Reset assembler options to their initial values.
3626 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
3627 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
3628
3629 getTargetStreamer().emitDirectiveSetMips0();
3630 return false;
3631}
3632
Toma Tabacu85618b32014-08-19 14:22:52 +00003633bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003634 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00003635 Parser.Lex();
3636 if (getLexer().isNot(AsmToken::Equal))
3637 return reportParseError("unexpected token, expected equals sign");
3638
3639 Parser.Lex();
3640 StringRef Arch;
3641 if (Parser.parseIdentifier(Arch))
3642 return reportParseError("expected arch identifier");
3643
3644 StringRef ArchFeatureName =
3645 StringSwitch<StringRef>(Arch)
3646 .Case("mips1", "mips1")
3647 .Case("mips2", "mips2")
3648 .Case("mips3", "mips3")
3649 .Case("mips4", "mips4")
3650 .Case("mips5", "mips5")
3651 .Case("mips32", "mips32")
3652 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003653 .Case("mips32r3", "mips32r3")
3654 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003655 .Case("mips32r6", "mips32r6")
3656 .Case("mips64", "mips64")
3657 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003658 .Case("mips64r3", "mips64r3")
3659 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003660 .Case("mips64r6", "mips64r6")
3661 .Case("cnmips", "cnmips")
3662 .Case("r4000", "mips3") // This is an implementation of Mips3.
3663 .Default("");
3664
3665 if (ArchFeatureName.empty())
3666 return reportParseError("unsupported architecture");
3667
3668 selectArch(ArchFeatureName);
3669 getTargetStreamer().emitDirectiveSetArch(Arch);
3670 return false;
3671}
3672
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003673bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003674 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003675 Parser.Lex();
3676 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003677 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003678
Matheus Almeida2852af82014-04-22 10:15:54 +00003679 switch (Feature) {
3680 default:
3681 llvm_unreachable("Unimplemented feature");
3682 case Mips::FeatureDSP:
3683 setFeatureBits(Mips::FeatureDSP, "dsp");
3684 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003685 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003686 case Mips::FeatureMicroMips:
3687 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003688 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003689 case Mips::FeatureMips1:
3690 selectArch("mips1");
3691 getTargetStreamer().emitDirectiveSetMips1();
3692 break;
3693 case Mips::FeatureMips2:
3694 selectArch("mips2");
3695 getTargetStreamer().emitDirectiveSetMips2();
3696 break;
3697 case Mips::FeatureMips3:
3698 selectArch("mips3");
3699 getTargetStreamer().emitDirectiveSetMips3();
3700 break;
3701 case Mips::FeatureMips4:
3702 selectArch("mips4");
3703 getTargetStreamer().emitDirectiveSetMips4();
3704 break;
3705 case Mips::FeatureMips5:
3706 selectArch("mips5");
3707 getTargetStreamer().emitDirectiveSetMips5();
3708 break;
3709 case Mips::FeatureMips32:
3710 selectArch("mips32");
3711 getTargetStreamer().emitDirectiveSetMips32();
3712 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003713 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003714 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003715 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003716 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003717 case Mips::FeatureMips32r3:
3718 selectArch("mips32r3");
3719 getTargetStreamer().emitDirectiveSetMips32R3();
3720 break;
3721 case Mips::FeatureMips32r5:
3722 selectArch("mips32r5");
3723 getTargetStreamer().emitDirectiveSetMips32R5();
3724 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003725 case Mips::FeatureMips32r6:
3726 selectArch("mips32r6");
3727 getTargetStreamer().emitDirectiveSetMips32R6();
3728 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003729 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003730 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00003731 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003732 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003733 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003734 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003735 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003736 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003737 case Mips::FeatureMips64r3:
3738 selectArch("mips64r3");
3739 getTargetStreamer().emitDirectiveSetMips64R3();
3740 break;
3741 case Mips::FeatureMips64r5:
3742 selectArch("mips64r5");
3743 getTargetStreamer().emitDirectiveSetMips64R5();
3744 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003745 case Mips::FeatureMips64r6:
3746 selectArch("mips64r6");
3747 getTargetStreamer().emitDirectiveSetMips64R6();
3748 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003749 }
3750 return false;
3751}
3752
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003753bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003754 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003755 if (getLexer().isNot(AsmToken::Comma)) {
3756 SMLoc Loc = getLexer().getLoc();
3757 Parser.eatToEndOfStatement();
3758 return Error(Loc, ErrorStr);
3759 }
3760
Matheus Almeida2852af82014-04-22 10:15:54 +00003761 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003762 return true;
3763}
3764
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003765bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003766 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00003767 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003768
Toma Tabacudde4c462014-11-06 10:02:45 +00003769 if (inMips16Mode()) {
3770 reportParseError(".cpload is not supported in Mips16 mode");
3771 return false;
3772 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003773
David Blaikie960ea3f2014-06-08 16:18:35 +00003774 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00003775 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003776 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3777 reportParseError("expected register containing function address");
3778 return false;
3779 }
3780
David Blaikie960ea3f2014-06-08 16:18:35 +00003781 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
3782 if (!RegOpnd.isGPRAsmReg()) {
3783 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003784 return false;
3785 }
3786
Toma Tabacudde4c462014-11-06 10:02:45 +00003787 // If this is not the end of the statement, report an error.
3788 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3789 reportParseError("unexpected token, expected end of statement");
3790 return false;
3791 }
3792
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003793 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003794 return false;
3795}
3796
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003797bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003798 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003799 unsigned FuncReg;
3800 unsigned Save;
3801 bool SaveIsReg = true;
3802
Matheus Almeida7e815762014-06-18 13:08:59 +00003803 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003804 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003805 if (ResTy == MatchOperand_NoMatch) {
3806 reportParseError("expected register containing function address");
3807 Parser.eatToEndOfStatement();
3808 return false;
3809 }
3810
3811 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3812 if (!FuncRegOpnd.isGPRAsmReg()) {
3813 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3814 Parser.eatToEndOfStatement();
3815 return false;
3816 }
3817
3818 FuncReg = FuncRegOpnd.getGPR32Reg();
3819 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003820
Toma Tabacu65f10572014-09-16 15:00:52 +00003821 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003822 return true;
3823
Toma Tabacu13964452014-09-04 13:23:44 +00003824 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003825 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003826 const AsmToken &Tok = Parser.getTok();
3827 if (Tok.is(AsmToken::Integer)) {
3828 Save = Tok.getIntVal();
3829 SaveIsReg = false;
3830 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003831 } else {
3832 reportParseError("expected save register or stack offset");
3833 Parser.eatToEndOfStatement();
3834 return false;
3835 }
3836 } else {
3837 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3838 if (!SaveOpnd.isGPRAsmReg()) {
3839 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3840 Parser.eatToEndOfStatement();
3841 return false;
3842 }
3843 Save = SaveOpnd.getGPR32Reg();
3844 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003845
Toma Tabacu65f10572014-09-16 15:00:52 +00003846 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003847 return true;
3848
Toma Tabacu8874eac2015-02-18 13:46:53 +00003849 const MCExpr *Expr;
3850 if (Parser.parseExpression(Expr)) {
3851 reportParseError("expected expression");
3852 return false;
3853 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003854
Toma Tabacu8874eac2015-02-18 13:46:53 +00003855 if (Expr->getKind() != MCExpr::SymbolRef) {
3856 reportParseError("expected symbol");
3857 return false;
3858 }
3859 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
3860
3861 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
3862 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003863 return false;
3864}
3865
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003866bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003867 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003868 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3869 const AsmToken &Tok = Parser.getTok();
3870
3871 if (Tok.getString() == "2008") {
3872 Parser.Lex();
3873 getTargetStreamer().emitDirectiveNaN2008();
3874 return false;
3875 } else if (Tok.getString() == "legacy") {
3876 Parser.Lex();
3877 getTargetStreamer().emitDirectiveNaNLegacy();
3878 return false;
3879 }
3880 }
3881 // If we don't recognize the option passed to the .nan
3882 // directive (e.g. no option or unknown option), emit an error.
3883 reportParseError("invalid option in .nan directive");
3884 return false;
3885}
3886
Jack Carter0b744b32012-10-04 02:29:46 +00003887bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003888 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003889 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003890 const AsmToken &Tok = Parser.getTok();
3891
3892 if (Tok.getString() == "noat") {
3893 return parseSetNoAtDirective();
3894 } else if (Tok.getString() == "at") {
3895 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003896 } else if (Tok.getString() == "arch") {
3897 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003898 } else if (Tok.getString() == "fp") {
3899 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003900 } else if (Tok.getString() == "pop") {
3901 return parseSetPopDirective();
3902 } else if (Tok.getString() == "push") {
3903 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003904 } else if (Tok.getString() == "reorder") {
3905 return parseSetReorderDirective();
3906 } else if (Tok.getString() == "noreorder") {
3907 return parseSetNoReorderDirective();
3908 } else if (Tok.getString() == "macro") {
3909 return parseSetMacroDirective();
3910 } else if (Tok.getString() == "nomacro") {
3911 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003912 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00003913 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003914 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003915 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003916 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003917 getTargetStreamer().emitDirectiveSetNoMicroMips();
3918 Parser.eatToEndOfStatement();
3919 return false;
3920 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003921 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003922 } else if (Tok.getString() == "mips0") {
3923 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003924 } else if (Tok.getString() == "mips1") {
3925 return parseSetFeature(Mips::FeatureMips1);
3926 } else if (Tok.getString() == "mips2") {
3927 return parseSetFeature(Mips::FeatureMips2);
3928 } else if (Tok.getString() == "mips3") {
3929 return parseSetFeature(Mips::FeatureMips3);
3930 } else if (Tok.getString() == "mips4") {
3931 return parseSetFeature(Mips::FeatureMips4);
3932 } else if (Tok.getString() == "mips5") {
3933 return parseSetFeature(Mips::FeatureMips5);
3934 } else if (Tok.getString() == "mips32") {
3935 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003936 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003937 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003938 } else if (Tok.getString() == "mips32r3") {
3939 return parseSetFeature(Mips::FeatureMips32r3);
3940 } else if (Tok.getString() == "mips32r5") {
3941 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003942 } else if (Tok.getString() == "mips32r6") {
3943 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003944 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003945 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003946 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003947 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003948 } else if (Tok.getString() == "mips64r3") {
3949 return parseSetFeature(Mips::FeatureMips64r3);
3950 } else if (Tok.getString() == "mips64r5") {
3951 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003952 } else if (Tok.getString() == "mips64r6") {
3953 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003954 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003955 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003956 } else if (Tok.getString() == "nodsp") {
3957 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003958 } else if (Tok.getString() == "msa") {
3959 return parseSetMsaDirective();
3960 } else if (Tok.getString() == "nomsa") {
3961 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003962 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003963 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003964 parseSetAssignment();
3965 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003966 }
Jack Carter07c818d2013-01-25 01:31:34 +00003967
Jack Carter0b744b32012-10-04 02:29:46 +00003968 return true;
3969}
3970
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003971/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003972/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003973bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003974 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003975 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3976 for (;;) {
3977 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003978 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003979 return true;
3980
3981 getParser().getStreamer().EmitValue(Value, Size);
3982
3983 if (getLexer().is(AsmToken::EndOfStatement))
3984 break;
3985
Jack Carter07c818d2013-01-25 01:31:34 +00003986 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003987 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00003988 Parser.Lex();
3989 }
3990 }
3991
3992 Parser.Lex();
3993 return false;
3994}
3995
Vladimir Medic4c299852013-11-06 11:27:05 +00003996/// parseDirectiveGpWord
3997/// ::= .gpword local_sym
3998bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003999 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004000 const MCExpr *Value;
4001 // EmitGPRel32Value requires an expression, so we are using base class
4002 // method to evaluate the expression.
4003 if (getParser().parseExpression(Value))
4004 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00004005 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00004006
Vladimir Medice10c1122013-11-13 13:18:04 +00004007 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004008 return Error(getLexer().getLoc(),
4009 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00004010 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00004011 return false;
4012}
4013
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004014/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00004015/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004016bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004017 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004018 const MCExpr *Value;
4019 // EmitGPRel64Value requires an expression, so we are using base class
4020 // method to evaluate the expression.
4021 if (getParser().parseExpression(Value))
4022 return true;
4023 getParser().getStreamer().EmitGPRel64Value(Value);
4024
4025 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004026 return Error(getLexer().getLoc(),
4027 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00004028 Parser.Lex(); // Eat EndOfStatement token.
4029 return false;
4030}
4031
Jack Carter0cd3c192014-01-06 23:27:31 +00004032bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004033 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00004034 // Get the option token.
4035 AsmToken Tok = Parser.getTok();
4036 // At the moment only identifiers are supported.
4037 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004038 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00004039 Parser.eatToEndOfStatement();
4040 return false;
4041 }
4042
4043 StringRef Option = Tok.getIdentifier();
4044
4045 if (Option == "pic0") {
4046 getTargetStreamer().emitDirectiveOptionPic0();
4047 Parser.Lex();
4048 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4049 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004050 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004051 Parser.eatToEndOfStatement();
4052 }
4053 return false;
4054 }
4055
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004056 if (Option == "pic2") {
4057 getTargetStreamer().emitDirectiveOptionPic2();
4058 Parser.Lex();
4059 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4060 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004061 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004062 Parser.eatToEndOfStatement();
4063 }
4064 return false;
4065 }
4066
Jack Carter0cd3c192014-01-06 23:27:31 +00004067 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00004068 Warning(Parser.getTok().getLoc(),
4069 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00004070 Parser.eatToEndOfStatement();
4071 return false;
4072}
4073
Toma Tabacu9ca50962015-04-16 09:53:47 +00004074/// parseInsnDirective
4075/// ::= .insn
4076bool MipsAsmParser::parseInsnDirective() {
4077 // If this is not the end of the statement, report an error.
4078 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4079 reportParseError("unexpected token, expected end of statement");
4080 return false;
4081 }
4082
4083 // The actual label marking happens in
4084 // MipsELFStreamer::createPendingLabelRelocs().
4085 getTargetStreamer().emitDirectiveInsn();
4086
4087 getParser().Lex(); // Eat EndOfStatement token.
4088 return false;
4089}
4090
Daniel Sanders7e527422014-07-10 13:38:23 +00004091/// parseDirectiveModule
4092/// ::= .module oddspreg
4093/// ::= .module nooddspreg
4094/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004095bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004096 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004097 MCAsmLexer &Lexer = getLexer();
4098 SMLoc L = Lexer.getLoc();
4099
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004100 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004101 // TODO : get a better message.
4102 reportParseError(".module directive must appear before any code");
4103 return false;
4104 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004105
Toma Tabacuc405c822015-01-23 10:40:19 +00004106 StringRef Option;
4107 if (Parser.parseIdentifier(Option)) {
4108 reportParseError("expected .module option identifier");
4109 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004110 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004111
Toma Tabacuc405c822015-01-23 10:40:19 +00004112 if (Option == "oddspreg") {
4113 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
4114 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4115
4116 // If this is not the end of the statement, report an error.
4117 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4118 reportParseError("unexpected token, expected end of statement");
4119 return false;
4120 }
4121
4122 return false; // parseDirectiveModule has finished successfully.
4123 } else if (Option == "nooddspreg") {
4124 if (!isABI_O32()) {
4125 Error(L, "'.module nooddspreg' requires the O32 ABI");
4126 return false;
4127 }
4128
4129 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
4130 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4131
4132 // If this is not the end of the statement, report an error.
4133 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4134 reportParseError("unexpected token, expected end of statement");
4135 return false;
4136 }
4137
4138 return false; // parseDirectiveModule has finished successfully.
4139 } else if (Option == "fp") {
4140 return parseDirectiveModuleFP();
4141 } else {
4142 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
4143 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004144}
4145
4146/// parseDirectiveModuleFP
4147/// ::= =32
4148/// ::= =xx
4149/// ::= =64
4150bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004151 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004152 MCAsmLexer &Lexer = getLexer();
4153
4154 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004155 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004156 return false;
4157 }
4158 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004159
Daniel Sanders7e527422014-07-10 13:38:23 +00004160 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004161 if (!parseFpABIValue(FpABI, ".module"))
4162 return false;
4163
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004164 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004165 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004166 return false;
4167 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004168
Daniel Sanders7201a3e2014-07-08 10:35:52 +00004169 // Emit appropriate flags.
4170 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00004171 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004172 return false;
4173}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004174
Daniel Sanders7e527422014-07-10 13:38:23 +00004175bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004176 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004177 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004178 MCAsmLexer &Lexer = getLexer();
4179
4180 if (Lexer.is(AsmToken::Identifier)) {
4181 StringRef Value = Parser.getTok().getString();
4182 Parser.Lex();
4183
4184 if (Value != "xx") {
4185 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4186 return false;
4187 }
4188
4189 if (!isABI_O32()) {
4190 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
4191 return false;
4192 }
4193
Daniel Sanders7e527422014-07-10 13:38:23 +00004194 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004195 return true;
4196 }
4197
4198 if (Lexer.is(AsmToken::Integer)) {
4199 unsigned Value = Parser.getTok().getIntVal();
4200 Parser.Lex();
4201
4202 if (Value != 32 && Value != 64) {
4203 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4204 return false;
4205 }
4206
4207 if (Value == 32) {
4208 if (!isABI_O32()) {
4209 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
4210 return false;
4211 }
4212
Daniel Sanders7e527422014-07-10 13:38:23 +00004213 FpABI = MipsABIFlagsSection::FpABIKind::S32;
4214 } else
4215 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004216
Daniel Sanders7e527422014-07-10 13:38:23 +00004217 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004218 }
4219
4220 return false;
4221}
4222
Jack Carter0b744b32012-10-04 02:29:46 +00004223bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004224 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004225 StringRef IDVal = DirectiveID.getString();
4226
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004227 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004228 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00004229 if (IDVal == ".dword") {
4230 parseDataDirective(8, DirectiveID.getLoc());
4231 return false;
4232 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004233 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004234 StringRef SymbolName;
4235
4236 if (Parser.parseIdentifier(SymbolName)) {
4237 reportParseError("expected identifier after .ent");
4238 return false;
4239 }
4240
4241 // There's an undocumented extension that allows an integer to
4242 // follow the name of the procedure which AFAICS is ignored by GAS.
4243 // Example: .ent foo,2
4244 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4245 if (getLexer().isNot(AsmToken::Comma)) {
4246 // Even though we accept this undocumented extension for compatibility
4247 // reasons, the additional integer argument does not actually change
4248 // the behaviour of the '.ent' directive, so we would like to discourage
4249 // its use. We do this by not referring to the extended version in
4250 // error messages which are not directly related to its use.
4251 reportParseError("unexpected token, expected end of statement");
4252 return false;
4253 }
4254 Parser.Lex(); // Eat the comma.
4255 const MCExpr *DummyNumber;
4256 int64_t DummyNumberVal;
4257 // If the user was explicitly trying to use the extended version,
4258 // we still give helpful extension-related error messages.
4259 if (Parser.parseExpression(DummyNumber)) {
4260 reportParseError("expected number after comma");
4261 return false;
4262 }
4263 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
4264 reportParseError("expected an absolute expression after comma");
4265 return false;
4266 }
4267 }
4268
4269 // If this is not the end of the statement, report an error.
4270 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4271 reportParseError("unexpected token, expected end of statement");
4272 return false;
4273 }
4274
4275 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
4276
4277 getTargetStreamer().emitDirectiveEnt(*Sym);
4278 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00004279 return false;
4280 }
4281
Jack Carter07c818d2013-01-25 01:31:34 +00004282 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004283 StringRef SymbolName;
4284
4285 if (Parser.parseIdentifier(SymbolName)) {
4286 reportParseError("expected identifier after .end");
4287 return false;
4288 }
4289
4290 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4291 reportParseError("unexpected token, expected end of statement");
4292 return false;
4293 }
4294
4295 if (CurrentFn == nullptr) {
4296 reportParseError(".end used without .ent");
4297 return false;
4298 }
4299
4300 if ((SymbolName != CurrentFn->getName())) {
4301 reportParseError(".end symbol does not match .ent symbol");
4302 return false;
4303 }
4304
4305 getTargetStreamer().emitDirectiveEnd(SymbolName);
4306 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00004307 return false;
4308 }
4309
Jack Carter07c818d2013-01-25 01:31:34 +00004310 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004311 // .frame $stack_reg, frame_size_in_bytes, $return_reg
4312 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004313 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004314 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4315 reportParseError("expected stack register");
4316 return false;
4317 }
4318
4319 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4320 if (!StackRegOpnd.isGPRAsmReg()) {
4321 reportParseError(StackRegOpnd.getStartLoc(),
4322 "expected general purpose register");
4323 return false;
4324 }
4325 unsigned StackReg = StackRegOpnd.getGPR32Reg();
4326
4327 if (Parser.getTok().is(AsmToken::Comma))
4328 Parser.Lex();
4329 else {
4330 reportParseError("unexpected token, expected comma");
4331 return false;
4332 }
4333
4334 // Parse the frame size.
4335 const MCExpr *FrameSize;
4336 int64_t FrameSizeVal;
4337
4338 if (Parser.parseExpression(FrameSize)) {
4339 reportParseError("expected frame size value");
4340 return false;
4341 }
4342
4343 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
4344 reportParseError("frame size not an absolute expression");
4345 return false;
4346 }
4347
4348 if (Parser.getTok().is(AsmToken::Comma))
4349 Parser.Lex();
4350 else {
4351 reportParseError("unexpected token, expected comma");
4352 return false;
4353 }
4354
4355 // Parse the return register.
4356 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00004357 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004358 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4359 reportParseError("expected return register");
4360 return false;
4361 }
4362
4363 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4364 if (!ReturnRegOpnd.isGPRAsmReg()) {
4365 reportParseError(ReturnRegOpnd.getStartLoc(),
4366 "expected general purpose register");
4367 return false;
4368 }
4369
4370 // If this is not the end of the statement, report an error.
4371 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4372 reportParseError("unexpected token, expected end of statement");
4373 return false;
4374 }
4375
4376 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
4377 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00004378 return false;
4379 }
4380
Jack Carter07c818d2013-01-25 01:31:34 +00004381 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00004382 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00004383 }
4384
Daniel Sandersd97a6342014-08-13 10:07:34 +00004385 if (IDVal == ".mask" || IDVal == ".fmask") {
4386 // .mask bitmask, frame_offset
4387 // bitmask: One bit for each register used.
4388 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
4389 // first register is expected to be saved.
4390 // Examples:
4391 // .mask 0x80000000, -4
4392 // .fmask 0x80000000, -4
4393 //
Jack Carterbe332172012-09-07 00:48:02 +00004394
Daniel Sandersd97a6342014-08-13 10:07:34 +00004395 // Parse the bitmask
4396 const MCExpr *BitMask;
4397 int64_t BitMaskVal;
4398
4399 if (Parser.parseExpression(BitMask)) {
4400 reportParseError("expected bitmask value");
4401 return false;
4402 }
4403
4404 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
4405 reportParseError("bitmask not an absolute expression");
4406 return false;
4407 }
4408
4409 if (Parser.getTok().is(AsmToken::Comma))
4410 Parser.Lex();
4411 else {
4412 reportParseError("unexpected token, expected comma");
4413 return false;
4414 }
4415
4416 // Parse the frame_offset
4417 const MCExpr *FrameOffset;
4418 int64_t FrameOffsetVal;
4419
4420 if (Parser.parseExpression(FrameOffset)) {
4421 reportParseError("expected frame offset value");
4422 return false;
4423 }
4424
4425 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
4426 reportParseError("frame offset not an absolute expression");
4427 return false;
4428 }
4429
4430 // If this is not the end of the statement, report an error.
4431 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4432 reportParseError("unexpected token, expected end of statement");
4433 return false;
4434 }
4435
4436 if (IDVal == ".mask")
4437 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
4438 else
4439 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00004440 return false;
4441 }
4442
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004443 if (IDVal == ".nan")
4444 return parseDirectiveNaN();
4445
Jack Carter07c818d2013-01-25 01:31:34 +00004446 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004447 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00004448 return false;
4449 }
4450
Rafael Espindolab59fb732014-03-28 18:50:26 +00004451 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004452 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004453 return false;
4454 }
4455
Jack Carter07c818d2013-01-25 01:31:34 +00004456 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004457 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00004458 return false;
4459 }
4460
Jack Carter0cd3c192014-01-06 23:27:31 +00004461 if (IDVal == ".option")
4462 return parseDirectiveOption();
4463
4464 if (IDVal == ".abicalls") {
4465 getTargetStreamer().emitDirectiveAbiCalls();
4466 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004467 Error(Parser.getTok().getLoc(),
4468 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004469 // Clear line
4470 Parser.eatToEndOfStatement();
4471 }
4472 return false;
4473 }
4474
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004475 if (IDVal == ".cpsetup")
4476 return parseDirectiveCPSetup();
4477
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004478 if (IDVal == ".module")
4479 return parseDirectiveModule();
4480
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004481 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
4482 return parseInternalDirectiveReallowModule();
4483
Toma Tabacu9ca50962015-04-16 09:53:47 +00004484 if (IDVal == ".insn")
4485 return parseInsnDirective();
4486
Rafael Espindola870c4e92012-01-11 03:56:41 +00004487 return true;
4488}
4489
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004490bool MipsAsmParser::parseInternalDirectiveReallowModule() {
4491 // If this is not the end of the statement, report an error.
4492 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4493 reportParseError("unexpected token, expected end of statement");
4494 return false;
4495 }
4496
4497 getTargetStreamer().reallowModuleDirective();
4498
4499 getParser().Lex(); // Eat EndOfStatement token.
4500 return false;
4501}
4502
Rafael Espindola870c4e92012-01-11 03:56:41 +00004503extern "C" void LLVMInitializeMipsAsmParser() {
4504 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
4505 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
4506 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
4507 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
4508}
Jack Carterb4dbc172012-09-05 23:34:03 +00004509
4510#define GET_REGISTER_MATCHER
4511#define GET_MATCHER_IMPLEMENTATION
4512#include "MipsGenAsmMatcher.inc"