blob: 1aa895d9ca88f66a2a35bd841880a5ac68bb96d0 [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 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000436
437 bool abiUsesSoftFloat() const {
438 return (STI.getFeatureBits() & Mips::FeatureSoftFloat);
439 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000440
Toma Tabacud9d344b2015-04-27 14:05:04 +0000441 /// Warn if RegIndex is the same as the current AT.
442 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000443};
444}
445
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000446namespace {
447
448/// MipsOperand - Instances of this class represent a parsed Mips machine
449/// instruction.
450class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000451public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000452 /// Broad categories of register classes
453 /// The exact class is finalized by the render method.
454 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000455 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000456 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000457 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000458 RegKind_FCC = 4, /// FCC
459 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
460 RegKind_MSACtrl = 16, /// MSA control registers
461 RegKind_COP2 = 32, /// COP2
462 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
463 /// context).
464 RegKind_CCR = 128, /// CCR
465 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000466 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000467
468 /// Potentially any (e.g. $1)
469 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
470 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000471 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000472 };
473
474private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000475 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000476 k_Immediate, /// An immediate (possibly involving symbol references)
477 k_Memory, /// Base + Offset Memory Address
478 k_PhysRegister, /// A physical register from the Mips namespace
479 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000480 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000481 k_RegList, /// A physical register list
482 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000483 } Kind;
484
David Blaikie960ea3f2014-06-08 16:18:35 +0000485public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000486 MipsOperand(KindTy K, MipsAsmParser &Parser)
487 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
488
David Blaikie960ea3f2014-06-08 16:18:35 +0000489private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000490 /// For diagnostics, and checking the assembler temporary
491 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000492
Eric Christopher8996c5d2013-03-15 00:42:55 +0000493 struct Token {
494 const char *Data;
495 unsigned Length;
496 };
497
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000498 struct PhysRegOp {
499 unsigned Num; /// Register Number
500 };
501
502 struct RegIdxOp {
503 unsigned Index; /// Index into the register class
504 RegKind Kind; /// Bitfield of the kinds it could possibly be
505 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000506 };
507
508 struct ImmOp {
509 const MCExpr *Val;
510 };
511
512 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000513 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000514 const MCExpr *Off;
515 };
516
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000517 struct RegListOp {
518 SmallVector<unsigned, 10> *List;
519 };
520
Jack Carterb4dbc172012-09-05 23:34:03 +0000521 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000522 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000523 struct PhysRegOp PhysReg;
524 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000525 struct ImmOp Imm;
526 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000527 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000528 };
529
530 SMLoc StartLoc, EndLoc;
531
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000532 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000533 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
534 const MCRegisterInfo *RegInfo,
535 SMLoc S, SMLoc E,
536 MipsAsmParser &Parser) {
537 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000538 Op->RegIdx.Index = Index;
539 Op->RegIdx.RegInfo = RegInfo;
540 Op->RegIdx.Kind = RegKind;
541 Op->StartLoc = S;
542 Op->EndLoc = E;
543 return Op;
544 }
545
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000546public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000547 /// Coerce the register to GPR32 and return the real register for the current
548 /// target.
549 unsigned getGPR32Reg() const {
550 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000551 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000552 unsigned ClassID = Mips::GPR32RegClassID;
553 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000554 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000555
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000556 /// Coerce the register to GPR32 and return the real register for the current
557 /// target.
558 unsigned getGPRMM16Reg() const {
559 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
560 unsigned ClassID = Mips::GPR32RegClassID;
561 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
562 }
563
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000564 /// Coerce the register to GPR64 and return the real register for the current
565 /// target.
566 unsigned getGPR64Reg() const {
567 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
568 unsigned ClassID = Mips::GPR64RegClassID;
569 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000570 }
571
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000572private:
573 /// Coerce the register to AFGR64 and return the real register for the current
574 /// target.
575 unsigned getAFGR64Reg() const {
576 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
577 if (RegIdx.Index % 2 != 0)
578 AsmParser.Warning(StartLoc, "Float register should be even.");
579 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
580 .getRegister(RegIdx.Index / 2);
581 }
582
583 /// Coerce the register to FGR64 and return the real register for the current
584 /// target.
585 unsigned getFGR64Reg() const {
586 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
587 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
588 .getRegister(RegIdx.Index);
589 }
590
591 /// Coerce the register to FGR32 and return the real register for the current
592 /// target.
593 unsigned getFGR32Reg() const {
594 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
595 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
596 .getRegister(RegIdx.Index);
597 }
598
599 /// Coerce the register to FGRH32 and return the real register for the current
600 /// target.
601 unsigned getFGRH32Reg() const {
602 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
603 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
604 .getRegister(RegIdx.Index);
605 }
606
607 /// Coerce the register to FCC and return the real register for the current
608 /// target.
609 unsigned getFCCReg() const {
610 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
611 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
612 .getRegister(RegIdx.Index);
613 }
614
615 /// Coerce the register to MSA128 and return the real register for the current
616 /// target.
617 unsigned getMSA128Reg() const {
618 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
619 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
620 // identical
621 unsigned ClassID = Mips::MSA128BRegClassID;
622 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
623 }
624
625 /// Coerce the register to MSACtrl and return the real register for the
626 /// current target.
627 unsigned getMSACtrlReg() const {
628 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
629 unsigned ClassID = Mips::MSACtrlRegClassID;
630 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
631 }
632
633 /// Coerce the register to COP2 and return the real register for the
634 /// current target.
635 unsigned getCOP2Reg() const {
636 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
637 unsigned ClassID = Mips::COP2RegClassID;
638 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
639 }
640
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000641 /// Coerce the register to COP3 and return the real register for the
642 /// current target.
643 unsigned getCOP3Reg() const {
644 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
645 unsigned ClassID = Mips::COP3RegClassID;
646 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
647 }
648
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000649 /// Coerce the register to ACC64DSP and return the real register for the
650 /// current target.
651 unsigned getACC64DSPReg() const {
652 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
653 unsigned ClassID = Mips::ACC64DSPRegClassID;
654 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
655 }
656
657 /// Coerce the register to HI32DSP and return the real register for the
658 /// current target.
659 unsigned getHI32DSPReg() const {
660 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
661 unsigned ClassID = Mips::HI32DSPRegClassID;
662 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
663 }
664
665 /// Coerce the register to LO32DSP and return the real register for the
666 /// current target.
667 unsigned getLO32DSPReg() const {
668 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
669 unsigned ClassID = Mips::LO32DSPRegClassID;
670 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
671 }
672
673 /// Coerce the register to CCR and return the real register for the
674 /// current target.
675 unsigned getCCRReg() const {
676 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
677 unsigned ClassID = Mips::CCRRegClassID;
678 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
679 }
680
681 /// Coerce the register to HWRegs and return the real register for the
682 /// current target.
683 unsigned getHWRegsReg() const {
684 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
685 unsigned ClassID = Mips::HWRegsRegClassID;
686 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
687 }
688
689public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000690 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000691 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000692 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000693 Inst.addOperand(MCOperand::CreateImm(0));
694 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
695 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
696 else
697 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000698 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000699
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000700 void addRegOperands(MCInst &Inst, unsigned N) const {
701 llvm_unreachable("Use a custom parser instead");
702 }
703
Daniel Sanders21bce302014-04-01 12:35:23 +0000704 /// Render the operand to an MCInst as a GPR32
705 /// Asserts if the wrong number of operands are requested, or the operand
706 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000707 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
708 assert(N == 1 && "Invalid number of operands!");
709 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
710 }
711
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000712 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
713 assert(N == 1 && "Invalid number of operands!");
714 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
715 }
716
Jozef Kolek1904fa22014-11-24 14:25:53 +0000717 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
718 assert(N == 1 && "Invalid number of operands!");
719 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
720 }
721
Zoran Jovanovic41688672015-02-10 16:36:20 +0000722 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
723 assert(N == 1 && "Invalid number of operands!");
724 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
725 }
726
Daniel Sanders21bce302014-04-01 12:35:23 +0000727 /// Render the operand to an MCInst as a GPR64
728 /// Asserts if the wrong number of operands are requested, or the operand
729 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000730 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
731 assert(N == 1 && "Invalid number of operands!");
732 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
733 }
734
735 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
736 assert(N == 1 && "Invalid number of operands!");
737 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
738 }
739
740 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
741 assert(N == 1 && "Invalid number of operands!");
742 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
743 }
744
745 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
746 assert(N == 1 && "Invalid number of operands!");
747 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000748 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000749 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000750 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
751 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000752 }
753
754 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
755 assert(N == 1 && "Invalid number of operands!");
756 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
757 }
758
759 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
760 assert(N == 1 && "Invalid number of operands!");
761 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
762 }
763
764 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
765 assert(N == 1 && "Invalid number of operands!");
766 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
767 }
768
769 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
770 assert(N == 1 && "Invalid number of operands!");
771 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
772 }
773
774 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
775 assert(N == 1 && "Invalid number of operands!");
776 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
777 }
778
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000779 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
780 assert(N == 1 && "Invalid number of operands!");
781 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
782 }
783
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000784 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
785 assert(N == 1 && "Invalid number of operands!");
786 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
787 }
788
789 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
790 assert(N == 1 && "Invalid number of operands!");
791 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
792 }
793
794 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
795 assert(N == 1 && "Invalid number of operands!");
796 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
797 }
798
799 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
800 assert(N == 1 && "Invalid number of operands!");
801 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
802 }
803
804 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
805 assert(N == 1 && "Invalid number of operands!");
806 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
807 }
808
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000809 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000810 assert(N == 1 && "Invalid number of operands!");
811 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000812 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000813 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000814
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000815 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000816 assert(N == 2 && "Invalid number of operands!");
817
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000818 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000819
820 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000821 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000822 }
823
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000824 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
825 assert(N == 2 && "Invalid number of operands!");
826
827 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPRMM16Reg()));
828
829 const MCExpr *Expr = getMemOff();
830 addExpr(Inst, Expr);
831 }
832
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000833 void addRegListOperands(MCInst &Inst, unsigned N) const {
834 assert(N == 1 && "Invalid number of operands!");
835
836 for (auto RegNo : getRegList())
837 Inst.addOperand(MCOperand::CreateReg(RegNo));
838 }
839
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000840 void addRegPairOperands(MCInst &Inst, unsigned N) const {
841 assert(N == 2 && "Invalid number of operands!");
842 unsigned RegNo = getRegPair();
843 Inst.addOperand(MCOperand::CreateReg(RegNo++));
844 Inst.addOperand(MCOperand::CreateReg(RegNo));
845 }
846
Zoran Jovanovic41688672015-02-10 16:36:20 +0000847 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
848 assert(N == 2 && "Invalid number of operands!");
849 for (auto RegNo : getRegList())
850 Inst.addOperand(MCOperand::CreateReg(RegNo));
851 }
852
Craig Topper56c590a2014-04-29 07:58:02 +0000853 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000854 // As a special case until we sort out the definition of div/divu, pretend
855 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
856 if (isGPRAsmReg() && RegIdx.Index == 0)
857 return true;
858
859 return Kind == k_PhysRegister;
860 }
861 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000862 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000863 bool isConstantImm() const {
864 return isImm() && dyn_cast<MCConstantExpr>(getImm());
865 }
Craig Topper56c590a2014-04-29 07:58:02 +0000866 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000867 // Note: It's not possible to pretend that other operand kinds are tokens.
868 // The matcher emitter checks tokens first.
869 return Kind == k_Token;
870 }
Craig Topper56c590a2014-04-29 07:58:02 +0000871 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000872 bool isConstantMemOff() const {
873 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
874 }
875 template <unsigned Bits> bool isMemWithSimmOffset() const {
876 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
877 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000878 bool isMemWithGRPMM16Base() const {
879 return isMem() && getMemBase()->isMM16AsmReg();
880 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000881 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
882 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
883 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
884 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000885 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
886 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
887 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
888 && (getMemBase()->getGPR32Reg() == Mips::SP);
889 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000890 bool isRegList16() const {
891 if (!isRegList())
892 return false;
893
894 int Size = RegList.List->size();
895 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
896 RegList.List->back() != Mips::RA)
897 return false;
898
899 int PrevReg = *RegList.List->begin();
900 for (int i = 1; i < Size - 1; i++) {
901 int Reg = (*(RegList.List))[i];
902 if ( Reg != PrevReg + 1)
903 return false;
904 PrevReg = Reg;
905 }
906
907 return true;
908 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000909 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000910 bool isLSAImm() const {
911 if (!isConstantImm())
912 return false;
913 int64_t Val = getConstantImm();
914 return 1 <= Val && Val <= 4;
915 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000916 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +0000917 bool isMovePRegPair() const {
918 if (Kind != k_RegList || RegList.List->size() != 2)
919 return false;
920
921 unsigned R0 = RegList.List->front();
922 unsigned R1 = RegList.List->back();
923
924 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
925 (R0 == Mips::A1 && R1 == Mips::A3) ||
926 (R0 == Mips::A2 && R1 == Mips::A3) ||
927 (R0 == Mips::A0 && R1 == Mips::S5) ||
928 (R0 == Mips::A0 && R1 == Mips::S6) ||
929 (R0 == Mips::A0 && R1 == Mips::A1) ||
930 (R0 == Mips::A0 && R1 == Mips::A2) ||
931 (R0 == Mips::A0 && R1 == Mips::A3))
932 return true;
933
934 return false;
935 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000936
937 StringRef getToken() const {
938 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000939 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000940 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000941 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000942
Craig Topper56c590a2014-04-29 07:58:02 +0000943 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000944 // As a special case until we sort out the definition of div/divu, pretend
945 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
946 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
947 RegIdx.Kind & RegKind_GPR)
948 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000949
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000950 assert(Kind == k_PhysRegister && "Invalid access!");
951 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000952 }
953
Jack Carterb4dbc172012-09-05 23:34:03 +0000954 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000955 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000956 return Imm.Val;
957 }
958
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000959 int64_t getConstantImm() const {
960 const MCExpr *Val = getImm();
961 return static_cast<const MCConstantExpr *>(Val)->getValue();
962 }
963
964 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000965 assert((Kind == k_Memory) && "Invalid access!");
966 return Mem.Base;
967 }
968
969 const MCExpr *getMemOff() const {
970 assert((Kind == k_Memory) && "Invalid access!");
971 return Mem.Off;
972 }
973
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000974 int64_t getConstantMemOff() const {
975 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
976 }
977
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000978 const SmallVectorImpl<unsigned> &getRegList() const {
979 assert((Kind == k_RegList) && "Invalid access!");
980 return *(RegList.List);
981 }
982
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000983 unsigned getRegPair() const {
984 assert((Kind == k_RegPair) && "Invalid access!");
985 return RegIdx.Index;
986 }
987
David Blaikie960ea3f2014-06-08 16:18:35 +0000988 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
989 MipsAsmParser &Parser) {
990 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000991 Op->Tok.Data = Str.data();
992 Op->Tok.Length = Str.size();
993 Op->StartLoc = S;
994 Op->EndLoc = S;
995 return Op;
996 }
997
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000998 /// Create a numeric register (e.g. $1). The exact register remains
999 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001000 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001001 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001002 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001003 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001004 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001005 }
1006
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001007 /// Create a register that is definitely a GPR.
1008 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001009 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001010 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001011 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001012 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001013 }
1014
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001015 /// Create a register that is definitely a FGR.
1016 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001017 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001018 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001019 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001020 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1021 }
1022
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001023 /// Create a register that is definitely a HWReg.
1024 /// This is typically only used for named registers such as $hwr_cpunum.
1025 static std::unique_ptr<MipsOperand>
1026 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1027 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1028 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1029 }
1030
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001031 /// Create a register that is definitely an FCC.
1032 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001033 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001034 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001035 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001036 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1037 }
1038
1039 /// Create a register that is definitely an ACC.
1040 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001041 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001042 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001043 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001044 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1045 }
1046
1047 /// Create a register that is definitely an MSA128.
1048 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001049 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001050 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001051 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001052 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1053 }
1054
1055 /// Create a register that is definitely an MSACtrl.
1056 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001057 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001058 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001059 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001060 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1061 }
1062
David Blaikie960ea3f2014-06-08 16:18:35 +00001063 static std::unique_ptr<MipsOperand>
1064 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1065 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001066 Op->Imm.Val = Val;
1067 Op->StartLoc = S;
1068 Op->EndLoc = E;
1069 return Op;
1070 }
1071
David Blaikie960ea3f2014-06-08 16:18:35 +00001072 static std::unique_ptr<MipsOperand>
1073 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1074 SMLoc E, MipsAsmParser &Parser) {
1075 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1076 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001077 Op->Mem.Off = Off;
1078 Op->StartLoc = S;
1079 Op->EndLoc = E;
1080 return Op;
1081 }
1082
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001083 static std::unique_ptr<MipsOperand>
1084 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1085 MipsAsmParser &Parser) {
1086 assert (Regs.size() > 0 && "Empty list not allowed");
1087
1088 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001089 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001090 Op->StartLoc = StartLoc;
1091 Op->EndLoc = EndLoc;
1092 return Op;
1093 }
1094
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001095 static std::unique_ptr<MipsOperand>
1096 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1097 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1098 Op->RegIdx.Index = RegNo;
1099 Op->StartLoc = S;
1100 Op->EndLoc = E;
1101 return Op;
1102 }
1103
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001104 bool isGPRAsmReg() const {
1105 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001106 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001107 bool isMM16AsmReg() const {
1108 if (!(isRegIdx() && RegIdx.Kind))
1109 return false;
1110 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1111 || RegIdx.Index == 16 || RegIdx.Index == 17);
1112 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001113 bool isMM16AsmRegZero() const {
1114 if (!(isRegIdx() && RegIdx.Kind))
1115 return false;
1116 return (RegIdx.Index == 0 ||
1117 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1118 RegIdx.Index == 17);
1119 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001120 bool isMM16AsmRegMoveP() const {
1121 if (!(isRegIdx() && RegIdx.Kind))
1122 return false;
1123 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1124 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1125 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001126 bool isFGRAsmReg() const {
1127 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1128 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001129 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001130 bool isHWRegsAsmReg() const {
1131 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001132 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001133 bool isCCRAsmReg() const {
1134 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001135 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001136 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001137 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1138 return false;
1139 if (!AsmParser.hasEightFccRegisters())
1140 return RegIdx.Index == 0;
1141 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001142 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001143 bool isACCAsmReg() const {
1144 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001145 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001146 bool isCOP2AsmReg() const {
1147 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001148 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001149 bool isCOP3AsmReg() const {
1150 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1151 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001152 bool isMSA128AsmReg() const {
1153 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001154 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001155 bool isMSACtrlAsmReg() const {
1156 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001157 }
1158
Jack Carterb4dbc172012-09-05 23:34:03 +00001159 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001160 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001161 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001162 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001163
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001164 virtual ~MipsOperand() {
1165 switch (Kind) {
1166 case k_Immediate:
1167 break;
1168 case k_Memory:
1169 delete Mem.Base;
1170 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001171 case k_RegList:
1172 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001173 case k_PhysRegister:
1174 case k_RegisterIndex:
1175 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001176 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001177 break;
1178 }
1179 }
1180
Craig Topper56c590a2014-04-29 07:58:02 +00001181 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001182 switch (Kind) {
1183 case k_Immediate:
1184 OS << "Imm<";
1185 Imm.Val->print(OS);
1186 OS << ">";
1187 break;
1188 case k_Memory:
1189 OS << "Mem<";
1190 Mem.Base->print(OS);
1191 OS << ", ";
1192 Mem.Off->print(OS);
1193 OS << ">";
1194 break;
1195 case k_PhysRegister:
1196 OS << "PhysReg<" << PhysReg.Num << ">";
1197 break;
1198 case k_RegisterIndex:
1199 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1200 break;
1201 case k_Token:
1202 OS << Tok.Data;
1203 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001204 case k_RegList:
1205 OS << "RegList< ";
1206 for (auto Reg : (*RegList.List))
1207 OS << Reg << " ";
1208 OS << ">";
1209 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001210 case k_RegPair:
1211 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1212 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001213 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001214 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001215}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001216} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001217
Jack Carter9e65aa32013-03-22 00:05:30 +00001218namespace llvm {
1219extern const MCInstrDesc MipsInsts[];
1220}
1221static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1222 return MipsInsts[Opcode];
1223}
1224
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001225static bool hasShortDelaySlot(unsigned Opcode) {
1226 switch (Opcode) {
1227 case Mips::JALS_MM:
1228 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001229 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001230 case Mips::BGEZALS_MM:
1231 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001232 return true;
1233 default:
1234 return false;
1235 }
1236}
1237
Jack Carter9e65aa32013-03-22 00:05:30 +00001238bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001239 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001240 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001241
Jack Carter9e65aa32013-03-22 00:05:30 +00001242 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001243
1244 if (MCID.isBranch() || MCID.isCall()) {
1245 const unsigned Opcode = Inst.getOpcode();
1246 MCOperand Offset;
1247
1248 switch (Opcode) {
1249 default:
1250 break;
Kai Nackee0245392015-01-27 19:11:28 +00001251 case Mips::BBIT0:
1252 case Mips::BBIT032:
1253 case Mips::BBIT1:
1254 case Mips::BBIT132:
1255 assert(hasCnMips() && "instruction only valid for octeon cpus");
1256 // Fall through
1257
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001258 case Mips::BEQ:
1259 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001260 case Mips::BEQ_MM:
1261 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001262 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001263 Offset = Inst.getOperand(2);
1264 if (!Offset.isImm())
1265 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001266 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001267 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001268 if (OffsetToAlignment(Offset.getImm(),
1269 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001270 return Error(IDLoc, "branch to misaligned address");
1271 break;
1272 case Mips::BGEZ:
1273 case Mips::BGTZ:
1274 case Mips::BLEZ:
1275 case Mips::BLTZ:
1276 case Mips::BGEZAL:
1277 case Mips::BLTZAL:
1278 case Mips::BC1F:
1279 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001280 case Mips::BGEZ_MM:
1281 case Mips::BGTZ_MM:
1282 case Mips::BLEZ_MM:
1283 case Mips::BLTZ_MM:
1284 case Mips::BGEZAL_MM:
1285 case Mips::BLTZAL_MM:
1286 case Mips::BC1F_MM:
1287 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001288 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001289 Offset = Inst.getOperand(1);
1290 if (!Offset.isImm())
1291 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001292 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001293 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001294 if (OffsetToAlignment(Offset.getImm(),
1295 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001296 return Error(IDLoc, "branch to misaligned address");
1297 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001298 case Mips::BEQZ16_MM:
1299 case Mips::BNEZ16_MM:
1300 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1301 Offset = Inst.getOperand(1);
1302 if (!Offset.isImm())
1303 break; // We'll deal with this situation later on when applying fixups.
1304 if (!isIntN(8, Offset.getImm()))
1305 return Error(IDLoc, "branch target out of range");
1306 if (OffsetToAlignment(Offset.getImm(), 2LL))
1307 return Error(IDLoc, "branch to misaligned address");
1308 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001309 }
1310 }
1311
Daniel Sandersa84989a2014-06-16 13:25:35 +00001312 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1313 // We still accept it but it is a normal nop.
1314 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1315 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1316 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1317 "nop instruction");
1318 }
1319
Kai Nackee0245392015-01-27 19:11:28 +00001320 if (hasCnMips()) {
1321 const unsigned Opcode = Inst.getOpcode();
1322 MCOperand Opnd;
1323 int Imm;
1324
1325 switch (Opcode) {
1326 default:
1327 break;
1328
1329 case Mips::BBIT0:
1330 case Mips::BBIT032:
1331 case Mips::BBIT1:
1332 case Mips::BBIT132:
1333 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1334 // The offset is handled above
1335 Opnd = Inst.getOperand(1);
1336 if (!Opnd.isImm())
1337 return Error(IDLoc, "expected immediate operand kind");
1338 Imm = Opnd.getImm();
1339 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1340 Opcode == Mips::BBIT1 ? 63 : 31))
1341 return Error(IDLoc, "immediate operand value out of range");
1342 if (Imm > 31) {
1343 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1344 : Mips::BBIT132);
1345 Inst.getOperand(1).setImm(Imm - 32);
1346 }
1347 break;
1348
1349 case Mips::CINS:
1350 case Mips::CINS32:
1351 case Mips::EXTS:
1352 case Mips::EXTS32:
1353 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1354 // Check length
1355 Opnd = Inst.getOperand(3);
1356 if (!Opnd.isImm())
1357 return Error(IDLoc, "expected immediate operand kind");
1358 Imm = Opnd.getImm();
1359 if (Imm < 0 || Imm > 31)
1360 return Error(IDLoc, "immediate operand value out of range");
1361 // Check position
1362 Opnd = Inst.getOperand(2);
1363 if (!Opnd.isImm())
1364 return Error(IDLoc, "expected immediate operand kind");
1365 Imm = Opnd.getImm();
1366 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1367 Opcode == Mips::EXTS ? 63 : 31))
1368 return Error(IDLoc, "immediate operand value out of range");
1369 if (Imm > 31) {
1370 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1371 Inst.getOperand(2).setImm(Imm - 32);
1372 }
1373 break;
1374
1375 case Mips::SEQi:
1376 case Mips::SNEi:
1377 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1378 Opnd = Inst.getOperand(2);
1379 if (!Opnd.isImm())
1380 return Error(IDLoc, "expected immediate operand kind");
1381 Imm = Opnd.getImm();
1382 if (!isInt<10>(Imm))
1383 return Error(IDLoc, "immediate operand value out of range");
1384 break;
1385 }
1386 }
1387
Jack Carter9e65aa32013-03-22 00:05:30 +00001388 if (MCID.mayLoad() || MCID.mayStore()) {
1389 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001390 // reference or immediate we may have to expand instructions.
1391 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001392 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001393 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1394 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001395 MCOperand &Op = Inst.getOperand(i);
1396 if (Op.isImm()) {
1397 int MemOffset = Op.getImm();
1398 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001399 // Offset can't exceed 16bit value.
1400 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001401 return false;
1402 }
1403 } else if (Op.isExpr()) {
1404 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001405 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001406 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001407 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001408 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001409 // Expand symbol.
1410 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001411 return false;
1412 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001413 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001414 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001415 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001416 }
1417 }
1418 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001419 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001420 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001421
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001422 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001423 if (MCID.mayLoad()) {
1424 // Try to create 16-bit GP relative load instruction.
1425 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1426 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1427 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1428 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1429 MCOperand &Op = Inst.getOperand(i);
1430 if (Op.isImm()) {
1431 int MemOffset = Op.getImm();
1432 MCOperand &DstReg = Inst.getOperand(0);
1433 MCOperand &BaseReg = Inst.getOperand(1);
1434 if (isIntN(9, MemOffset) && (MemOffset % 4 == 0) &&
1435 getContext().getRegisterInfo()->getRegClass(
1436 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
1437 BaseReg.getReg() == Mips::GP) {
1438 MCInst TmpInst;
1439 TmpInst.setLoc(IDLoc);
1440 TmpInst.setOpcode(Mips::LWGP_MM);
1441 TmpInst.addOperand(MCOperand::CreateReg(DstReg.getReg()));
1442 TmpInst.addOperand(MCOperand::CreateReg(Mips::GP));
1443 TmpInst.addOperand(MCOperand::CreateImm(MemOffset));
1444 Instructions.push_back(TmpInst);
1445 return false;
1446 }
1447 }
1448 }
1449 } // for
1450 } // if load
1451
1452 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1453
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001454 MCOperand Opnd;
1455 int Imm;
1456
1457 switch (Inst.getOpcode()) {
1458 default:
1459 break;
1460 case Mips::ADDIUS5_MM:
1461 Opnd = Inst.getOperand(2);
1462 if (!Opnd.isImm())
1463 return Error(IDLoc, "expected immediate operand kind");
1464 Imm = Opnd.getImm();
1465 if (Imm < -8 || Imm > 7)
1466 return Error(IDLoc, "immediate operand value out of range");
1467 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001468 case Mips::ADDIUSP_MM:
1469 Opnd = Inst.getOperand(0);
1470 if (!Opnd.isImm())
1471 return Error(IDLoc, "expected immediate operand kind");
1472 Imm = Opnd.getImm();
1473 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1474 Imm % 4 != 0)
1475 return Error(IDLoc, "immediate operand value out of range");
1476 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001477 case Mips::SLL16_MM:
1478 case Mips::SRL16_MM:
1479 Opnd = Inst.getOperand(2);
1480 if (!Opnd.isImm())
1481 return Error(IDLoc, "expected immediate operand kind");
1482 Imm = Opnd.getImm();
1483 if (Imm < 1 || Imm > 8)
1484 return Error(IDLoc, "immediate operand value out of range");
1485 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001486 case Mips::LI16_MM:
1487 Opnd = Inst.getOperand(1);
1488 if (!Opnd.isImm())
1489 return Error(IDLoc, "expected immediate operand kind");
1490 Imm = Opnd.getImm();
1491 if (Imm < -1 || Imm > 126)
1492 return Error(IDLoc, "immediate operand value out of range");
1493 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001494 case Mips::ADDIUR2_MM:
1495 Opnd = Inst.getOperand(2);
1496 if (!Opnd.isImm())
1497 return Error(IDLoc, "expected immediate operand kind");
1498 Imm = Opnd.getImm();
1499 if (!(Imm == 1 || Imm == -1 ||
1500 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1501 return Error(IDLoc, "immediate operand value out of range");
1502 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001503 case Mips::ADDIUR1SP_MM:
1504 Opnd = Inst.getOperand(1);
1505 if (!Opnd.isImm())
1506 return Error(IDLoc, "expected immediate operand kind");
1507 Imm = Opnd.getImm();
1508 if (OffsetToAlignment(Imm, 4LL))
1509 return Error(IDLoc, "misaligned immediate operand value");
1510 if (Imm < 0 || Imm > 255)
1511 return Error(IDLoc, "immediate operand value out of range");
1512 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001513 case Mips::ANDI16_MM:
1514 Opnd = Inst.getOperand(2);
1515 if (!Opnd.isImm())
1516 return Error(IDLoc, "expected immediate operand kind");
1517 Imm = Opnd.getImm();
1518 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1519 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1520 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1521 return Error(IDLoc, "immediate operand value out of range");
1522 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001523 case Mips::LBU16_MM:
1524 Opnd = Inst.getOperand(2);
1525 if (!Opnd.isImm())
1526 return Error(IDLoc, "expected immediate operand kind");
1527 Imm = Opnd.getImm();
1528 if (Imm < -1 || Imm > 14)
1529 return Error(IDLoc, "immediate operand value out of range");
1530 break;
1531 case Mips::SB16_MM:
1532 Opnd = Inst.getOperand(2);
1533 if (!Opnd.isImm())
1534 return Error(IDLoc, "expected immediate operand kind");
1535 Imm = Opnd.getImm();
1536 if (Imm < 0 || Imm > 15)
1537 return Error(IDLoc, "immediate operand value out of range");
1538 break;
1539 case Mips::LHU16_MM:
1540 case Mips::SH16_MM:
1541 Opnd = Inst.getOperand(2);
1542 if (!Opnd.isImm())
1543 return Error(IDLoc, "expected immediate operand kind");
1544 Imm = Opnd.getImm();
1545 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1546 return Error(IDLoc, "immediate operand value out of range");
1547 break;
1548 case Mips::LW16_MM:
1549 case Mips::SW16_MM:
1550 Opnd = Inst.getOperand(2);
1551 if (!Opnd.isImm())
1552 return Error(IDLoc, "expected immediate operand kind");
1553 Imm = Opnd.getImm();
1554 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1555 return Error(IDLoc, "immediate operand value out of range");
1556 break;
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001557 case Mips::CACHE:
1558 case Mips::PREF:
1559 Opnd = Inst.getOperand(2);
1560 if (!Opnd.isImm())
1561 return Error(IDLoc, "expected immediate operand kind");
1562 Imm = Opnd.getImm();
1563 if (!isUInt<5>(Imm))
1564 return Error(IDLoc, "immediate operand value out of range");
1565 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001566 case Mips::ADDIUPC_MM:
1567 MCOperand Opnd = Inst.getOperand(1);
1568 if (!Opnd.isImm())
1569 return Error(IDLoc, "expected immediate operand kind");
1570 int Imm = Opnd.getImm();
1571 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1572 return Error(IDLoc, "immediate operand value out of range");
1573 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001574 }
1575 }
1576
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001577 if (needsExpansion(Inst)) {
1578 if (expandInstruction(Inst, IDLoc, Instructions))
1579 return true;
1580 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001581 Instructions.push_back(Inst);
1582
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001583 // If this instruction has a delay slot and .set reorder is active,
1584 // emit a NOP after it.
1585 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1586 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1587
Jack Carter9e65aa32013-03-22 00:05:30 +00001588 return false;
1589}
1590
Jack Carter30a59822012-10-04 04:03:53 +00001591bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1592
Jack Carterd0bd6422013-04-18 00:41:53 +00001593 switch (Inst.getOpcode()) {
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001594 case Mips::LoadImm32:
1595 case Mips::LoadImm64:
1596 case Mips::LoadAddrImm32:
1597 case Mips::LoadAddrReg32:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001598 case Mips::B_MM_Pseudo:
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001599 case Mips::LWM_MM:
1600 case Mips::SWM_MM:
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001601 case Mips::JalOneReg:
1602 case Mips::JalTwoReg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001603 return true;
1604 default:
1605 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001606 }
1607}
Jack Carter92995f12012-10-06 00:53:28 +00001608
Matheus Almeida3813d572014-06-19 14:39:14 +00001609bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001610 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001611 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001612 default: llvm_unreachable("unimplemented expansion");
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001613 case Mips::LoadImm32:
Toma Tabacu00e98672015-05-01 12:19:27 +00001614 return expandLoadImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001615 case Mips::LoadImm64:
Toma Tabacu00e98672015-05-01 12:19:27 +00001616 return expandLoadImm(Inst, false, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001617 case Mips::LoadAddrImm32:
Jack Carterd0bd6422013-04-18 00:41:53 +00001618 return expandLoadAddressImm(Inst, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001619 case Mips::LoadAddrReg32:
Jack Carterd0bd6422013-04-18 00:41:53 +00001620 return expandLoadAddressReg(Inst, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001621 case Mips::B_MM_Pseudo:
1622 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001623 case Mips::SWM_MM:
1624 case Mips::LWM_MM:
1625 return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001626 case Mips::JalOneReg:
1627 case Mips::JalTwoReg:
1628 return expandJalWithRegs(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001629 }
Jack Carter30a59822012-10-04 04:03:53 +00001630}
Jack Carter92995f12012-10-06 00:53:28 +00001631
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001632namespace {
Toma Tabacua2861db2015-05-01 10:26:47 +00001633template <unsigned ShiftAmount>
Toma Tabacu61145652015-04-28 13:16:06 +00001634void createLShiftOri(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001635 SmallVectorImpl<MCInst> &Instructions) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001636 MCInst tmpInst;
Toma Tabacua2861db2015-05-01 10:26:47 +00001637 if (ShiftAmount >= 32) {
1638 tmpInst.setOpcode(Mips::DSLL32);
1639 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1640 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1641 tmpInst.addOperand(MCOperand::CreateImm(ShiftAmount - 32));
1642 tmpInst.setLoc(IDLoc);
1643 Instructions.push_back(tmpInst);
1644 tmpInst.clear();
1645 } else if (ShiftAmount > 0) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001646 tmpInst.setOpcode(Mips::DSLL);
1647 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1648 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacua2861db2015-05-01 10:26:47 +00001649 tmpInst.addOperand(MCOperand::CreateImm(ShiftAmount));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001650 tmpInst.setLoc(IDLoc);
1651 Instructions.push_back(tmpInst);
1652 tmpInst.clear();
1653 }
Toma Tabacu7dea2e32015-04-28 14:06:35 +00001654 // There's no need for an ORi if the immediate is 0.
1655 if (Operand.isImm() && Operand.getImm() == 0)
1656 return;
1657
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001658 tmpInst.setOpcode(Mips::ORi);
1659 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1660 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001661 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001662 tmpInst.setLoc(IDLoc);
1663 Instructions.push_back(tmpInst);
1664}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001665
Toma Tabacua2861db2015-05-01 10:26:47 +00001666template <unsigned ShiftAmount>
Toma Tabacu61145652015-04-28 13:16:06 +00001667void createLShiftOri(int64_t Value, unsigned RegNo, SMLoc IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001668 SmallVectorImpl<MCInst> &Instructions) {
1669 createLShiftOri<ShiftAmount>(MCOperand::CreateImm(Value), RegNo, IDLoc,
1670 Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001671}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001672}
1673
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001674bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
1675 SmallVectorImpl<MCInst> &Instructions) {
1676 // Create a JALR instruction which is going to replace the pseudo-JAL.
1677 MCInst JalrInst;
1678 JalrInst.setLoc(IDLoc);
1679 const MCOperand FirstRegOp = Inst.getOperand(0);
1680 const unsigned Opcode = Inst.getOpcode();
1681
1682 if (Opcode == Mips::JalOneReg) {
1683 // jal $rs => jalr $rs
1684 if (inMicroMipsMode()) {
1685 JalrInst.setOpcode(Mips::JALR16_MM);
1686 JalrInst.addOperand(FirstRegOp);
1687 } else {
1688 JalrInst.setOpcode(Mips::JALR);
1689 JalrInst.addOperand(MCOperand::CreateReg(Mips::RA));
1690 JalrInst.addOperand(FirstRegOp);
1691 }
1692 } else if (Opcode == Mips::JalTwoReg) {
1693 // jal $rd, $rs => jalr $rd, $rs
1694 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
1695 JalrInst.addOperand(FirstRegOp);
1696 const MCOperand SecondRegOp = Inst.getOperand(1);
1697 JalrInst.addOperand(SecondRegOp);
1698 }
1699 Instructions.push_back(JalrInst);
1700
1701 // If .set reorder is active, emit a NOP after it.
1702 if (AssemblerOptions.back()->isReorder()) {
1703 // This is a 32-bit NOP because these 2 pseudo-instructions
1704 // do not have a short delay slot.
1705 MCInst NopInst;
1706 NopInst.setOpcode(Mips::SLL);
1707 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1708 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1709 NopInst.addOperand(MCOperand::CreateImm(0));
1710 Instructions.push_back(NopInst);
1711 }
1712
1713 return false;
1714}
1715
Toma Tabacu00e98672015-05-01 12:19:27 +00001716bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001717 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00001718 if (!Is32BitImm && !isGP64bit()) {
1719 Error(IDLoc, "instruction requires a 64-bit architecture");
1720 return true;
1721 }
1722
Jack Carter92995f12012-10-06 00:53:28 +00001723 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001724 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001725 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001726 const MCOperand &RegOp = Inst.getOperand(0);
1727 assert(RegOp.isReg() && "expected register operand kind");
1728
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001729 int64_t ImmValue = ImmOp.getImm();
Toma Tabacu137d90a2015-04-28 12:04:53 +00001730 unsigned Reg = RegOp.getReg();
Jack Carter92995f12012-10-06 00:53:28 +00001731 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001732 // FIXME: gas has a special case for values that are 000...1111, which
1733 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001734 if (0 <= ImmValue && ImmValue <= 65535) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001735 // For unsigned and positive signed 16-bit values (0 <= j <= 65535):
Jack Carter30a59822012-10-04 04:03:53 +00001736 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001737 tmpInst.setOpcode(Mips::ORi);
Toma Tabacu137d90a2015-04-28 12:04:53 +00001738 tmpInst.addOperand(MCOperand::CreateReg(Reg));
Jack Carterd0bd6422013-04-18 00:41:53 +00001739 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001740 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001741 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001742 } else if (ImmValue < 0 && ImmValue >= -32768) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001743 // For negative signed 16-bit values (-32768 <= j < 0):
Jack Carter30a59822012-10-04 04:03:53 +00001744 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001745 tmpInst.setOpcode(Mips::ADDiu);
Toma Tabacu137d90a2015-04-28 12:04:53 +00001746 tmpInst.addOperand(MCOperand::CreateReg(Reg));
Jack Carterd0bd6422013-04-18 00:41:53 +00001747 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001748 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001749 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001750 } else if ((ImmValue & 0xffffffff) == ImmValue) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001751 // For all other values which are representable as a 32-bit integer:
Jack Carter30a59822012-10-04 04:03:53 +00001752 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001753 // ori d,d,lo16(j)
Toma Tabacu79588102015-04-29 10:19:56 +00001754 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1755 uint16_t Bits15To0 = ImmValue & 0xffff;
1756
Jack Carter873c7242013-01-12 01:03:14 +00001757 tmpInst.setOpcode(Mips::LUi);
Toma Tabacu137d90a2015-04-28 12:04:53 +00001758 tmpInst.addOperand(MCOperand::CreateReg(Reg));
Toma Tabacu79588102015-04-29 10:19:56 +00001759 tmpInst.addOperand(MCOperand::CreateImm(Bits31To16));
Jack Carter30a59822012-10-04 04:03:53 +00001760 Instructions.push_back(tmpInst);
Toma Tabacua2861db2015-05-01 10:26:47 +00001761 createLShiftOri<0>(Bits15To0, Reg, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001762 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Toma Tabacu00e98672015-05-01 12:19:27 +00001763 if (Is32BitImm) {
1764 Error(IDLoc, "instruction requires a 32-bit immediate");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001765 return true;
1766 }
1767
1768 // <------- lo32 ------>
1769 // <------- hi32 ------>
1770 // <- hi16 -> <- lo16 ->
1771 // _________________________________
1772 // | | | |
Toma Tabacubda745f2015-04-27 15:21:38 +00001773 // | 16-bits | 16-bits | 16-bits |
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001774 // |__________|__________|__________|
1775 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001776 // For any 64-bit value that is representable as a 48-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001777 // li d,j => lui d,hi16(j)
1778 // ori d,d,hi16(lo32(j))
1779 // dsll d,d,16
1780 // ori d,d,lo16(lo32(j))
Toma Tabacu79588102015-04-29 10:19:56 +00001781 uint16_t Bits47To32 = (ImmValue >> 32) & 0xffff;
1782 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1783 uint16_t Bits15To0 = ImmValue & 0xffff;
1784
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001785 tmpInst.setOpcode(Mips::LUi);
Toma Tabacu137d90a2015-04-28 12:04:53 +00001786 tmpInst.addOperand(MCOperand::CreateReg(Reg));
Toma Tabacu79588102015-04-29 10:19:56 +00001787 tmpInst.addOperand(MCOperand::CreateImm(Bits47To32));
Jack Carter30a59822012-10-04 04:03:53 +00001788 Instructions.push_back(tmpInst);
Toma Tabacua2861db2015-05-01 10:26:47 +00001789 createLShiftOri<0>(Bits31To16, Reg, IDLoc, Instructions);
1790 createLShiftOri<16>(Bits15To0, Reg, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001791 } else {
Toma Tabacu00e98672015-05-01 12:19:27 +00001792 if (Is32BitImm) {
1793 Error(IDLoc, "instruction requires a 32-bit immediate");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001794 return true;
1795 }
1796
1797 // <------- hi32 ------> <------- lo32 ------>
1798 // <- hi16 -> <- lo16 ->
1799 // ___________________________________________
1800 // | | | | |
Toma Tabacubda745f2015-04-27 15:21:38 +00001801 // | 16-bits | 16-bits | 16-bits | 16-bits |
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001802 // |__________|__________|__________|__________|
1803 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001804 // For all other values which are representable as a 64-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001805 // li d,j => lui d,hi16(j)
1806 // ori d,d,lo16(hi32(j))
1807 // dsll d,d,16
1808 // ori d,d,hi16(lo32(j))
1809 // dsll d,d,16
1810 // ori d,d,lo16(lo32(j))
Toma Tabacu79588102015-04-29 10:19:56 +00001811 uint16_t Bits63To48 = (ImmValue >> 48) & 0xffff;
1812 uint16_t Bits47To32 = (ImmValue >> 32) & 0xffff;
1813 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1814 uint16_t Bits15To0 = ImmValue & 0xffff;
1815
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001816 tmpInst.setOpcode(Mips::LUi);
Toma Tabacu137d90a2015-04-28 12:04:53 +00001817 tmpInst.addOperand(MCOperand::CreateReg(Reg));
Toma Tabacu79588102015-04-29 10:19:56 +00001818 tmpInst.addOperand(MCOperand::CreateImm(Bits63To48));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001819 Instructions.push_back(tmpInst);
Toma Tabacua2861db2015-05-01 10:26:47 +00001820 createLShiftOri<0>(Bits47To32, Reg, IDLoc, Instructions);
1821
1822 // When Bits31To16 is 0, do a left shift of 32 bits instead of doing
1823 // two left shifts of 16 bits.
1824 if (Bits31To16 == 0) {
1825 createLShiftOri<32>(Bits15To0, Reg, IDLoc, Instructions);
1826 } else {
1827 createLShiftOri<16>(Bits31To16, Reg, IDLoc, Instructions);
1828 createLShiftOri<16>(Bits15To0, Reg, IDLoc, Instructions);
1829 }
Jack Carter30a59822012-10-04 04:03:53 +00001830 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001831 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001832}
Jack Carter92995f12012-10-06 00:53:28 +00001833
Matheus Almeida3813d572014-06-19 14:39:14 +00001834bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001835MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1836 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001837 MCInst tmpInst;
1838 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001839 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1840 "expected immediate operand kind");
1841 if (!ImmOp.isImm()) {
1842 expandLoadAddressSym(Inst, IDLoc, Instructions);
1843 return false;
1844 }
Jack Carter543fdf82012-10-09 23:29:45 +00001845 const MCOperand &SrcRegOp = Inst.getOperand(1);
1846 assert(SrcRegOp.isReg() && "expected register operand kind");
1847 const MCOperand &DstRegOp = Inst.getOperand(0);
1848 assert(DstRegOp.isReg() && "expected register operand kind");
1849 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001850 if (-32768 <= ImmValue && ImmValue <= 65535) {
1851 // For -32768 <= j <= 65535.
1852 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001853 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001854 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1855 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1856 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1857 Instructions.push_back(tmpInst);
1858 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001859 // For any other value of j that is representable as a 32-bit integer.
1860 // la d,j(s) => lui d,hi16(j)
1861 // ori d,d,lo16(j)
1862 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001863 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001864 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1865 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1866 Instructions.push_back(tmpInst);
1867 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001868 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001869 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1870 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1871 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1872 Instructions.push_back(tmpInst);
1873 tmpInst.clear();
1874 tmpInst.setOpcode(Mips::ADDu);
1875 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1876 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1877 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1878 Instructions.push_back(tmpInst);
1879 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001880 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001881}
1882
Matheus Almeida3813d572014-06-19 14:39:14 +00001883bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001884MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1885 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001886 MCInst tmpInst;
1887 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001888 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1889 "expected immediate operand kind");
1890 if (!ImmOp.isImm()) {
1891 expandLoadAddressSym(Inst, IDLoc, Instructions);
1892 return false;
1893 }
Jack Carter543fdf82012-10-09 23:29:45 +00001894 const MCOperand &RegOp = Inst.getOperand(0);
1895 assert(RegOp.isReg() && "expected register operand kind");
1896 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001897 if (-32768 <= ImmValue && ImmValue <= 65535) {
1898 // For -32768 <= j <= 65535.
1899 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001900 tmpInst.setOpcode(Mips::ADDiu);
1901 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001902 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001903 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1904 Instructions.push_back(tmpInst);
1905 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001906 // For any other value of j that is representable as a 32-bit integer.
1907 // la d,j => lui d,hi16(j)
1908 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001909 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001910 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1911 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1912 Instructions.push_back(tmpInst);
1913 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001914 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001915 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1916 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1917 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1918 Instructions.push_back(tmpInst);
1919 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001920 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001921}
1922
Toma Tabacu0d64b202014-08-14 10:29:17 +00001923void
1924MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1925 SmallVectorImpl<MCInst> &Instructions) {
1926 // FIXME: If we do have a valid at register to use, we should generate a
1927 // slightly shorter sequence here.
1928 MCInst tmpInst;
1929 int ExprOperandNo = 1;
1930 // Sometimes the assembly parser will get the immediate expression as
1931 // a $zero + an immediate.
1932 if (Inst.getNumOperands() == 3) {
1933 assert(Inst.getOperand(1).getReg() ==
1934 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1935 ExprOperandNo = 2;
1936 }
1937 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1938 assert(SymOp.isExpr() && "expected symbol operand kind");
1939 const MCOperand &RegOp = Inst.getOperand(0);
1940 unsigned RegNo = RegOp.getReg();
1941 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1942 const MCSymbolRefExpr *HiExpr =
1943 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1944 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1945 const MCSymbolRefExpr *LoExpr =
1946 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1947 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1948 if (isGP64bit()) {
1949 // If it's a 64-bit architecture, expand to:
1950 // la d,sym => lui d,highest(sym)
1951 // ori d,d,higher(sym)
1952 // dsll d,d,16
1953 // ori d,d,hi16(sym)
1954 // dsll d,d,16
1955 // ori d,d,lo16(sym)
1956 const MCSymbolRefExpr *HighestExpr =
1957 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1958 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1959 const MCSymbolRefExpr *HigherExpr =
1960 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1961 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1962
1963 tmpInst.setOpcode(Mips::LUi);
1964 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1965 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1966 Instructions.push_back(tmpInst);
1967
Toma Tabacua2861db2015-05-01 10:26:47 +00001968 createLShiftOri<0>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1969 Instructions);
1970 createLShiftOri<16>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00001971 Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001972 createLShiftOri<16>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00001973 Instructions);
1974 } else {
1975 // Otherwise, expand to:
1976 // la d,sym => lui d,hi16(sym)
1977 // ori d,d,lo16(sym)
1978 tmpInst.setOpcode(Mips::LUi);
1979 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1980 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1981 Instructions.push_back(tmpInst);
1982
Toma Tabacua2861db2015-05-01 10:26:47 +00001983 createLShiftOri<0>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1984 Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001985 }
1986}
1987
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00001988bool MipsAsmParser::expandUncondBranchMMPseudo(
1989 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00001990 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
1991 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001992
1993 MCOperand Offset = Inst.getOperand(0);
1994 if (Offset.isExpr()) {
1995 Inst.clear();
1996 Inst.setOpcode(Mips::BEQ_MM);
1997 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1998 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1999 Inst.addOperand(MCOperand::CreateExpr(Offset.getExpr()));
2000 } else {
2001 assert(Offset.isImm() && "expected immediate operand kind");
2002 if (isIntN(11, Offset.getImm())) {
2003 // If offset fits into 11 bits then this instruction becomes microMIPS
2004 // 16-bit unconditional branch instruction.
2005 Inst.setOpcode(Mips::B16_MM);
2006 } else {
2007 if (!isIntN(17, Offset.getImm()))
2008 Error(IDLoc, "branch target out of range");
2009 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2010 Error(IDLoc, "branch to misaligned address");
2011 Inst.clear();
2012 Inst.setOpcode(Mips::BEQ_MM);
2013 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2014 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2015 Inst.addOperand(MCOperand::CreateImm(Offset.getImm()));
2016 }
2017 }
2018 Instructions.push_back(Inst);
2019
Toma Tabacu234482a2015-03-16 12:03:39 +00002020 // If .set reorder is active, emit a NOP after the branch instruction.
2021 if (AssemblerOptions.back()->isReorder())
2022 createNop(true, IDLoc, Instructions);
2023
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002024 return false;
2025}
2026
Jack Carter9e65aa32013-03-22 00:05:30 +00002027void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002028 SmallVectorImpl<MCInst> &Instructions,
2029 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002030 const MCSymbolRefExpr *SR;
2031 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00002032 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002033 const MCExpr *ExprOffset;
2034 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002035 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002036 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2037 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002038 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002039 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2040 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002041 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002042 if (isImmOpnd) {
2043 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2044 ImmOffset = Inst.getOperand(2).getImm();
2045 LoOffset = ImmOffset & 0x0000ffff;
2046 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002047 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002048 if (LoOffset & 0x8000)
2049 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002050 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002051 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002052 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002053 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002054 // These are some of the types of expansions we perform here:
2055 // 1) lw $8, sym => lui $8, %hi(sym)
2056 // lw $8, %lo(sym)($8)
2057 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2058 // add $8, $8, $9
2059 // lw $8, %lo(offset)($9)
2060 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2061 // add $at, $at, $8
2062 // lw $8, %lo(offset)($at)
2063 // 4) sw $8, sym => lui $at, %hi(sym)
2064 // sw $8, %lo(sym)($at)
2065 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2066 // add $at, $at, $8
2067 // sw $8, %lo(offset)($at)
2068 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2069 // ldc1 $f0, %lo(sym)($at)
2070 //
2071 // For load instructions we can use the destination register as a temporary
2072 // if base and dst are different (examples 1 and 2) and if the base register
2073 // is general purpose otherwise we must use $at (example 6) and error if it's
2074 // not available. For stores we must use $at (examples 4 and 5) because we
2075 // must not clobber the source register setting up the offset.
2076 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2077 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2078 unsigned RegClassIDOp0 =
2079 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2080 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2081 (RegClassIDOp0 == Mips::GPR64RegClassID);
2082 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002083 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002084 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002085 // At this point we need AT to perform the expansions and we exit if it is
2086 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002087 TmpRegNum = getATReg(IDLoc);
2088 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002089 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002090 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002091
Jack Carter9e65aa32013-03-22 00:05:30 +00002092 TempInst.setOpcode(Mips::LUi);
2093 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2094 if (isImmOpnd)
2095 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
2096 else {
2097 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002098 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00002099 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
2100 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
2101 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00002102 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002103 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002104 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00002105 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002106 }
2107 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002108 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002109 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002110 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002111 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002112 // Add temp register to base.
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002113 if (BaseRegNum != Mips::ZERO) {
2114 TempInst.setOpcode(Mips::ADDu);
2115 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2116 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2117 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
2118 Instructions.push_back(TempInst);
2119 TempInst.clear();
2120 }
Alp Tokercb402912014-01-24 17:20:08 +00002121 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002122 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002123 TempInst.setOpcode(Inst.getOpcode());
2124 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
2125 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2126 if (isImmOpnd)
2127 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
2128 else {
2129 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002130 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
2131 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
2132 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00002133 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002134 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002135 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00002136 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002137 }
2138 }
2139 Instructions.push_back(TempInst);
2140 TempInst.clear();
2141}
2142
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002143bool
2144MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2145 SmallVectorImpl<MCInst> &Instructions) {
2146 unsigned OpNum = Inst.getNumOperands();
2147 unsigned Opcode = Inst.getOpcode();
2148 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2149
2150 assert (Inst.getOperand(OpNum - 1).isImm() &&
2151 Inst.getOperand(OpNum - 2).isReg() &&
2152 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2153
2154 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2155 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2156 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2157 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2158 // It can be implemented as SWM16 or LWM16 instruction.
2159 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2160
2161 Inst.setOpcode(NewOpcode);
2162 Instructions.push_back(Inst);
2163 return false;
2164}
2165
Toma Tabacu234482a2015-03-16 12:03:39 +00002166void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
2167 SmallVectorImpl<MCInst> &Instructions) {
2168 MCInst NopInst;
2169 if (hasShortDelaySlot) {
2170 NopInst.setOpcode(Mips::MOVE16_MM);
2171 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2172 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2173 } else {
2174 NopInst.setOpcode(Mips::SLL);
2175 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2176 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2177 NopInst.addOperand(MCOperand::CreateImm(0));
2178 }
2179 Instructions.push_back(NopInst);
2180}
2181
Matheus Almeida595fcab2014-06-11 15:05:56 +00002182unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
2183 // As described by the Mips32r2 spec, the registers Rd and Rs for
2184 // jalr.hb must be different.
2185 unsigned Opcode = Inst.getOpcode();
2186
2187 if (Opcode == Mips::JALR_HB &&
2188 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
2189 return Match_RequiresDifferentSrcAndDst;
2190
2191 return Match_Success;
2192}
2193
David Blaikie960ea3f2014-06-08 16:18:35 +00002194bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
2195 OperandVector &Operands,
2196 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00002197 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00002198 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00002199
Jack Carterb4dbc172012-09-05 23:34:03 +00002200 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00002201 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00002202 unsigned MatchResult =
2203 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00002204
2205 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002206 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002207 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00002208 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00002209 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00002210 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00002211 return false;
2212 }
2213 case Match_MissingFeature:
2214 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
2215 return true;
2216 case Match_InvalidOperand: {
2217 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00002218 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002219 if (ErrorInfo >= Operands.size())
2220 return Error(IDLoc, "too few operands for instruction");
2221
David Blaikie960ea3f2014-06-08 16:18:35 +00002222 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00002223 if (ErrorLoc == SMLoc())
2224 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00002225 }
2226
2227 return Error(ErrorLoc, "invalid operand for instruction");
2228 }
2229 case Match_MnemonicFail:
2230 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00002231 case Match_RequiresDifferentSrcAndDst:
2232 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00002233 }
Craig Topper589ceee2015-01-03 08:16:34 +00002234
2235 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00002236}
2237
Toma Tabacud9d344b2015-04-27 14:05:04 +00002238void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
2239 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
2240 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
2241 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002242}
2243
Daniel Sandersef638fe2014-10-03 15:37:37 +00002244void
2245MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
2246 SMRange Range, bool ShowColors) {
2247 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00002248 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00002249 ShowColors);
2250}
2251
Jack Carter1ac53222013-02-20 23:11:17 +00002252int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002253 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002254
Vladimir Medic4c299852013-11-06 11:27:05 +00002255 CC = StringSwitch<unsigned>(Name)
2256 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002257 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00002258 .Case("a0", 4)
2259 .Case("a1", 5)
2260 .Case("a2", 6)
2261 .Case("a3", 7)
2262 .Case("v0", 2)
2263 .Case("v1", 3)
2264 .Case("s0", 16)
2265 .Case("s1", 17)
2266 .Case("s2", 18)
2267 .Case("s3", 19)
2268 .Case("s4", 20)
2269 .Case("s5", 21)
2270 .Case("s6", 22)
2271 .Case("s7", 23)
2272 .Case("k0", 26)
2273 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002274 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00002275 .Case("sp", 29)
2276 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002277 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00002278 .Case("ra", 31)
2279 .Case("t0", 8)
2280 .Case("t1", 9)
2281 .Case("t2", 10)
2282 .Case("t3", 11)
2283 .Case("t4", 12)
2284 .Case("t5", 13)
2285 .Case("t6", 14)
2286 .Case("t7", 15)
2287 .Case("t8", 24)
2288 .Case("t9", 25)
2289 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002290
Toma Tabacufda445c2014-09-15 15:33:01 +00002291 if (!(isABI_N32() || isABI_N64()))
2292 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002293
Daniel Sandersef638fe2014-10-03 15:37:37 +00002294 if (12 <= CC && CC <= 15) {
2295 // Name is one of t4-t7
2296 AsmToken RegTok = getLexer().peekTok();
2297 SMRange RegRange = RegTok.getLocRange();
2298
2299 StringRef FixedName = StringSwitch<StringRef>(Name)
2300 .Case("t4", "t0")
2301 .Case("t5", "t1")
2302 .Case("t6", "t2")
2303 .Case("t7", "t3")
2304 .Default("");
2305 assert(FixedName != "" && "Register name is not one of t4-t7.");
2306
2307 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
2308 "Did you mean $" + FixedName + "?", RegRange);
2309 }
2310
Toma Tabacufda445c2014-09-15 15:33:01 +00002311 // Although SGI documentation just cuts out t0-t3 for n32/n64,
2312 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
2313 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
2314 if (8 <= CC && CC <= 11)
2315 CC += 4;
2316
2317 if (CC == -1)
2318 CC = StringSwitch<unsigned>(Name)
2319 .Case("a4", 8)
2320 .Case("a5", 9)
2321 .Case("a6", 10)
2322 .Case("a7", 11)
2323 .Case("kt0", 26)
2324 .Case("kt1", 27)
2325 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002326
2327 return CC;
2328}
Jack Carterd0bd6422013-04-18 00:41:53 +00002329
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002330int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
2331 int CC;
2332
2333 CC = StringSwitch<unsigned>(Name)
2334 .Case("hwr_cpunum", 0)
2335 .Case("hwr_synci_step", 1)
2336 .Case("hwr_cc", 2)
2337 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00002338 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002339 .Default(-1);
2340
2341 return CC;
2342}
2343
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002344int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002345
Jack Cartera63b16a2012-09-07 00:23:42 +00002346 if (Name[0] == 'f') {
2347 StringRef NumString = Name.substr(1);
2348 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002349 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002350 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002351 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00002352 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002353 return IntVal;
2354 }
2355 return -1;
2356}
Jack Cartera63b16a2012-09-07 00:23:42 +00002357
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002358int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
2359
2360 if (Name.startswith("fcc")) {
2361 StringRef NumString = Name.substr(3);
2362 unsigned IntVal;
2363 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002364 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002365 if (IntVal > 7) // There are only 8 fcc registers.
2366 return -1;
2367 return IntVal;
2368 }
2369 return -1;
2370}
2371
2372int MipsAsmParser::matchACRegisterName(StringRef Name) {
2373
Akira Hatanaka274d24c2013-08-14 01:15:52 +00002374 if (Name.startswith("ac")) {
2375 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002376 unsigned IntVal;
2377 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002378 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002379 if (IntVal > 3) // There are only 3 acc registers.
2380 return -1;
2381 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00002382 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002383 return -1;
2384}
Jack Carterd0bd6422013-04-18 00:41:53 +00002385
Jack Carter5dc8ac92013-09-25 23:50:44 +00002386int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
2387 unsigned IntVal;
2388
2389 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2390 return -1;
2391
2392 if (IntVal > 31)
2393 return -1;
2394
2395 return IntVal;
2396}
2397
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002398int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
2399 int CC;
2400
2401 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00002402 .Case("msair", 0)
2403 .Case("msacsr", 1)
2404 .Case("msaaccess", 2)
2405 .Case("msasave", 3)
2406 .Case("msamodify", 4)
2407 .Case("msarequest", 5)
2408 .Case("msamap", 6)
2409 .Case("msaunmap", 7)
2410 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002411
2412 return CC;
2413}
2414
Toma Tabacu89a712b2015-04-15 10:48:56 +00002415unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00002416 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00002417 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002418 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00002419 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00002420 return 0;
2421 }
2422 unsigned AT = getReg(
2423 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00002424 return AT;
2425}
Jack Carter0b744b32012-10-04 02:29:46 +00002426
Jack Carterd0bd6422013-04-18 00:41:53 +00002427unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00002428 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00002429}
2430
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002431unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002432 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00002433 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002434}
2435
Jack Carter873c7242013-01-12 01:03:14 +00002436int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002437 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00002438 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00002439 return -1;
2440
Jack Carter873c7242013-01-12 01:03:14 +00002441 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00002442}
2443
Toma Tabacu13964452014-09-04 13:23:44 +00002444bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002445 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002446 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002447
Jack Carter30a59822012-10-04 04:03:53 +00002448 // Check if the current operand has a custom associated parser, if so, try to
2449 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00002450 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2451 if (ResTy == MatchOperand_Success)
2452 return false;
2453 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2454 // there was a match, but an error occurred, in which case, just return that
2455 // the operand parsing failed.
2456 if (ResTy == MatchOperand_ParseFail)
2457 return true;
2458
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002459 DEBUG(dbgs() << ".. Generic Parser\n");
2460
Jack Carterb4dbc172012-09-05 23:34:03 +00002461 switch (getLexer().getKind()) {
2462 default:
2463 Error(Parser.getTok().getLoc(), "unexpected token in operand");
2464 return true;
2465 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002466 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00002467 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00002468
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002469 // Almost all registers have been parsed by custom parsers. There is only
2470 // one exception to this. $zero (and it's alias $0) will reach this point
2471 // for div, divu, and similar instructions because it is not an operand
2472 // to the instruction definition but an explicit register. Special case
2473 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00002474 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00002475 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002476
Jack Carterd0bd6422013-04-18 00:41:53 +00002477 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00002478 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002479 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00002480 return true;
2481
Jack Carter873c7242013-01-12 01:03:14 +00002482 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00002483 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00002484 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00002485 const MCExpr *Res =
2486 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00002487
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002488 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002489 return false;
2490 }
Vladimir Medic4c299852013-11-06 11:27:05 +00002491 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00002492 case AsmToken::LParen:
2493 case AsmToken::Minus:
2494 case AsmToken::Plus:
2495 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002496 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00002497 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002498 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002499 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002500 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00002501 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00002502 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002503 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002504 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002505 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00002506 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00002507 return true;
2508
Jack Carter873c7242013-01-12 01:03:14 +00002509 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2510
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002511 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00002512 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002513 } // case AsmToken::Percent
2514 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00002515 return true;
2516}
2517
Vladimir Medic4c299852013-11-06 11:27:05 +00002518const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00002519 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00002520 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00002521 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002522 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00002523 // It's a constant, evaluate reloc value.
2524 int16_t Val;
2525 switch (getVariantKind(RelocStr)) {
2526 case MCSymbolRefExpr::VK_Mips_ABS_LO:
2527 // Get the 1st 16-bits.
2528 Val = MCE->getValue() & 0xffff;
2529 break;
2530 case MCSymbolRefExpr::VK_Mips_ABS_HI:
2531 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2532 // 16 bits being negative.
2533 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2534 break;
2535 case MCSymbolRefExpr::VK_Mips_HIGHER:
2536 // Get the 3rd 16-bits.
2537 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2538 break;
2539 case MCSymbolRefExpr::VK_Mips_HIGHEST:
2540 // Get the 4th 16-bits.
2541 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2542 break;
2543 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00002544 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00002545 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00002546 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002547 }
2548
Jack Carterb5cf5902013-04-17 00:18:04 +00002549 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002550 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00002551 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00002552 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00002553 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002554 return Res;
2555 }
2556
2557 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00002558 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2559
Sasa Stankovic06c47802014-04-03 10:37:45 +00002560 // Try to create target expression.
2561 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
2562 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002563
Jack Carterd0bd6422013-04-18 00:41:53 +00002564 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2565 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00002566 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
2567 return Res;
2568 }
2569
2570 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002571 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
2572 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
2573 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002574 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002575 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002576 return Expr;
2577}
2578
2579bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2580
2581 switch (Expr->getKind()) {
2582 case MCExpr::Constant:
2583 return true;
2584 case MCExpr::SymbolRef:
2585 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2586 case MCExpr::Binary:
2587 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2588 if (!isEvaluated(BE->getLHS()))
2589 return false;
2590 return isEvaluated(BE->getRHS());
2591 }
2592 case MCExpr::Unary:
2593 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002594 case MCExpr::Target:
2595 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002596 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002597 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002598}
Jack Carterd0bd6422013-04-18 00:41:53 +00002599
Jack Carterb5cf5902013-04-17 00:18:04 +00002600bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002601 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00002602 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002603 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002604 if (Tok.isNot(AsmToken::Identifier))
2605 return true;
2606
Yaron Keren075759a2015-03-30 15:42:36 +00002607 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00002608
Jack Carterd0bd6422013-04-18 00:41:53 +00002609 Parser.Lex(); // Eat the identifier.
2610 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002611 const MCExpr *IdVal;
2612 SMLoc EndLoc;
2613
2614 if (getLexer().getKind() == AsmToken::LParen) {
2615 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002616 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002617 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002618 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002619 const AsmToken &nextTok = Parser.getTok();
2620 if (nextTok.isNot(AsmToken::Identifier))
2621 return true;
2622 Str += "(%";
2623 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002624 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002625 if (getLexer().getKind() != AsmToken::LParen)
2626 return true;
2627 } else
2628 break;
2629 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002630 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002631 return true;
2632
2633 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002634 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002635
2636 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002637 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002638
Jack Carterd0bd6422013-04-18 00:41:53 +00002639 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002640 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002641}
2642
Jack Carterb4dbc172012-09-05 23:34:03 +00002643bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2644 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002645 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002646 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002647 if (ResTy == MatchOperand_Success) {
2648 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002649 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002650 StartLoc = Operand.getStartLoc();
2651 EndLoc = Operand.getEndLoc();
2652
2653 // AFAIK, we only support numeric registers and named GPR's in CFI
2654 // directives.
2655 // Don't worry about eating tokens before failing. Using an unrecognised
2656 // register is a parse error.
2657 if (Operand.isGPRAsmReg()) {
2658 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002659 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002660 }
2661
2662 return (RegNo == (unsigned)-1);
2663 }
2664
2665 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002666 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002667}
2668
Jack Carterb5cf5902013-04-17 00:18:04 +00002669bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002670 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00002671 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002672 bool Result = true;
2673
2674 while (getLexer().getKind() == AsmToken::LParen)
2675 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002676
Jack Carterd0bd6422013-04-18 00:41:53 +00002677 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002678 default:
2679 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002680 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002681 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002682 case AsmToken::Integer:
2683 case AsmToken::Minus:
2684 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002685 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002686 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002687 else
2688 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002689 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002690 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002691 break;
Jack Carter873c7242013-01-12 01:03:14 +00002692 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002693 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002694 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002695 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002696}
2697
David Blaikie960ea3f2014-06-08 16:18:35 +00002698MipsAsmParser::OperandMatchResultTy
2699MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002700 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002701 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002702 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002703 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002704 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002705 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002706 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002707 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002708
Jack Carterb5cf5902013-04-17 00:18:04 +00002709 if (getLexer().getKind() == AsmToken::LParen) {
2710 Parser.Lex();
2711 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002712 }
2713
Jack Carterb5cf5902013-04-17 00:18:04 +00002714 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002715 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002716 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002717
Jack Carterd0bd6422013-04-18 00:41:53 +00002718 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002719 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002720 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2721 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002722 SMLoc E =
2723 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002724 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002725 return MatchOperand_Success;
2726 }
2727 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002728 SMLoc E =
2729 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002730
Jack Carterd0bd6422013-04-18 00:41:53 +00002731 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002732 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002733 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002734 S, E, *this);
2735 Operands.push_back(
2736 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002737 return MatchOperand_Success;
2738 }
2739 Error(Parser.getTok().getLoc(), "'(' expected");
2740 return MatchOperand_ParseFail;
2741 }
2742
Jack Carterd0bd6422013-04-18 00:41:53 +00002743 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002744 }
2745
Toma Tabacu13964452014-09-04 13:23:44 +00002746 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002747 if (Res != MatchOperand_Success)
2748 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002749
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002750 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002751 Error(Parser.getTok().getLoc(), "')' expected");
2752 return MatchOperand_ParseFail;
2753 }
2754
Jack Carter873c7242013-01-12 01:03:14 +00002755 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2756
Jack Carterd0bd6422013-04-18 00:41:53 +00002757 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002758
Craig Topper062a2ba2014-04-25 05:30:21 +00002759 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002760 IdVal = MCConstantExpr::Create(0, getContext());
2761
Jack Carterd0bd6422013-04-18 00:41:53 +00002762 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002763 std::unique_ptr<MipsOperand> op(
2764 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002765 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002766 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002767 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002768 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002769 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2770 int64_t Imm;
2771 if (IdVal->EvaluateAsAbsolute(Imm))
2772 IdVal = MCConstantExpr::Create(Imm, getContext());
2773 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2774 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2775 getContext());
2776 }
2777
David Blaikie960ea3f2014-06-08 16:18:35 +00002778 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002779 return MatchOperand_Success;
2780}
2781
David Blaikie960ea3f2014-06-08 16:18:35 +00002782bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002783 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00002784 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2785 if (Sym) {
2786 SMLoc S = Parser.getTok().getLoc();
2787 const MCExpr *Expr;
2788 if (Sym->isVariable())
2789 Expr = Sym->getVariableValue();
2790 else
2791 return false;
2792 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002793 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002794 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002795 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002796 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002797 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002798 if (ResTy == MatchOperand_Success) {
2799 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002800 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002801 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002802 llvm_unreachable("Should never ParseFail");
2803 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002804 }
2805 } else if (Expr->getKind() == MCExpr::Constant) {
2806 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002807 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002808 Operands.push_back(
2809 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002810 return true;
2811 }
2812 }
2813 return false;
2814}
Jack Carterd0bd6422013-04-18 00:41:53 +00002815
Jack Carter873c7242013-01-12 01:03:14 +00002816MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002817MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002818 StringRef Identifier,
2819 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002820 int Index = matchCPURegisterName(Identifier);
2821 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002822 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002823 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2824 return MatchOperand_Success;
2825 }
2826
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002827 Index = matchHWRegsRegisterName(Identifier);
2828 if (Index != -1) {
2829 Operands.push_back(MipsOperand::createHWRegsReg(
2830 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2831 return MatchOperand_Success;
2832 }
2833
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002834 Index = matchFPURegisterName(Identifier);
2835 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002836 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002837 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2838 return MatchOperand_Success;
2839 }
2840
2841 Index = matchFCCRegisterName(Identifier);
2842 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002843 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002844 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2845 return MatchOperand_Success;
2846 }
2847
2848 Index = matchACRegisterName(Identifier);
2849 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002850 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002851 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2852 return MatchOperand_Success;
2853 }
2854
2855 Index = matchMSA128RegisterName(Identifier);
2856 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002857 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002858 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2859 return MatchOperand_Success;
2860 }
2861
2862 Index = matchMSA128CtrlRegisterName(Identifier);
2863 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002864 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002865 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2866 return MatchOperand_Success;
2867 }
2868
2869 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002870}
2871
2872MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002873MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002874 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00002875 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002876
2877 if (Token.is(AsmToken::Identifier)) {
2878 DEBUG(dbgs() << ".. identifier\n");
2879 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002880 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002881 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002882 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002883 } else if (Token.is(AsmToken::Integer)) {
2884 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002885 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002886 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2887 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002888 return MatchOperand_Success;
2889 }
2890
2891 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2892
2893 return MatchOperand_NoMatch;
2894}
2895
David Blaikie960ea3f2014-06-08 16:18:35 +00002896MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002897MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002898 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002899 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002900
2901 auto Token = Parser.getTok();
2902
2903 SMLoc S = Token.getLoc();
2904
2905 if (Token.isNot(AsmToken::Dollar)) {
2906 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2907 if (Token.is(AsmToken::Identifier)) {
2908 if (searchSymbolAlias(Operands))
2909 return MatchOperand_Success;
2910 }
2911 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2912 return MatchOperand_NoMatch;
2913 }
2914 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002915
Toma Tabacu13964452014-09-04 13:23:44 +00002916 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002917 if (ResTy == MatchOperand_Success) {
2918 Parser.Lex(); // $
2919 Parser.Lex(); // identifier
2920 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002921 return ResTy;
2922}
2923
2924MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002925MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002926 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002927 switch (getLexer().getKind()) {
2928 default:
2929 return MatchOperand_NoMatch;
2930 case AsmToken::LParen:
2931 case AsmToken::Minus:
2932 case AsmToken::Plus:
2933 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002934 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002935 case AsmToken::String:
2936 break;
2937 }
2938
2939 const MCExpr *IdVal;
2940 SMLoc S = Parser.getTok().getLoc();
2941 if (getParser().parseExpression(IdVal))
2942 return MatchOperand_ParseFail;
2943
2944 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2945 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2946 return MatchOperand_Success;
2947}
2948
David Blaikie960ea3f2014-06-08 16:18:35 +00002949MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002950MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002951 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002952 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002953
2954 SMLoc S = getLexer().getLoc();
2955
2956 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002957 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002958 if (ResTy != MatchOperand_NoMatch)
2959 return ResTy;
2960
Daniel Sanders315386c2014-04-01 10:40:14 +00002961 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002962 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002963 if (ResTy != MatchOperand_NoMatch)
2964 return ResTy;
2965
Daniel Sandersffd84362014-04-01 10:41:48 +00002966 const MCExpr *Expr = nullptr;
2967 if (Parser.parseExpression(Expr)) {
2968 // We have no way of knowing if a symbol was consumed so we must ParseFail
2969 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002970 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002971 Operands.push_back(
2972 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002973 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002974}
2975
Vladimir Medic2b953d02013-10-01 09:48:56 +00002976MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002977MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002978 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00002979 const MCExpr *IdVal;
2980 // If the first token is '$' we may have register operand.
2981 if (Parser.getTok().is(AsmToken::Dollar))
2982 return MatchOperand_NoMatch;
2983 SMLoc S = Parser.getTok().getLoc();
2984 if (getParser().parseExpression(IdVal))
2985 return MatchOperand_ParseFail;
2986 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002987 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002988 int64_t Val = MCE->getValue();
2989 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2990 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002991 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002992 return MatchOperand_Success;
2993}
2994
Matheus Almeida779c5932013-11-18 12:32:49 +00002995MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002996MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002997 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00002998 switch (getLexer().getKind()) {
2999 default:
3000 return MatchOperand_NoMatch;
3001 case AsmToken::LParen:
3002 case AsmToken::Plus:
3003 case AsmToken::Minus:
3004 case AsmToken::Integer:
3005 break;
3006 }
3007
3008 const MCExpr *Expr;
3009 SMLoc S = Parser.getTok().getLoc();
3010
3011 if (getParser().parseExpression(Expr))
3012 return MatchOperand_ParseFail;
3013
3014 int64_t Val;
3015 if (!Expr->EvaluateAsAbsolute(Val)) {
3016 Error(S, "expected immediate value");
3017 return MatchOperand_ParseFail;
3018 }
3019
3020 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
3021 // and because the CPU always adds one to the immediate field, the allowed
3022 // range becomes 1..4. We'll only check the range here and will deal
3023 // with the addition/subtraction when actually decoding/encoding
3024 // the instruction.
3025 if (Val < 1 || Val > 4) {
3026 Error(S, "immediate not in range (1..4)");
3027 return MatchOperand_ParseFail;
3028 }
3029
Jack Carter3b2c96e2014-01-22 23:31:38 +00003030 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003031 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00003032 return MatchOperand_Success;
3033}
3034
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00003035MipsAsmParser::OperandMatchResultTy
3036MipsAsmParser::parseRegisterList(OperandVector &Operands) {
3037 MCAsmParser &Parser = getParser();
3038 SmallVector<unsigned, 10> Regs;
3039 unsigned RegNo;
3040 unsigned PrevReg = Mips::NoRegister;
3041 bool RegRange = false;
3042 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3043
3044 if (Parser.getTok().isNot(AsmToken::Dollar))
3045 return MatchOperand_ParseFail;
3046
3047 SMLoc S = Parser.getTok().getLoc();
3048 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
3049 SMLoc E = getLexer().getLoc();
3050 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
3051 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
3052 if (RegRange) {
3053 // Remove last register operand because registers from register range
3054 // should be inserted first.
3055 if (RegNo == Mips::RA) {
3056 Regs.push_back(RegNo);
3057 } else {
3058 unsigned TmpReg = PrevReg + 1;
3059 while (TmpReg <= RegNo) {
3060 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
3061 Error(E, "invalid register operand");
3062 return MatchOperand_ParseFail;
3063 }
3064
3065 PrevReg = TmpReg;
3066 Regs.push_back(TmpReg++);
3067 }
3068 }
3069
3070 RegRange = false;
3071 } else {
3072 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
3073 (RegNo != Mips::RA)) {
3074 Error(E, "$16 or $31 expected");
3075 return MatchOperand_ParseFail;
3076 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
3077 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3078 Error(E, "invalid register operand");
3079 return MatchOperand_ParseFail;
3080 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
3081 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3082 Error(E, "consecutive register numbers expected");
3083 return MatchOperand_ParseFail;
3084 }
3085
3086 Regs.push_back(RegNo);
3087 }
3088
3089 if (Parser.getTok().is(AsmToken::Minus))
3090 RegRange = true;
3091
3092 if (!Parser.getTok().isNot(AsmToken::Minus) &&
3093 !Parser.getTok().isNot(AsmToken::Comma)) {
3094 Error(E, "',' or '-' expected");
3095 return MatchOperand_ParseFail;
3096 }
3097
3098 Lex(); // Consume comma or minus
3099 if (Parser.getTok().isNot(AsmToken::Dollar))
3100 break;
3101
3102 PrevReg = RegNo;
3103 }
3104
3105 SMLoc E = Parser.getTok().getLoc();
3106 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3107 parseMemOperand(Operands);
3108 return MatchOperand_Success;
3109}
3110
Zoran Jovanovic2deca342014-12-16 14:59:10 +00003111MipsAsmParser::OperandMatchResultTy
3112MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
3113 MCAsmParser &Parser = getParser();
3114
3115 SMLoc S = Parser.getTok().getLoc();
3116 if (parseAnyRegister(Operands) != MatchOperand_Success)
3117 return MatchOperand_ParseFail;
3118
3119 SMLoc E = Parser.getTok().getLoc();
3120 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
3121 unsigned Reg = Op.getGPR32Reg();
3122 Operands.pop_back();
3123 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
3124 return MatchOperand_Success;
3125}
3126
Zoran Jovanovic41688672015-02-10 16:36:20 +00003127MipsAsmParser::OperandMatchResultTy
3128MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
3129 MCAsmParser &Parser = getParser();
3130 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3131 SmallVector<unsigned, 10> Regs;
3132
3133 if (Parser.getTok().isNot(AsmToken::Dollar))
3134 return MatchOperand_ParseFail;
3135
3136 SMLoc S = Parser.getTok().getLoc();
3137
3138 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3139 return MatchOperand_ParseFail;
3140
3141 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3142 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3143 Regs.push_back(RegNo);
3144
3145 SMLoc E = Parser.getTok().getLoc();
3146 if (Parser.getTok().isNot(AsmToken::Comma)) {
3147 Error(E, "',' expected");
3148 return MatchOperand_ParseFail;
3149 }
3150
3151 // Remove comma.
3152 Parser.Lex();
3153
3154 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3155 return MatchOperand_ParseFail;
3156
3157 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3158 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3159 Regs.push_back(RegNo);
3160
3161 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3162
3163 return MatchOperand_Success;
3164}
3165
Jack Carterdc1e35d2012-09-06 20:00:02 +00003166MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
3167
Vladimir Medic4c299852013-11-06 11:27:05 +00003168 MCSymbolRefExpr::VariantKind VK =
3169 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
3170 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
3171 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
3172 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
3173 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
3174 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
3175 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
3176 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
3177 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
3178 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
3179 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
3180 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
3181 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
3182 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
3183 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
3184 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
3185 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
3186 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00003187 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
3188 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
3189 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
3190 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
3191 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
3192 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00003193 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
3194 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00003195 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003196
Matheus Almeida2852af82014-04-22 10:15:54 +00003197 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00003198
Jack Carterdc1e35d2012-09-06 20:00:02 +00003199 return VK;
3200}
Jack Cartera63b16a2012-09-07 00:23:42 +00003201
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003202/// Sometimes (i.e. load/stores) the operand may be followed immediately by
3203/// either this.
3204/// ::= '(', register, ')'
3205/// handle it before we iterate so we don't get tripped up by the lack of
3206/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003207bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003208 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003209 if (getLexer().is(AsmToken::LParen)) {
3210 Operands.push_back(
3211 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
3212 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003213 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003214 SMLoc Loc = getLexer().getLoc();
3215 Parser.eatToEndOfStatement();
3216 return Error(Loc, "unexpected token in argument list");
3217 }
3218 if (Parser.getTok().isNot(AsmToken::RParen)) {
3219 SMLoc Loc = getLexer().getLoc();
3220 Parser.eatToEndOfStatement();
3221 return Error(Loc, "unexpected token, expected ')'");
3222 }
3223 Operands.push_back(
3224 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
3225 Parser.Lex();
3226 }
3227 return false;
3228}
3229
3230/// Sometimes (i.e. in MSA) the operand may be followed immediately by
3231/// either one of these.
3232/// ::= '[', register, ']'
3233/// ::= '[', integer, ']'
3234/// handle it before we iterate so we don't get tripped up by the lack of
3235/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003236bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00003237 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003238 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003239 if (getLexer().is(AsmToken::LBrac)) {
3240 Operands.push_back(
3241 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
3242 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003243 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003244 SMLoc Loc = getLexer().getLoc();
3245 Parser.eatToEndOfStatement();
3246 return Error(Loc, "unexpected token in argument list");
3247 }
3248 if (Parser.getTok().isNot(AsmToken::RBrac)) {
3249 SMLoc Loc = getLexer().getLoc();
3250 Parser.eatToEndOfStatement();
3251 return Error(Loc, "unexpected token, expected ']'");
3252 }
3253 Operands.push_back(
3254 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
3255 Parser.Lex();
3256 }
3257 return false;
3258}
3259
David Blaikie960ea3f2014-06-08 16:18:35 +00003260bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
3261 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003262 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003263 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003264
3265 // We have reached first instruction, module directive are now forbidden.
3266 getTargetStreamer().forbidModuleDirective();
3267
Vladimir Medic74593e62013-07-17 15:00:42 +00003268 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00003269 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00003270 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00003271 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00003272 }
Vladimir Medic64828a12013-07-16 10:07:14 +00003273 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003274 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003275
3276 // Read the remaining operands.
3277 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3278 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003279 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003280 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003281 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003282 return Error(Loc, "unexpected token in argument list");
3283 }
Toma Tabacu13964452014-09-04 13:23:44 +00003284 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003285 return true;
3286 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00003287
Jack Carterd0bd6422013-04-18 00:41:53 +00003288 while (getLexer().is(AsmToken::Comma)) {
3289 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00003290 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003291 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003292 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003293 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003294 return Error(Loc, "unexpected token in argument list");
3295 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003296 // Parse bracket and parenthesis suffixes before we iterate
3297 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00003298 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003299 return true;
3300 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00003301 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003302 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003303 }
3304 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003305 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3306 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003307 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003308 return Error(Loc, "unexpected token in argument list");
3309 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003310 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00003311 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00003312}
3313
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003314bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003315 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003316 SMLoc Loc = getLexer().getLoc();
3317 Parser.eatToEndOfStatement();
3318 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00003319}
3320
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003321bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003322 return Error(Loc, ErrorMsg);
3323}
3324
Jack Carter0b744b32012-10-04 02:29:46 +00003325bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003326 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003327 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00003328
3329 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00003330 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00003331
3332 Parser.Lex(); // Eat "noat".
3333
Jack Carterd0bd6422013-04-18 00:41:53 +00003334 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003335 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003336 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003337 return false;
3338 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003339
3340 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003341 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003342 return false;
3343}
Jack Carterd0bd6422013-04-18 00:41:53 +00003344
Jack Carter0b744b32012-10-04 02:29:46 +00003345bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00003346 // Line can be: ".set at", which sets $at to $1
3347 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00003348 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00003349 Parser.Lex(); // Eat "at".
3350
Jack Carter0b744b32012-10-04 02:29:46 +00003351 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003352 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00003353 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00003354
3355 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003356 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003357 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00003358 }
3359
3360 if (getLexer().isNot(AsmToken::Equal)) {
3361 reportParseError("unexpected token, expected equals sign");
3362 return false;
3363 }
3364 Parser.Lex(); // Eat "=".
3365
3366 if (getLexer().isNot(AsmToken::Dollar)) {
3367 if (getLexer().is(AsmToken::EndOfStatement)) {
3368 reportParseError("no register specified");
3369 return false;
3370 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00003371 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00003372 return false;
3373 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003374 }
3375 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00003376
Toma Tabacu16a74492015-02-13 10:30:57 +00003377 // Find out what "reg" is.
3378 unsigned AtRegNo;
3379 const AsmToken &Reg = Parser.getTok();
3380 if (Reg.is(AsmToken::Identifier)) {
3381 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
3382 } else if (Reg.is(AsmToken::Integer)) {
3383 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00003384 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00003385 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00003386 return false;
3387 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003388
3389 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00003390 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003391 reportParseError("invalid register");
3392 return false;
3393 }
3394 Parser.Lex(); // Eat "reg".
3395
3396 // If this is not the end of the statement, report an error.
3397 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3398 reportParseError("unexpected token, expected end of statement");
3399 return false;
3400 }
3401
3402 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
3403
3404 Parser.Lex(); // Consume the EndOfStatement.
3405 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003406}
3407
3408bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003409 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003410 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003411 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003412 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003413 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003414 return false;
3415 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003416 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00003417 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003418 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003419 return false;
3420}
3421
3422bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003423 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003424 Parser.Lex();
3425 // If this is not the end of the statement, report an error.
3426 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003427 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003428 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003429 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003430 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00003431 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003432 Parser.Lex(); // Consume the EndOfStatement.
3433 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003434}
3435
3436bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003437 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003438 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003439 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003440 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003441 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003442 return false;
3443 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003444 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003445 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003446 return false;
3447}
3448
3449bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003450 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003451 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003452 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003453 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003454 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003455 return false;
3456 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003457 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00003458 reportParseError("`noreorder' must be set before `nomacro'");
3459 return false;
3460 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003461 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003462 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003463 return false;
3464}
Jack Carterd76b2372013-03-21 21:44:16 +00003465
Daniel Sanders44934432014-08-07 12:03:36 +00003466bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003467 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003468 Parser.Lex();
3469
3470 // If this is not the end of the statement, report an error.
3471 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003472 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003473
3474 setFeatureBits(Mips::FeatureMSA, "msa");
3475 getTargetStreamer().emitDirectiveSetMsa();
3476 return false;
3477}
3478
3479bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003480 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003481 Parser.Lex();
3482
3483 // If this is not the end of the statement, report an error.
3484 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003485 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003486
3487 clearFeatureBits(Mips::FeatureMSA, "msa");
3488 getTargetStreamer().emitDirectiveSetNoMsa();
3489 return false;
3490}
3491
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003492bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003493 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003494 Parser.Lex(); // Eat "nodsp".
3495
3496 // If this is not the end of the statement, report an error.
3497 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3498 reportParseError("unexpected token, expected end of statement");
3499 return false;
3500 }
3501
3502 clearFeatureBits(Mips::FeatureDSP, "dsp");
3503 getTargetStreamer().emitDirectiveSetNoDsp();
3504 return false;
3505}
3506
Toma Tabacucc2502d2014-11-04 17:18:07 +00003507bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003508 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003509 Parser.Lex(); // Eat "mips16".
3510
Jack Carter39536722014-01-22 23:08:42 +00003511 // If this is not the end of the statement, report an error.
3512 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003513 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00003514 return false;
3515 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00003516
3517 setFeatureBits(Mips::FeatureMips16, "mips16");
3518 getTargetStreamer().emitDirectiveSetMips16();
3519 Parser.Lex(); // Consume the EndOfStatement.
3520 return false;
3521}
3522
3523bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003524 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003525 Parser.Lex(); // Eat "nomips16".
3526
3527 // If this is not the end of the statement, report an error.
3528 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3529 reportParseError("unexpected token, expected end of statement");
3530 return false;
3531 }
3532
3533 clearFeatureBits(Mips::FeatureMips16, "mips16");
3534 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00003535 Parser.Lex(); // Consume the EndOfStatement.
3536 return false;
3537}
3538
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003539bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003540 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003541 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003542 // Line can be: .set fp=32
3543 // .set fp=xx
3544 // .set fp=64
3545 Parser.Lex(); // Eat fp token
3546 AsmToken Tok = Parser.getTok();
3547 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003548 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003549 return false;
3550 }
3551 Parser.Lex(); // Eat '=' token.
3552 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003553
3554 if (!parseFpABIValue(FpAbiVal, ".set"))
3555 return false;
3556
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003557 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003558 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003559 return false;
3560 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003561 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003562 Parser.Lex(); // Consume the EndOfStatement.
3563 return false;
3564}
3565
Toma Tabacu9db22db2014-09-09 10:15:38 +00003566bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003567 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003568 SMLoc Loc = getLexer().getLoc();
3569
3570 Parser.Lex();
3571 if (getLexer().isNot(AsmToken::EndOfStatement))
3572 return reportParseError("unexpected token, expected end of statement");
3573
3574 // Always keep an element on the options "stack" to prevent the user
3575 // from changing the initial options. This is how we remember them.
3576 if (AssemblerOptions.size() == 2)
3577 return reportParseError(Loc, ".set pop with no .set push");
3578
3579 AssemblerOptions.pop_back();
3580 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
3581
3582 getTargetStreamer().emitDirectiveSetPop();
3583 return false;
3584}
3585
3586bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003587 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003588 Parser.Lex();
3589 if (getLexer().isNot(AsmToken::EndOfStatement))
3590 return reportParseError("unexpected token, expected end of statement");
3591
3592 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00003593 AssemblerOptions.push_back(
3594 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00003595
3596 getTargetStreamer().emitDirectiveSetPush();
3597 return false;
3598}
3599
Jack Carterd76b2372013-03-21 21:44:16 +00003600bool MipsAsmParser::parseSetAssignment() {
3601 StringRef Name;
3602 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00003603 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00003604
3605 if (Parser.parseIdentifier(Name))
3606 reportParseError("expected identifier after .set");
3607
3608 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003609 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00003610 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00003611
Jack Carter3b2c96e2014-01-22 23:31:38 +00003612 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00003613 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00003614
Toma Tabacuf25949b2015-04-07 13:59:39 +00003615 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00003616 Sym->setVariableValue(Value);
3617
3618 return false;
3619}
Jack Carterd0bd6422013-04-18 00:41:53 +00003620
Toma Tabacu26647792014-09-09 12:52:14 +00003621bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003622 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00003623 Parser.Lex();
3624 if (getLexer().isNot(AsmToken::EndOfStatement))
3625 return reportParseError("unexpected token, expected end of statement");
3626
3627 // Reset assembler options to their initial values.
3628 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
3629 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
3630
3631 getTargetStreamer().emitDirectiveSetMips0();
3632 return false;
3633}
3634
Toma Tabacu85618b32014-08-19 14:22:52 +00003635bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003636 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00003637 Parser.Lex();
3638 if (getLexer().isNot(AsmToken::Equal))
3639 return reportParseError("unexpected token, expected equals sign");
3640
3641 Parser.Lex();
3642 StringRef Arch;
3643 if (Parser.parseIdentifier(Arch))
3644 return reportParseError("expected arch identifier");
3645
3646 StringRef ArchFeatureName =
3647 StringSwitch<StringRef>(Arch)
3648 .Case("mips1", "mips1")
3649 .Case("mips2", "mips2")
3650 .Case("mips3", "mips3")
3651 .Case("mips4", "mips4")
3652 .Case("mips5", "mips5")
3653 .Case("mips32", "mips32")
3654 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003655 .Case("mips32r3", "mips32r3")
3656 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003657 .Case("mips32r6", "mips32r6")
3658 .Case("mips64", "mips64")
3659 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003660 .Case("mips64r3", "mips64r3")
3661 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003662 .Case("mips64r6", "mips64r6")
3663 .Case("cnmips", "cnmips")
3664 .Case("r4000", "mips3") // This is an implementation of Mips3.
3665 .Default("");
3666
3667 if (ArchFeatureName.empty())
3668 return reportParseError("unsupported architecture");
3669
3670 selectArch(ArchFeatureName);
3671 getTargetStreamer().emitDirectiveSetArch(Arch);
3672 return false;
3673}
3674
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003675bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003676 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003677 Parser.Lex();
3678 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003679 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003680
Matheus Almeida2852af82014-04-22 10:15:54 +00003681 switch (Feature) {
3682 default:
3683 llvm_unreachable("Unimplemented feature");
3684 case Mips::FeatureDSP:
3685 setFeatureBits(Mips::FeatureDSP, "dsp");
3686 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003687 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003688 case Mips::FeatureMicroMips:
3689 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003690 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003691 case Mips::FeatureMips1:
3692 selectArch("mips1");
3693 getTargetStreamer().emitDirectiveSetMips1();
3694 break;
3695 case Mips::FeatureMips2:
3696 selectArch("mips2");
3697 getTargetStreamer().emitDirectiveSetMips2();
3698 break;
3699 case Mips::FeatureMips3:
3700 selectArch("mips3");
3701 getTargetStreamer().emitDirectiveSetMips3();
3702 break;
3703 case Mips::FeatureMips4:
3704 selectArch("mips4");
3705 getTargetStreamer().emitDirectiveSetMips4();
3706 break;
3707 case Mips::FeatureMips5:
3708 selectArch("mips5");
3709 getTargetStreamer().emitDirectiveSetMips5();
3710 break;
3711 case Mips::FeatureMips32:
3712 selectArch("mips32");
3713 getTargetStreamer().emitDirectiveSetMips32();
3714 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003715 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003716 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003717 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003718 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003719 case Mips::FeatureMips32r3:
3720 selectArch("mips32r3");
3721 getTargetStreamer().emitDirectiveSetMips32R3();
3722 break;
3723 case Mips::FeatureMips32r5:
3724 selectArch("mips32r5");
3725 getTargetStreamer().emitDirectiveSetMips32R5();
3726 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003727 case Mips::FeatureMips32r6:
3728 selectArch("mips32r6");
3729 getTargetStreamer().emitDirectiveSetMips32R6();
3730 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003731 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003732 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00003733 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003734 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003735 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003736 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003737 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003738 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003739 case Mips::FeatureMips64r3:
3740 selectArch("mips64r3");
3741 getTargetStreamer().emitDirectiveSetMips64R3();
3742 break;
3743 case Mips::FeatureMips64r5:
3744 selectArch("mips64r5");
3745 getTargetStreamer().emitDirectiveSetMips64R5();
3746 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003747 case Mips::FeatureMips64r6:
3748 selectArch("mips64r6");
3749 getTargetStreamer().emitDirectiveSetMips64R6();
3750 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003751 }
3752 return false;
3753}
3754
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003755bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003756 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003757 if (getLexer().isNot(AsmToken::Comma)) {
3758 SMLoc Loc = getLexer().getLoc();
3759 Parser.eatToEndOfStatement();
3760 return Error(Loc, ErrorStr);
3761 }
3762
Matheus Almeida2852af82014-04-22 10:15:54 +00003763 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003764 return true;
3765}
3766
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003767bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003768 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00003769 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003770
Toma Tabacudde4c462014-11-06 10:02:45 +00003771 if (inMips16Mode()) {
3772 reportParseError(".cpload is not supported in Mips16 mode");
3773 return false;
3774 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003775
David Blaikie960ea3f2014-06-08 16:18:35 +00003776 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00003777 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003778 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3779 reportParseError("expected register containing function address");
3780 return false;
3781 }
3782
David Blaikie960ea3f2014-06-08 16:18:35 +00003783 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
3784 if (!RegOpnd.isGPRAsmReg()) {
3785 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003786 return false;
3787 }
3788
Toma Tabacudde4c462014-11-06 10:02:45 +00003789 // If this is not the end of the statement, report an error.
3790 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3791 reportParseError("unexpected token, expected end of statement");
3792 return false;
3793 }
3794
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003795 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003796 return false;
3797}
3798
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003799bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003800 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003801 unsigned FuncReg;
3802 unsigned Save;
3803 bool SaveIsReg = true;
3804
Matheus Almeida7e815762014-06-18 13:08:59 +00003805 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003806 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003807 if (ResTy == MatchOperand_NoMatch) {
3808 reportParseError("expected register containing function address");
3809 Parser.eatToEndOfStatement();
3810 return false;
3811 }
3812
3813 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3814 if (!FuncRegOpnd.isGPRAsmReg()) {
3815 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3816 Parser.eatToEndOfStatement();
3817 return false;
3818 }
3819
3820 FuncReg = FuncRegOpnd.getGPR32Reg();
3821 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003822
Toma Tabacu65f10572014-09-16 15:00:52 +00003823 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003824 return true;
3825
Toma Tabacu13964452014-09-04 13:23:44 +00003826 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003827 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003828 const AsmToken &Tok = Parser.getTok();
3829 if (Tok.is(AsmToken::Integer)) {
3830 Save = Tok.getIntVal();
3831 SaveIsReg = false;
3832 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003833 } else {
3834 reportParseError("expected save register or stack offset");
3835 Parser.eatToEndOfStatement();
3836 return false;
3837 }
3838 } else {
3839 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3840 if (!SaveOpnd.isGPRAsmReg()) {
3841 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3842 Parser.eatToEndOfStatement();
3843 return false;
3844 }
3845 Save = SaveOpnd.getGPR32Reg();
3846 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003847
Toma Tabacu65f10572014-09-16 15:00:52 +00003848 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003849 return true;
3850
Toma Tabacu8874eac2015-02-18 13:46:53 +00003851 const MCExpr *Expr;
3852 if (Parser.parseExpression(Expr)) {
3853 reportParseError("expected expression");
3854 return false;
3855 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003856
Toma Tabacu8874eac2015-02-18 13:46:53 +00003857 if (Expr->getKind() != MCExpr::SymbolRef) {
3858 reportParseError("expected symbol");
3859 return false;
3860 }
3861 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
3862
3863 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
3864 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003865 return false;
3866}
3867
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003868bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003869 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003870 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3871 const AsmToken &Tok = Parser.getTok();
3872
3873 if (Tok.getString() == "2008") {
3874 Parser.Lex();
3875 getTargetStreamer().emitDirectiveNaN2008();
3876 return false;
3877 } else if (Tok.getString() == "legacy") {
3878 Parser.Lex();
3879 getTargetStreamer().emitDirectiveNaNLegacy();
3880 return false;
3881 }
3882 }
3883 // If we don't recognize the option passed to the .nan
3884 // directive (e.g. no option or unknown option), emit an error.
3885 reportParseError("invalid option in .nan directive");
3886 return false;
3887}
3888
Jack Carter0b744b32012-10-04 02:29:46 +00003889bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003890 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003891 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003892 const AsmToken &Tok = Parser.getTok();
3893
3894 if (Tok.getString() == "noat") {
3895 return parseSetNoAtDirective();
3896 } else if (Tok.getString() == "at") {
3897 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003898 } else if (Tok.getString() == "arch") {
3899 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003900 } else if (Tok.getString() == "fp") {
3901 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003902 } else if (Tok.getString() == "pop") {
3903 return parseSetPopDirective();
3904 } else if (Tok.getString() == "push") {
3905 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003906 } else if (Tok.getString() == "reorder") {
3907 return parseSetReorderDirective();
3908 } else if (Tok.getString() == "noreorder") {
3909 return parseSetNoReorderDirective();
3910 } else if (Tok.getString() == "macro") {
3911 return parseSetMacroDirective();
3912 } else if (Tok.getString() == "nomacro") {
3913 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003914 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00003915 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003916 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003917 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003918 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003919 getTargetStreamer().emitDirectiveSetNoMicroMips();
3920 Parser.eatToEndOfStatement();
3921 return false;
3922 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003923 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003924 } else if (Tok.getString() == "mips0") {
3925 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003926 } else if (Tok.getString() == "mips1") {
3927 return parseSetFeature(Mips::FeatureMips1);
3928 } else if (Tok.getString() == "mips2") {
3929 return parseSetFeature(Mips::FeatureMips2);
3930 } else if (Tok.getString() == "mips3") {
3931 return parseSetFeature(Mips::FeatureMips3);
3932 } else if (Tok.getString() == "mips4") {
3933 return parseSetFeature(Mips::FeatureMips4);
3934 } else if (Tok.getString() == "mips5") {
3935 return parseSetFeature(Mips::FeatureMips5);
3936 } else if (Tok.getString() == "mips32") {
3937 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003938 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003939 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003940 } else if (Tok.getString() == "mips32r3") {
3941 return parseSetFeature(Mips::FeatureMips32r3);
3942 } else if (Tok.getString() == "mips32r5") {
3943 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003944 } else if (Tok.getString() == "mips32r6") {
3945 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003946 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003947 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003948 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003949 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003950 } else if (Tok.getString() == "mips64r3") {
3951 return parseSetFeature(Mips::FeatureMips64r3);
3952 } else if (Tok.getString() == "mips64r5") {
3953 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003954 } else if (Tok.getString() == "mips64r6") {
3955 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003956 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003957 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003958 } else if (Tok.getString() == "nodsp") {
3959 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003960 } else if (Tok.getString() == "msa") {
3961 return parseSetMsaDirective();
3962 } else if (Tok.getString() == "nomsa") {
3963 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003964 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003965 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003966 parseSetAssignment();
3967 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003968 }
Jack Carter07c818d2013-01-25 01:31:34 +00003969
Jack Carter0b744b32012-10-04 02:29:46 +00003970 return true;
3971}
3972
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003973/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003974/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003975bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003976 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003977 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3978 for (;;) {
3979 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003980 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003981 return true;
3982
3983 getParser().getStreamer().EmitValue(Value, Size);
3984
3985 if (getLexer().is(AsmToken::EndOfStatement))
3986 break;
3987
Jack Carter07c818d2013-01-25 01:31:34 +00003988 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003989 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00003990 Parser.Lex();
3991 }
3992 }
3993
3994 Parser.Lex();
3995 return false;
3996}
3997
Vladimir Medic4c299852013-11-06 11:27:05 +00003998/// parseDirectiveGpWord
3999/// ::= .gpword local_sym
4000bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004001 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004002 const MCExpr *Value;
4003 // EmitGPRel32Value requires an expression, so we are using base class
4004 // method to evaluate the expression.
4005 if (getParser().parseExpression(Value))
4006 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00004007 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00004008
Vladimir Medice10c1122013-11-13 13:18:04 +00004009 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004010 return Error(getLexer().getLoc(),
4011 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00004012 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00004013 return false;
4014}
4015
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004016/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00004017/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004018bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004019 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004020 const MCExpr *Value;
4021 // EmitGPRel64Value requires an expression, so we are using base class
4022 // method to evaluate the expression.
4023 if (getParser().parseExpression(Value))
4024 return true;
4025 getParser().getStreamer().EmitGPRel64Value(Value);
4026
4027 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004028 return Error(getLexer().getLoc(),
4029 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00004030 Parser.Lex(); // Eat EndOfStatement token.
4031 return false;
4032}
4033
Jack Carter0cd3c192014-01-06 23:27:31 +00004034bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004035 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00004036 // Get the option token.
4037 AsmToken Tok = Parser.getTok();
4038 // At the moment only identifiers are supported.
4039 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004040 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00004041 Parser.eatToEndOfStatement();
4042 return false;
4043 }
4044
4045 StringRef Option = Tok.getIdentifier();
4046
4047 if (Option == "pic0") {
4048 getTargetStreamer().emitDirectiveOptionPic0();
4049 Parser.Lex();
4050 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4051 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004052 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004053 Parser.eatToEndOfStatement();
4054 }
4055 return false;
4056 }
4057
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004058 if (Option == "pic2") {
4059 getTargetStreamer().emitDirectiveOptionPic2();
4060 Parser.Lex();
4061 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4062 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004063 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004064 Parser.eatToEndOfStatement();
4065 }
4066 return false;
4067 }
4068
Jack Carter0cd3c192014-01-06 23:27:31 +00004069 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00004070 Warning(Parser.getTok().getLoc(),
4071 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00004072 Parser.eatToEndOfStatement();
4073 return false;
4074}
4075
Toma Tabacu9ca50962015-04-16 09:53:47 +00004076/// parseInsnDirective
4077/// ::= .insn
4078bool MipsAsmParser::parseInsnDirective() {
4079 // If this is not the end of the statement, report an error.
4080 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4081 reportParseError("unexpected token, expected end of statement");
4082 return false;
4083 }
4084
4085 // The actual label marking happens in
4086 // MipsELFStreamer::createPendingLabelRelocs().
4087 getTargetStreamer().emitDirectiveInsn();
4088
4089 getParser().Lex(); // Eat EndOfStatement token.
4090 return false;
4091}
4092
Daniel Sanders7e527422014-07-10 13:38:23 +00004093/// parseDirectiveModule
4094/// ::= .module oddspreg
4095/// ::= .module nooddspreg
4096/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004097bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004098 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004099 MCAsmLexer &Lexer = getLexer();
4100 SMLoc L = Lexer.getLoc();
4101
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004102 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004103 // TODO : get a better message.
4104 reportParseError(".module directive must appear before any code");
4105 return false;
4106 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004107
Toma Tabacuc405c822015-01-23 10:40:19 +00004108 StringRef Option;
4109 if (Parser.parseIdentifier(Option)) {
4110 reportParseError("expected .module option identifier");
4111 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004112 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004113
Toma Tabacuc405c822015-01-23 10:40:19 +00004114 if (Option == "oddspreg") {
4115 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
4116 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4117
4118 // If this is not the end of the statement, report an error.
4119 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4120 reportParseError("unexpected token, expected end of statement");
4121 return false;
4122 }
4123
4124 return false; // parseDirectiveModule has finished successfully.
4125 } else if (Option == "nooddspreg") {
4126 if (!isABI_O32()) {
4127 Error(L, "'.module nooddspreg' requires the O32 ABI");
4128 return false;
4129 }
4130
4131 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
4132 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4133
4134 // If this is not the end of the statement, report an error.
4135 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4136 reportParseError("unexpected token, expected end of statement");
4137 return false;
4138 }
4139
4140 return false; // parseDirectiveModule has finished successfully.
4141 } else if (Option == "fp") {
4142 return parseDirectiveModuleFP();
4143 } else {
4144 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
4145 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004146}
4147
4148/// parseDirectiveModuleFP
4149/// ::= =32
4150/// ::= =xx
4151/// ::= =64
4152bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004153 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004154 MCAsmLexer &Lexer = getLexer();
4155
4156 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004157 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004158 return false;
4159 }
4160 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004161
Daniel Sanders7e527422014-07-10 13:38:23 +00004162 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004163 if (!parseFpABIValue(FpABI, ".module"))
4164 return false;
4165
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004166 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004167 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004168 return false;
4169 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004170
Daniel Sanders7201a3e2014-07-08 10:35:52 +00004171 // Emit appropriate flags.
4172 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00004173 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004174 return false;
4175}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004176
Daniel Sanders7e527422014-07-10 13:38:23 +00004177bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004178 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004179 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004180 MCAsmLexer &Lexer = getLexer();
4181
4182 if (Lexer.is(AsmToken::Identifier)) {
4183 StringRef Value = Parser.getTok().getString();
4184 Parser.Lex();
4185
4186 if (Value != "xx") {
4187 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4188 return false;
4189 }
4190
4191 if (!isABI_O32()) {
4192 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
4193 return false;
4194 }
4195
Daniel Sanders7e527422014-07-10 13:38:23 +00004196 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004197 return true;
4198 }
4199
4200 if (Lexer.is(AsmToken::Integer)) {
4201 unsigned Value = Parser.getTok().getIntVal();
4202 Parser.Lex();
4203
4204 if (Value != 32 && Value != 64) {
4205 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4206 return false;
4207 }
4208
4209 if (Value == 32) {
4210 if (!isABI_O32()) {
4211 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
4212 return false;
4213 }
4214
Daniel Sanders7e527422014-07-10 13:38:23 +00004215 FpABI = MipsABIFlagsSection::FpABIKind::S32;
4216 } else
4217 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004218
Daniel Sanders7e527422014-07-10 13:38:23 +00004219 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004220 }
4221
4222 return false;
4223}
4224
Jack Carter0b744b32012-10-04 02:29:46 +00004225bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004226 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004227 StringRef IDVal = DirectiveID.getString();
4228
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004229 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004230 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00004231 if (IDVal == ".dword") {
4232 parseDataDirective(8, DirectiveID.getLoc());
4233 return false;
4234 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004235 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004236 StringRef SymbolName;
4237
4238 if (Parser.parseIdentifier(SymbolName)) {
4239 reportParseError("expected identifier after .ent");
4240 return false;
4241 }
4242
4243 // There's an undocumented extension that allows an integer to
4244 // follow the name of the procedure which AFAICS is ignored by GAS.
4245 // Example: .ent foo,2
4246 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4247 if (getLexer().isNot(AsmToken::Comma)) {
4248 // Even though we accept this undocumented extension for compatibility
4249 // reasons, the additional integer argument does not actually change
4250 // the behaviour of the '.ent' directive, so we would like to discourage
4251 // its use. We do this by not referring to the extended version in
4252 // error messages which are not directly related to its use.
4253 reportParseError("unexpected token, expected end of statement");
4254 return false;
4255 }
4256 Parser.Lex(); // Eat the comma.
4257 const MCExpr *DummyNumber;
4258 int64_t DummyNumberVal;
4259 // If the user was explicitly trying to use the extended version,
4260 // we still give helpful extension-related error messages.
4261 if (Parser.parseExpression(DummyNumber)) {
4262 reportParseError("expected number after comma");
4263 return false;
4264 }
4265 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
4266 reportParseError("expected an absolute expression after comma");
4267 return false;
4268 }
4269 }
4270
4271 // If this is not the end of the statement, report an error.
4272 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4273 reportParseError("unexpected token, expected end of statement");
4274 return false;
4275 }
4276
4277 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
4278
4279 getTargetStreamer().emitDirectiveEnt(*Sym);
4280 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00004281 return false;
4282 }
4283
Jack Carter07c818d2013-01-25 01:31:34 +00004284 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004285 StringRef SymbolName;
4286
4287 if (Parser.parseIdentifier(SymbolName)) {
4288 reportParseError("expected identifier after .end");
4289 return false;
4290 }
4291
4292 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4293 reportParseError("unexpected token, expected end of statement");
4294 return false;
4295 }
4296
4297 if (CurrentFn == nullptr) {
4298 reportParseError(".end used without .ent");
4299 return false;
4300 }
4301
4302 if ((SymbolName != CurrentFn->getName())) {
4303 reportParseError(".end symbol does not match .ent symbol");
4304 return false;
4305 }
4306
4307 getTargetStreamer().emitDirectiveEnd(SymbolName);
4308 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00004309 return false;
4310 }
4311
Jack Carter07c818d2013-01-25 01:31:34 +00004312 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004313 // .frame $stack_reg, frame_size_in_bytes, $return_reg
4314 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004315 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004316 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4317 reportParseError("expected stack register");
4318 return false;
4319 }
4320
4321 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4322 if (!StackRegOpnd.isGPRAsmReg()) {
4323 reportParseError(StackRegOpnd.getStartLoc(),
4324 "expected general purpose register");
4325 return false;
4326 }
4327 unsigned StackReg = StackRegOpnd.getGPR32Reg();
4328
4329 if (Parser.getTok().is(AsmToken::Comma))
4330 Parser.Lex();
4331 else {
4332 reportParseError("unexpected token, expected comma");
4333 return false;
4334 }
4335
4336 // Parse the frame size.
4337 const MCExpr *FrameSize;
4338 int64_t FrameSizeVal;
4339
4340 if (Parser.parseExpression(FrameSize)) {
4341 reportParseError("expected frame size value");
4342 return false;
4343 }
4344
4345 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
4346 reportParseError("frame size not an absolute expression");
4347 return false;
4348 }
4349
4350 if (Parser.getTok().is(AsmToken::Comma))
4351 Parser.Lex();
4352 else {
4353 reportParseError("unexpected token, expected comma");
4354 return false;
4355 }
4356
4357 // Parse the return register.
4358 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00004359 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004360 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4361 reportParseError("expected return register");
4362 return false;
4363 }
4364
4365 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4366 if (!ReturnRegOpnd.isGPRAsmReg()) {
4367 reportParseError(ReturnRegOpnd.getStartLoc(),
4368 "expected general purpose register");
4369 return false;
4370 }
4371
4372 // If this is not the end of the statement, report an error.
4373 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4374 reportParseError("unexpected token, expected end of statement");
4375 return false;
4376 }
4377
4378 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
4379 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00004380 return false;
4381 }
4382
Jack Carter07c818d2013-01-25 01:31:34 +00004383 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00004384 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00004385 }
4386
Daniel Sandersd97a6342014-08-13 10:07:34 +00004387 if (IDVal == ".mask" || IDVal == ".fmask") {
4388 // .mask bitmask, frame_offset
4389 // bitmask: One bit for each register used.
4390 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
4391 // first register is expected to be saved.
4392 // Examples:
4393 // .mask 0x80000000, -4
4394 // .fmask 0x80000000, -4
4395 //
Jack Carterbe332172012-09-07 00:48:02 +00004396
Daniel Sandersd97a6342014-08-13 10:07:34 +00004397 // Parse the bitmask
4398 const MCExpr *BitMask;
4399 int64_t BitMaskVal;
4400
4401 if (Parser.parseExpression(BitMask)) {
4402 reportParseError("expected bitmask value");
4403 return false;
4404 }
4405
4406 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
4407 reportParseError("bitmask not an absolute expression");
4408 return false;
4409 }
4410
4411 if (Parser.getTok().is(AsmToken::Comma))
4412 Parser.Lex();
4413 else {
4414 reportParseError("unexpected token, expected comma");
4415 return false;
4416 }
4417
4418 // Parse the frame_offset
4419 const MCExpr *FrameOffset;
4420 int64_t FrameOffsetVal;
4421
4422 if (Parser.parseExpression(FrameOffset)) {
4423 reportParseError("expected frame offset value");
4424 return false;
4425 }
4426
4427 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
4428 reportParseError("frame offset not an absolute expression");
4429 return false;
4430 }
4431
4432 // If this is not the end of the statement, report an error.
4433 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4434 reportParseError("unexpected token, expected end of statement");
4435 return false;
4436 }
4437
4438 if (IDVal == ".mask")
4439 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
4440 else
4441 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00004442 return false;
4443 }
4444
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004445 if (IDVal == ".nan")
4446 return parseDirectiveNaN();
4447
Jack Carter07c818d2013-01-25 01:31:34 +00004448 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004449 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00004450 return false;
4451 }
4452
Rafael Espindolab59fb732014-03-28 18:50:26 +00004453 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004454 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004455 return false;
4456 }
4457
Jack Carter07c818d2013-01-25 01:31:34 +00004458 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004459 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00004460 return false;
4461 }
4462
Jack Carter0cd3c192014-01-06 23:27:31 +00004463 if (IDVal == ".option")
4464 return parseDirectiveOption();
4465
4466 if (IDVal == ".abicalls") {
4467 getTargetStreamer().emitDirectiveAbiCalls();
4468 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004469 Error(Parser.getTok().getLoc(),
4470 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004471 // Clear line
4472 Parser.eatToEndOfStatement();
4473 }
4474 return false;
4475 }
4476
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004477 if (IDVal == ".cpsetup")
4478 return parseDirectiveCPSetup();
4479
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004480 if (IDVal == ".module")
4481 return parseDirectiveModule();
4482
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004483 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
4484 return parseInternalDirectiveReallowModule();
4485
Toma Tabacu9ca50962015-04-16 09:53:47 +00004486 if (IDVal == ".insn")
4487 return parseInsnDirective();
4488
Rafael Espindola870c4e92012-01-11 03:56:41 +00004489 return true;
4490}
4491
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004492bool MipsAsmParser::parseInternalDirectiveReallowModule() {
4493 // If this is not the end of the statement, report an error.
4494 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4495 reportParseError("unexpected token, expected end of statement");
4496 return false;
4497 }
4498
4499 getTargetStreamer().reallowModuleDirective();
4500
4501 getParser().Lex(); // Eat EndOfStatement token.
4502 return false;
4503}
4504
Rafael Espindola870c4e92012-01-11 03:56:41 +00004505extern "C" void LLVMInitializeMipsAsmParser() {
4506 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
4507 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
4508 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
4509 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
4510}
Jack Carterb4dbc172012-09-05 23:34:03 +00004511
4512#define GET_REGISTER_MATCHER
4513#define GET_MATCHER_IMPLEMENTATION
4514#include "MipsGenAsmMatcher.inc"