blob: feca3743b9063df4871934ca9ef20f039ad3f63f [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 Kupersteindb0712f2015-05-26 10:47:10 +000081 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +000082
Jack Carter0b744b32012-10-04 02:29:46 +000083private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000084 unsigned ATReg;
85 bool Reorder;
86 bool Macro;
Toma Tabacu9db22db2014-09-09 10:15:38 +000087 uint64_t Features;
Jack Carter0b744b32012-10-04 02:29:46 +000088};
89}
90
Michael Kupersteindb0712f2015-05-26 10:47:10 +000091const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
92 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
93 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
94 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
95 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
96 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
97 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
98 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
99 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
100};
101
Jack Carter0b744b32012-10-04 02:29:46 +0000102namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +0000103class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000104 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000105 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000106 return static_cast<MipsTargetStreamer &>(TS);
107 }
108
Jack Carterb4dbc172012-09-05 23:34:03 +0000109 MCSubtargetInfo &STI;
Eric Christophera5762812015-01-26 17:33:46 +0000110 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000111 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000112 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
113 // nullptr, which indicates that no function is currently
114 // selected. This usually happens after an '.end func'
115 // directive.
Jack Carter0b744b32012-10-04 02:29:46 +0000116
Daniel Sandersef638fe2014-10-03 15:37:37 +0000117 // Print a warning along with its fix-it message at the given range.
118 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
119 SMRange Range, bool ShowColors = true);
120
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000121#define GET_ASSEMBLER_HEADER
122#include "MipsGenAsmMatcher.inc"
123
Matheus Almeida595fcab2014-06-11 15:05:56 +0000124 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
125
Chad Rosier49963552012-10-13 00:26:04 +0000126 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000127 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000128 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000129 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000130
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000131 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000132 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000133
Toma Tabacu13964452014-09-04 13:23:44 +0000134 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000135
Toma Tabacu13964452014-09-04 13:23:44 +0000136 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000137
David Blaikie960ea3f2014-06-08 16:18:35 +0000138 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
139 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000140
Craig Topper56c590a2014-04-29 07:58:02 +0000141 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000142
David Blaikie960ea3f2014-06-08 16:18:35 +0000143 MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000144
145 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000146 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000147 StringRef Identifier, SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000148
Jack Carter873c7242013-01-12 01:03:14 +0000149 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000150 matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
Jack Carter873c7242013-01-12 01:03:14 +0000151
Toma Tabacu13964452014-09-04 13:23:44 +0000152 MipsAsmParser::OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000153
Toma Tabacu13964452014-09-04 13:23:44 +0000154 MipsAsmParser::OperandMatchResultTy parseImm(OperandVector &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000155
Toma Tabacu13964452014-09-04 13:23:44 +0000156 MipsAsmParser::OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000157
David Blaikie960ea3f2014-06-08 16:18:35 +0000158 MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000159
Toma Tabacu13964452014-09-04 13:23:44 +0000160 MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000161
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000162 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000163 parseRegisterPair (OperandVector &Operands);
164
165 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +0000166 parseMovePRegPair(OperandVector &Operands);
167
168 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000169 parseRegisterList (OperandVector &Operands);
170
David Blaikie960ea3f2014-06-08 16:18:35 +0000171 bool searchSymbolAlias(OperandVector &Operands);
172
Toma Tabacu13964452014-09-04 13:23:44 +0000173 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000174
Jack Carter30a59822012-10-04 04:03:53 +0000175 bool needsExpansion(MCInst &Inst);
176
Matheus Almeida3813d572014-06-19 14:39:14 +0000177 // Expands assembly pseudo instructions.
178 // Returns false on success, true otherwise.
179 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000180 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000181
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000182 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
183 SmallVectorImpl<MCInst> &Instructions);
184
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000185 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
186 bool Is32BitImm, SMLoc IDLoc,
187 SmallVectorImpl<MCInst> &Instructions);
188
Toma Tabacu00e98672015-05-01 12:19:27 +0000189 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000190 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000191
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000192 bool expandLoadAddressImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000193 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000194
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000195 bool expandLoadAddressReg(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000196 SmallVectorImpl<MCInst> &Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000197 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
198 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000199
Toma Tabacub5592ee2015-05-14 10:02:58 +0000200 void expandLoadAddressSym(const MCOperand &DstRegOp, const MCOperand &SymOp,
Toma Tabacuec1de822015-05-14 10:53:40 +0000201 bool Is32BitSym, SMLoc IDLoc,
202 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +0000203
Jack Carter9e65aa32013-03-22 00:05:30 +0000204 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000205 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
206 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000207
208 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
209 SmallVectorImpl<MCInst> &Instructions);
210
Toma Tabacu234482a2015-03-16 12:03:39 +0000211 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
212 SmallVectorImpl<MCInst> &Instructions);
213
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000214 void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
215 SmallVectorImpl<MCInst> &Instructions);
216
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000217 bool reportParseError(Twine ErrorMsg);
218 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000219
Jack Carterb5cf5902013-04-17 00:18:04 +0000220 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000221 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000222
Vladimir Medic4c299852013-11-06 11:27:05 +0000223 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000224
225 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000226 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000227 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000228 bool parseSetFeature(uint64_t Feature);
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000229 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000230 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000231 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000232 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000233 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000234 bool parseInsnDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000235
236 bool parseSetAtDirective();
237 bool parseSetNoAtDirective();
238 bool parseSetMacroDirective();
239 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000240 bool parseSetMsaDirective();
241 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000242 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000243 bool parseSetReorderDirective();
244 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000245 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000246 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000247 bool parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000248 bool parseSetPopDirective();
249 bool parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000250
Jack Carterd76b2372013-03-21 21:44:16 +0000251 bool parseSetAssignment();
252
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000253 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000254 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000255 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000256 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000257 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000258 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
259 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000260
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000261 bool parseInternalDirectiveReallowModule();
262
Jack Carterdc1e35d2012-09-06 20:00:02 +0000263 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000264
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000265 bool eatComma(StringRef ErrorStr);
266
Jack Carter1ac53222013-02-20 23:11:17 +0000267 int matchCPURegisterName(StringRef Symbol);
268
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000269 int matchHWRegsRegisterName(StringRef Symbol);
270
Jack Carter873c7242013-01-12 01:03:14 +0000271 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000272
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000273 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000274
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000275 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000276
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000277 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000278
Jack Carter5dc8ac92013-09-25 23:50:44 +0000279 int matchMSA128RegisterName(StringRef Name);
280
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000281 int matchMSA128CtrlRegisterName(StringRef Name);
282
Jack Carterd0bd6422013-04-18 00:41:53 +0000283 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000284
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000285 unsigned getGPR(int RegNo);
286
Toma Tabacu89a712b2015-04-15 10:48:56 +0000287 /// Returns the internal register number for the current AT. Also checks if
288 /// the current AT is unavailable (set to $0) and gives an error if it is.
289 /// This should be used in pseudo-instruction expansions which need AT.
290 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000291
292 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000293 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000294
295 // Helper function that checks if the value of a vector index is within the
296 // boundaries of accepted values for each RegisterKind
297 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
298 bool validateMSAIndex(int Val, int RegKind);
299
Daniel Sandersf0df2212014-08-04 12:20:00 +0000300 // Selects a new architecture by updating the FeatureBits with the necessary
301 // info including implied dependencies.
302 // Internally, it clears all the feature bits related to *any* architecture
303 // and selects the new one using the ToggleFeature functionality of the
304 // MCSubtargetInfo object that handles implied dependencies. The reason we
305 // clear all the arch related bits manually is because ToggleFeature only
306 // clears the features that imply the feature being cleared and not the
307 // features implied by the feature being cleared. This is easier to see
308 // with an example:
309 // --------------------------------------------------
310 // | Feature | Implies |
311 // | -------------------------------------------------|
312 // | FeatureMips1 | None |
313 // | FeatureMips2 | FeatureMips1 |
314 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
315 // | FeatureMips4 | FeatureMips3 |
316 // | ... | |
317 // --------------------------------------------------
318 //
319 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
320 // FeatureMipsGP64 | FeatureMips1)
321 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
322 void selectArch(StringRef ArchFeature) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000323 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000324 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
325 STI.setFeatureBits(FeatureBits);
326 setAvailableFeatures(
327 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000328 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000329 }
330
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000331 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000332 if (!(STI.getFeatureBits()[Feature])) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000333 setAvailableFeatures(
334 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000335 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000336 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000337 }
338
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000339 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000340 if (STI.getFeatureBits()[Feature]) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000341 setAvailableFeatures(
342 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000343 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000344 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000345 }
346
Rafael Espindola870c4e92012-01-11 03:56:41 +0000347public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000348 enum MipsMatchResultTy {
349 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
350#define GET_OPERAND_DIAGNOSTIC_TYPES
351#include "MipsGenAsmMatcher.inc"
352#undef GET_OPERAND_DIAGNOSTIC_TYPES
353
354 };
355
Joey Gouly0e76fa72013-09-12 10:28:05 +0000356 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000357 const MCInstrInfo &MII, const MCTargetOptions &Options)
Eric Christophera5762812015-01-26 17:33:46 +0000358 : MCTargetAsmParser(), STI(sti),
359 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
360 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000361 MCAsmParserExtension::Initialize(parser);
362
Toma Tabacu11e14a92015-04-21 11:50:52 +0000363 parser.addAliasForDirective(".asciiz", ".asciz");
364
Jack Carterb4dbc172012-09-05 23:34:03 +0000365 // Initialize the set of available features.
366 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000367
368 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000369 AssemblerOptions.push_back(
370 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000371
372 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000373 AssemblerOptions.push_back(
374 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000375
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000376 getTargetStreamer().updateABIInfo(*this);
377
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000378 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000379 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000380
381 CurrentFn = nullptr;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000382 }
383
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000384 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
385 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
386
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000387 bool isGP64bit() const { return STI.getFeatureBits()[Mips::FeatureGP64Bit]; }
388 bool isFP64bit() const { return STI.getFeatureBits()[Mips::FeatureFP64Bit]; }
Eric Christophera5762812015-01-26 17:33:46 +0000389 const MipsABIInfo &getABI() const { return ABI; }
390 bool isABI_N32() const { return ABI.IsN32(); }
391 bool isABI_N64() const { return ABI.IsN64(); }
392 bool isABI_O32() const { return ABI.IsO32(); }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000393 bool isABI_FPXX() const { return STI.getFeatureBits()[Mips::FeatureFPXX]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000394
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000395 bool useOddSPReg() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000396 return !(STI.getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000397 }
398
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000399 bool inMicroMipsMode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000400 return STI.getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000401 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000402 bool hasMips1() const { return STI.getFeatureBits()[Mips::FeatureMips1]; }
403 bool hasMips2() const { return STI.getFeatureBits()[Mips::FeatureMips2]; }
404 bool hasMips3() const { return STI.getFeatureBits()[Mips::FeatureMips3]; }
405 bool hasMips4() const { return STI.getFeatureBits()[Mips::FeatureMips4]; }
406 bool hasMips5() const { return STI.getFeatureBits()[Mips::FeatureMips5]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000407 bool hasMips32() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000408 return STI.getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000409 }
410 bool hasMips64() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000411 return STI.getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000412 }
413 bool hasMips32r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000414 return STI.getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000415 }
416 bool hasMips64r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000417 return STI.getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000418 }
Daniel Sanders17793142015-02-18 16:24:50 +0000419 bool hasMips32r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000420 return (STI.getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000421 }
422 bool hasMips64r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000423 return (STI.getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000424 }
425 bool hasMips32r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000426 return (STI.getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000427 }
428 bool hasMips64r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000429 return (STI.getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000430 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000431 bool hasMips32r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000432 return STI.getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000433 }
434 bool hasMips64r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000435 return STI.getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000436 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000437
438 bool hasDSP() const { return STI.getFeatureBits()[Mips::FeatureDSP]; }
439 bool hasDSPR2() const { return STI.getFeatureBits()[Mips::FeatureDSPR2]; }
440 bool hasMSA() const { return STI.getFeatureBits()[Mips::FeatureMSA]; }
Kai Nackee0245392015-01-27 19:11:28 +0000441 bool hasCnMips() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000442 return (STI.getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000443 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000444
445 bool inMips16Mode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000446 return STI.getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000447 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000448
Eric Christophere8ae3e32015-05-07 23:10:21 +0000449 bool useSoftFloat() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000450 return STI.getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000451 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000452
Toma Tabacud9d344b2015-04-27 14:05:04 +0000453 /// Warn if RegIndex is the same as the current AT.
454 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000455
456 void warnIfNoMacro(SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000457};
458}
459
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000460namespace {
461
462/// MipsOperand - Instances of this class represent a parsed Mips machine
463/// instruction.
464class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000465public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000466 /// Broad categories of register classes
467 /// The exact class is finalized by the render method.
468 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000469 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000470 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000471 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000472 RegKind_FCC = 4, /// FCC
473 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
474 RegKind_MSACtrl = 16, /// MSA control registers
475 RegKind_COP2 = 32, /// COP2
476 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
477 /// context).
478 RegKind_CCR = 128, /// CCR
479 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000480 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000481
482 /// Potentially any (e.g. $1)
483 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
484 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000485 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000486 };
487
488private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000489 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000490 k_Immediate, /// An immediate (possibly involving symbol references)
491 k_Memory, /// Base + Offset Memory Address
492 k_PhysRegister, /// A physical register from the Mips namespace
493 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000494 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000495 k_RegList, /// A physical register list
496 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000497 } Kind;
498
David Blaikie960ea3f2014-06-08 16:18:35 +0000499public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000500 MipsOperand(KindTy K, MipsAsmParser &Parser)
501 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
502
David Blaikie960ea3f2014-06-08 16:18:35 +0000503private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000504 /// For diagnostics, and checking the assembler temporary
505 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000506
Eric Christopher8996c5d2013-03-15 00:42:55 +0000507 struct Token {
508 const char *Data;
509 unsigned Length;
510 };
511
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000512 struct PhysRegOp {
513 unsigned Num; /// Register Number
514 };
515
516 struct RegIdxOp {
517 unsigned Index; /// Index into the register class
518 RegKind Kind; /// Bitfield of the kinds it could possibly be
519 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000520 };
521
522 struct ImmOp {
523 const MCExpr *Val;
524 };
525
526 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000527 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000528 const MCExpr *Off;
529 };
530
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000531 struct RegListOp {
532 SmallVector<unsigned, 10> *List;
533 };
534
Jack Carterb4dbc172012-09-05 23:34:03 +0000535 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000536 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000537 struct PhysRegOp PhysReg;
538 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000539 struct ImmOp Imm;
540 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000541 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000542 };
543
544 SMLoc StartLoc, EndLoc;
545
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000546 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000547 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
548 const MCRegisterInfo *RegInfo,
549 SMLoc S, SMLoc E,
550 MipsAsmParser &Parser) {
551 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000552 Op->RegIdx.Index = Index;
553 Op->RegIdx.RegInfo = RegInfo;
554 Op->RegIdx.Kind = RegKind;
555 Op->StartLoc = S;
556 Op->EndLoc = E;
557 return Op;
558 }
559
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000560public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000561 /// Coerce the register to GPR32 and return the real register for the current
562 /// target.
563 unsigned getGPR32Reg() const {
564 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000565 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000566 unsigned ClassID = Mips::GPR32RegClassID;
567 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000568 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000569
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000570 /// Coerce the register to GPR32 and return the real register for the current
571 /// target.
572 unsigned getGPRMM16Reg() const {
573 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
574 unsigned ClassID = Mips::GPR32RegClassID;
575 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
576 }
577
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000578 /// Coerce the register to GPR64 and return the real register for the current
579 /// target.
580 unsigned getGPR64Reg() const {
581 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
582 unsigned ClassID = Mips::GPR64RegClassID;
583 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000584 }
585
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000586private:
587 /// Coerce the register to AFGR64 and return the real register for the current
588 /// target.
589 unsigned getAFGR64Reg() const {
590 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
591 if (RegIdx.Index % 2 != 0)
592 AsmParser.Warning(StartLoc, "Float register should be even.");
593 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
594 .getRegister(RegIdx.Index / 2);
595 }
596
597 /// Coerce the register to FGR64 and return the real register for the current
598 /// target.
599 unsigned getFGR64Reg() const {
600 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
601 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
602 .getRegister(RegIdx.Index);
603 }
604
605 /// Coerce the register to FGR32 and return the real register for the current
606 /// target.
607 unsigned getFGR32Reg() const {
608 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
609 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
610 .getRegister(RegIdx.Index);
611 }
612
613 /// Coerce the register to FGRH32 and return the real register for the current
614 /// target.
615 unsigned getFGRH32Reg() const {
616 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
617 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
618 .getRegister(RegIdx.Index);
619 }
620
621 /// Coerce the register to FCC and return the real register for the current
622 /// target.
623 unsigned getFCCReg() const {
624 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
625 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
626 .getRegister(RegIdx.Index);
627 }
628
629 /// Coerce the register to MSA128 and return the real register for the current
630 /// target.
631 unsigned getMSA128Reg() const {
632 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
633 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
634 // identical
635 unsigned ClassID = Mips::MSA128BRegClassID;
636 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
637 }
638
639 /// Coerce the register to MSACtrl and return the real register for the
640 /// current target.
641 unsigned getMSACtrlReg() const {
642 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
643 unsigned ClassID = Mips::MSACtrlRegClassID;
644 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
645 }
646
647 /// Coerce the register to COP2 and return the real register for the
648 /// current target.
649 unsigned getCOP2Reg() const {
650 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
651 unsigned ClassID = Mips::COP2RegClassID;
652 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
653 }
654
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000655 /// Coerce the register to COP3 and return the real register for the
656 /// current target.
657 unsigned getCOP3Reg() const {
658 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
659 unsigned ClassID = Mips::COP3RegClassID;
660 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
661 }
662
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000663 /// Coerce the register to ACC64DSP and return the real register for the
664 /// current target.
665 unsigned getACC64DSPReg() const {
666 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
667 unsigned ClassID = Mips::ACC64DSPRegClassID;
668 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
669 }
670
671 /// Coerce the register to HI32DSP and return the real register for the
672 /// current target.
673 unsigned getHI32DSPReg() const {
674 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
675 unsigned ClassID = Mips::HI32DSPRegClassID;
676 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
677 }
678
679 /// Coerce the register to LO32DSP and return the real register for the
680 /// current target.
681 unsigned getLO32DSPReg() const {
682 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
683 unsigned ClassID = Mips::LO32DSPRegClassID;
684 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
685 }
686
687 /// Coerce the register to CCR and return the real register for the
688 /// current target.
689 unsigned getCCRReg() const {
690 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
691 unsigned ClassID = Mips::CCRRegClassID;
692 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
693 }
694
695 /// Coerce the register to HWRegs and return the real register for the
696 /// current target.
697 unsigned getHWRegsReg() const {
698 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
699 unsigned ClassID = Mips::HWRegsRegClassID;
700 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
701 }
702
703public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000704 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000705 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000706 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000707 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000708 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000709 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000710 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000711 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000712 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000713
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000714 void addRegOperands(MCInst &Inst, unsigned N) const {
715 llvm_unreachable("Use a custom parser instead");
716 }
717
Daniel Sanders21bce302014-04-01 12:35:23 +0000718 /// Render the operand to an MCInst as a GPR32
719 /// Asserts if the wrong number of operands are requested, or the operand
720 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000721 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
722 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000723 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000724 }
725
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000726 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
727 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000728 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000729 }
730
Jozef Kolek1904fa22014-11-24 14:25:53 +0000731 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
732 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000733 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000734 }
735
Zoran Jovanovic41688672015-02-10 16:36:20 +0000736 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
737 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000738 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000739 }
740
Daniel Sanders21bce302014-04-01 12:35:23 +0000741 /// Render the operand to an MCInst as a GPR64
742 /// Asserts if the wrong number of operands are requested, or the operand
743 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000744 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
745 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000746 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000747 }
748
749 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
750 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000751 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000752 }
753
754 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
755 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000756 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000757 }
758
759 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
760 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000761 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000762 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000763 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000764 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
765 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000766 }
767
768 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
769 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000770 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000771 }
772
773 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
774 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000775 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000776 }
777
778 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
779 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000780 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000781 }
782
783 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
784 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000785 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000786 }
787
788 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
789 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000790 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000791 }
792
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000793 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
794 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000795 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000796 }
797
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000798 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
799 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000800 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000801 }
802
803 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
804 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000805 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000806 }
807
808 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
809 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000810 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000811 }
812
813 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
814 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000815 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000816 }
817
818 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
819 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000820 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000821 }
822
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000823 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000824 assert(N == 1 && "Invalid number of operands!");
825 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000826 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000827 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000828
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000829 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000830 assert(N == 2 && "Invalid number of operands!");
831
Jim Grosbache9119e42015-05-13 18:37:00 +0000832 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000833
834 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000835 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000836 }
837
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000838 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
839 assert(N == 2 && "Invalid number of operands!");
840
Jim Grosbache9119e42015-05-13 18:37:00 +0000841 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000842
843 const MCExpr *Expr = getMemOff();
844 addExpr(Inst, Expr);
845 }
846
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000847 void addRegListOperands(MCInst &Inst, unsigned N) const {
848 assert(N == 1 && "Invalid number of operands!");
849
850 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000851 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000852 }
853
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000854 void addRegPairOperands(MCInst &Inst, unsigned N) const {
855 assert(N == 2 && "Invalid number of operands!");
856 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +0000857 Inst.addOperand(MCOperand::createReg(RegNo++));
858 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000859 }
860
Zoran Jovanovic41688672015-02-10 16:36:20 +0000861 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
862 assert(N == 2 && "Invalid number of operands!");
863 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000864 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000865 }
866
Craig Topper56c590a2014-04-29 07:58:02 +0000867 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000868 // As a special case until we sort out the definition of div/divu, pretend
869 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
870 if (isGPRAsmReg() && RegIdx.Index == 0)
871 return true;
872
873 return Kind == k_PhysRegister;
874 }
875 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000876 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000877 bool isConstantImm() const {
878 return isImm() && dyn_cast<MCConstantExpr>(getImm());
879 }
Craig Topper56c590a2014-04-29 07:58:02 +0000880 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000881 // Note: It's not possible to pretend that other operand kinds are tokens.
882 // The matcher emitter checks tokens first.
883 return Kind == k_Token;
884 }
Craig Topper56c590a2014-04-29 07:58:02 +0000885 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000886 bool isConstantMemOff() const {
887 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
888 }
889 template <unsigned Bits> bool isMemWithSimmOffset() const {
890 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
891 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000892 bool isMemWithGRPMM16Base() const {
893 return isMem() && getMemBase()->isMM16AsmReg();
894 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000895 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
896 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
897 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
898 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000899 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
900 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
901 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
902 && (getMemBase()->getGPR32Reg() == Mips::SP);
903 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000904 bool isRegList16() const {
905 if (!isRegList())
906 return false;
907
908 int Size = RegList.List->size();
909 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
910 RegList.List->back() != Mips::RA)
911 return false;
912
913 int PrevReg = *RegList.List->begin();
914 for (int i = 1; i < Size - 1; i++) {
915 int Reg = (*(RegList.List))[i];
916 if ( Reg != PrevReg + 1)
917 return false;
918 PrevReg = Reg;
919 }
920
921 return true;
922 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000923 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000924 bool isLSAImm() const {
925 if (!isConstantImm())
926 return false;
927 int64_t Val = getConstantImm();
928 return 1 <= Val && Val <= 4;
929 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000930 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +0000931 bool isMovePRegPair() const {
932 if (Kind != k_RegList || RegList.List->size() != 2)
933 return false;
934
935 unsigned R0 = RegList.List->front();
936 unsigned R1 = RegList.List->back();
937
938 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
939 (R0 == Mips::A1 && R1 == Mips::A3) ||
940 (R0 == Mips::A2 && R1 == Mips::A3) ||
941 (R0 == Mips::A0 && R1 == Mips::S5) ||
942 (R0 == Mips::A0 && R1 == Mips::S6) ||
943 (R0 == Mips::A0 && R1 == Mips::A1) ||
944 (R0 == Mips::A0 && R1 == Mips::A2) ||
945 (R0 == Mips::A0 && R1 == Mips::A3))
946 return true;
947
948 return false;
949 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000950
951 StringRef getToken() const {
952 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000953 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000954 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000955 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000956
Craig Topper56c590a2014-04-29 07:58:02 +0000957 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000958 // As a special case until we sort out the definition of div/divu, pretend
959 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
960 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
961 RegIdx.Kind & RegKind_GPR)
962 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000963
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000964 assert(Kind == k_PhysRegister && "Invalid access!");
965 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000966 }
967
Jack Carterb4dbc172012-09-05 23:34:03 +0000968 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000969 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000970 return Imm.Val;
971 }
972
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000973 int64_t getConstantImm() const {
974 const MCExpr *Val = getImm();
975 return static_cast<const MCConstantExpr *>(Val)->getValue();
976 }
977
978 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000979 assert((Kind == k_Memory) && "Invalid access!");
980 return Mem.Base;
981 }
982
983 const MCExpr *getMemOff() const {
984 assert((Kind == k_Memory) && "Invalid access!");
985 return Mem.Off;
986 }
987
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000988 int64_t getConstantMemOff() const {
989 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
990 }
991
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000992 const SmallVectorImpl<unsigned> &getRegList() const {
993 assert((Kind == k_RegList) && "Invalid access!");
994 return *(RegList.List);
995 }
996
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000997 unsigned getRegPair() const {
998 assert((Kind == k_RegPair) && "Invalid access!");
999 return RegIdx.Index;
1000 }
1001
David Blaikie960ea3f2014-06-08 16:18:35 +00001002 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1003 MipsAsmParser &Parser) {
1004 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001005 Op->Tok.Data = Str.data();
1006 Op->Tok.Length = Str.size();
1007 Op->StartLoc = S;
1008 Op->EndLoc = S;
1009 return Op;
1010 }
1011
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001012 /// Create a numeric register (e.g. $1). The exact register remains
1013 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001014 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001015 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001016 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001017 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001018 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001019 }
1020
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001021 /// Create a register that is definitely a GPR.
1022 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001023 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001024 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001025 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001026 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001027 }
1028
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001029 /// Create a register that is definitely a FGR.
1030 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001031 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001032 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001033 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001034 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1035 }
1036
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001037 /// Create a register that is definitely a HWReg.
1038 /// This is typically only used for named registers such as $hwr_cpunum.
1039 static std::unique_ptr<MipsOperand>
1040 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1041 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1042 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1043 }
1044
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001045 /// Create a register that is definitely an FCC.
1046 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001047 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001048 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001049 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001050 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1051 }
1052
1053 /// Create a register that is definitely an ACC.
1054 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001055 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001056 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001057 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001058 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1059 }
1060
1061 /// Create a register that is definitely an MSA128.
1062 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001063 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001064 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001065 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001066 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1067 }
1068
1069 /// Create a register that is definitely an MSACtrl.
1070 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001071 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001072 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001073 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001074 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1075 }
1076
David Blaikie960ea3f2014-06-08 16:18:35 +00001077 static std::unique_ptr<MipsOperand>
1078 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1079 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001080 Op->Imm.Val = Val;
1081 Op->StartLoc = S;
1082 Op->EndLoc = E;
1083 return Op;
1084 }
1085
David Blaikie960ea3f2014-06-08 16:18:35 +00001086 static std::unique_ptr<MipsOperand>
1087 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1088 SMLoc E, MipsAsmParser &Parser) {
1089 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1090 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001091 Op->Mem.Off = Off;
1092 Op->StartLoc = S;
1093 Op->EndLoc = E;
1094 return Op;
1095 }
1096
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001097 static std::unique_ptr<MipsOperand>
1098 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1099 MipsAsmParser &Parser) {
1100 assert (Regs.size() > 0 && "Empty list not allowed");
1101
1102 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001103 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001104 Op->StartLoc = StartLoc;
1105 Op->EndLoc = EndLoc;
1106 return Op;
1107 }
1108
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001109 static std::unique_ptr<MipsOperand>
1110 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1111 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1112 Op->RegIdx.Index = RegNo;
1113 Op->StartLoc = S;
1114 Op->EndLoc = E;
1115 return Op;
1116 }
1117
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001118 bool isGPRAsmReg() const {
1119 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001120 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001121 bool isMM16AsmReg() const {
1122 if (!(isRegIdx() && RegIdx.Kind))
1123 return false;
1124 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1125 || RegIdx.Index == 16 || RegIdx.Index == 17);
1126 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001127 bool isMM16AsmRegZero() const {
1128 if (!(isRegIdx() && RegIdx.Kind))
1129 return false;
1130 return (RegIdx.Index == 0 ||
1131 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1132 RegIdx.Index == 17);
1133 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001134 bool isMM16AsmRegMoveP() const {
1135 if (!(isRegIdx() && RegIdx.Kind))
1136 return false;
1137 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1138 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1139 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001140 bool isFGRAsmReg() const {
1141 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1142 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001143 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001144 bool isHWRegsAsmReg() const {
1145 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001146 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001147 bool isCCRAsmReg() const {
1148 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001149 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001150 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001151 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1152 return false;
1153 if (!AsmParser.hasEightFccRegisters())
1154 return RegIdx.Index == 0;
1155 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001156 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001157 bool isACCAsmReg() const {
1158 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001159 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001160 bool isCOP2AsmReg() const {
1161 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001162 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001163 bool isCOP3AsmReg() const {
1164 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1165 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001166 bool isMSA128AsmReg() const {
1167 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001168 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001169 bool isMSACtrlAsmReg() const {
1170 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001171 }
1172
Jack Carterb4dbc172012-09-05 23:34:03 +00001173 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001174 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001175 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001176 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001177
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001178 virtual ~MipsOperand() {
1179 switch (Kind) {
1180 case k_Immediate:
1181 break;
1182 case k_Memory:
1183 delete Mem.Base;
1184 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001185 case k_RegList:
1186 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001187 case k_PhysRegister:
1188 case k_RegisterIndex:
1189 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001190 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001191 break;
1192 }
1193 }
1194
Craig Topper56c590a2014-04-29 07:58:02 +00001195 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001196 switch (Kind) {
1197 case k_Immediate:
1198 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001199 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001200 OS << ">";
1201 break;
1202 case k_Memory:
1203 OS << "Mem<";
1204 Mem.Base->print(OS);
1205 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001206 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001207 OS << ">";
1208 break;
1209 case k_PhysRegister:
1210 OS << "PhysReg<" << PhysReg.Num << ">";
1211 break;
1212 case k_RegisterIndex:
1213 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1214 break;
1215 case k_Token:
1216 OS << Tok.Data;
1217 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001218 case k_RegList:
1219 OS << "RegList< ";
1220 for (auto Reg : (*RegList.List))
1221 OS << Reg << " ";
1222 OS << ">";
1223 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001224 case k_RegPair:
1225 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1226 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001227 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001228 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001229}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001230} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001231
Jack Carter9e65aa32013-03-22 00:05:30 +00001232namespace llvm {
1233extern const MCInstrDesc MipsInsts[];
1234}
1235static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1236 return MipsInsts[Opcode];
1237}
1238
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001239static bool hasShortDelaySlot(unsigned Opcode) {
1240 switch (Opcode) {
1241 case Mips::JALS_MM:
1242 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001243 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001244 case Mips::BGEZALS_MM:
1245 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001246 return true;
1247 default:
1248 return false;
1249 }
1250}
1251
Jack Carter9e65aa32013-03-22 00:05:30 +00001252bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001253 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001254 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001255
Jack Carter9e65aa32013-03-22 00:05:30 +00001256 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001257
1258 if (MCID.isBranch() || MCID.isCall()) {
1259 const unsigned Opcode = Inst.getOpcode();
1260 MCOperand Offset;
1261
1262 switch (Opcode) {
1263 default:
1264 break;
Kai Nackee0245392015-01-27 19:11:28 +00001265 case Mips::BBIT0:
1266 case Mips::BBIT032:
1267 case Mips::BBIT1:
1268 case Mips::BBIT132:
1269 assert(hasCnMips() && "instruction only valid for octeon cpus");
1270 // Fall through
1271
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001272 case Mips::BEQ:
1273 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001274 case Mips::BEQ_MM:
1275 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001276 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001277 Offset = Inst.getOperand(2);
1278 if (!Offset.isImm())
1279 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001280 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001281 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001282 if (OffsetToAlignment(Offset.getImm(),
1283 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001284 return Error(IDLoc, "branch to misaligned address");
1285 break;
1286 case Mips::BGEZ:
1287 case Mips::BGTZ:
1288 case Mips::BLEZ:
1289 case Mips::BLTZ:
1290 case Mips::BGEZAL:
1291 case Mips::BLTZAL:
1292 case Mips::BC1F:
1293 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001294 case Mips::BGEZ_MM:
1295 case Mips::BGTZ_MM:
1296 case Mips::BLEZ_MM:
1297 case Mips::BLTZ_MM:
1298 case Mips::BGEZAL_MM:
1299 case Mips::BLTZAL_MM:
1300 case Mips::BC1F_MM:
1301 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001302 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001303 Offset = Inst.getOperand(1);
1304 if (!Offset.isImm())
1305 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001306 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001307 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001308 if (OffsetToAlignment(Offset.getImm(),
1309 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001310 return Error(IDLoc, "branch to misaligned address");
1311 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001312 case Mips::BEQZ16_MM:
1313 case Mips::BNEZ16_MM:
1314 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1315 Offset = Inst.getOperand(1);
1316 if (!Offset.isImm())
1317 break; // We'll deal with this situation later on when applying fixups.
1318 if (!isIntN(8, Offset.getImm()))
1319 return Error(IDLoc, "branch target out of range");
1320 if (OffsetToAlignment(Offset.getImm(), 2LL))
1321 return Error(IDLoc, "branch to misaligned address");
1322 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001323 }
1324 }
1325
Daniel Sandersa84989a2014-06-16 13:25:35 +00001326 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1327 // We still accept it but it is a normal nop.
1328 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1329 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1330 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1331 "nop instruction");
1332 }
1333
Kai Nackee0245392015-01-27 19:11:28 +00001334 if (hasCnMips()) {
1335 const unsigned Opcode = Inst.getOpcode();
1336 MCOperand Opnd;
1337 int Imm;
1338
1339 switch (Opcode) {
1340 default:
1341 break;
1342
1343 case Mips::BBIT0:
1344 case Mips::BBIT032:
1345 case Mips::BBIT1:
1346 case Mips::BBIT132:
1347 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1348 // The offset is handled above
1349 Opnd = Inst.getOperand(1);
1350 if (!Opnd.isImm())
1351 return Error(IDLoc, "expected immediate operand kind");
1352 Imm = Opnd.getImm();
1353 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1354 Opcode == Mips::BBIT1 ? 63 : 31))
1355 return Error(IDLoc, "immediate operand value out of range");
1356 if (Imm > 31) {
1357 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1358 : Mips::BBIT132);
1359 Inst.getOperand(1).setImm(Imm - 32);
1360 }
1361 break;
1362
1363 case Mips::CINS:
1364 case Mips::CINS32:
1365 case Mips::EXTS:
1366 case Mips::EXTS32:
1367 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1368 // Check length
1369 Opnd = Inst.getOperand(3);
1370 if (!Opnd.isImm())
1371 return Error(IDLoc, "expected immediate operand kind");
1372 Imm = Opnd.getImm();
1373 if (Imm < 0 || Imm > 31)
1374 return Error(IDLoc, "immediate operand value out of range");
1375 // Check position
1376 Opnd = Inst.getOperand(2);
1377 if (!Opnd.isImm())
1378 return Error(IDLoc, "expected immediate operand kind");
1379 Imm = Opnd.getImm();
1380 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1381 Opcode == Mips::EXTS ? 63 : 31))
1382 return Error(IDLoc, "immediate operand value out of range");
1383 if (Imm > 31) {
1384 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1385 Inst.getOperand(2).setImm(Imm - 32);
1386 }
1387 break;
1388
1389 case Mips::SEQi:
1390 case Mips::SNEi:
1391 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1392 Opnd = Inst.getOperand(2);
1393 if (!Opnd.isImm())
1394 return Error(IDLoc, "expected immediate operand kind");
1395 Imm = Opnd.getImm();
1396 if (!isInt<10>(Imm))
1397 return Error(IDLoc, "immediate operand value out of range");
1398 break;
1399 }
1400 }
1401
Jack Carter9e65aa32013-03-22 00:05:30 +00001402 if (MCID.mayLoad() || MCID.mayStore()) {
1403 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001404 // reference or immediate we may have to expand instructions.
1405 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001406 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001407 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1408 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001409 MCOperand &Op = Inst.getOperand(i);
1410 if (Op.isImm()) {
1411 int MemOffset = Op.getImm();
1412 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001413 // Offset can't exceed 16bit value.
1414 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001415 return false;
1416 }
1417 } else if (Op.isExpr()) {
1418 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001419 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001420 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001421 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001422 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001423 // Expand symbol.
1424 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001425 return false;
1426 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001427 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001428 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001429 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001430 }
1431 }
1432 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001433 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001434 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001435
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001436 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001437 if (MCID.mayLoad()) {
1438 // Try to create 16-bit GP relative load instruction.
1439 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1440 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1441 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1442 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1443 MCOperand &Op = Inst.getOperand(i);
1444 if (Op.isImm()) {
1445 int MemOffset = Op.getImm();
1446 MCOperand &DstReg = Inst.getOperand(0);
1447 MCOperand &BaseReg = Inst.getOperand(1);
1448 if (isIntN(9, MemOffset) && (MemOffset % 4 == 0) &&
1449 getContext().getRegisterInfo()->getRegClass(
1450 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
1451 BaseReg.getReg() == Mips::GP) {
1452 MCInst TmpInst;
1453 TmpInst.setLoc(IDLoc);
1454 TmpInst.setOpcode(Mips::LWGP_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00001455 TmpInst.addOperand(MCOperand::createReg(DstReg.getReg()));
1456 TmpInst.addOperand(MCOperand::createReg(Mips::GP));
1457 TmpInst.addOperand(MCOperand::createImm(MemOffset));
Jozef Koleke10a02e2015-01-28 17:27:26 +00001458 Instructions.push_back(TmpInst);
1459 return false;
1460 }
1461 }
1462 }
1463 } // for
1464 } // if load
1465
1466 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1467
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001468 MCOperand Opnd;
1469 int Imm;
1470
1471 switch (Inst.getOpcode()) {
1472 default:
1473 break;
1474 case Mips::ADDIUS5_MM:
1475 Opnd = Inst.getOperand(2);
1476 if (!Opnd.isImm())
1477 return Error(IDLoc, "expected immediate operand kind");
1478 Imm = Opnd.getImm();
1479 if (Imm < -8 || Imm > 7)
1480 return Error(IDLoc, "immediate operand value out of range");
1481 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001482 case Mips::ADDIUSP_MM:
1483 Opnd = Inst.getOperand(0);
1484 if (!Opnd.isImm())
1485 return Error(IDLoc, "expected immediate operand kind");
1486 Imm = Opnd.getImm();
1487 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1488 Imm % 4 != 0)
1489 return Error(IDLoc, "immediate operand value out of range");
1490 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001491 case Mips::SLL16_MM:
1492 case Mips::SRL16_MM:
1493 Opnd = Inst.getOperand(2);
1494 if (!Opnd.isImm())
1495 return Error(IDLoc, "expected immediate operand kind");
1496 Imm = Opnd.getImm();
1497 if (Imm < 1 || Imm > 8)
1498 return Error(IDLoc, "immediate operand value out of range");
1499 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001500 case Mips::LI16_MM:
1501 Opnd = Inst.getOperand(1);
1502 if (!Opnd.isImm())
1503 return Error(IDLoc, "expected immediate operand kind");
1504 Imm = Opnd.getImm();
1505 if (Imm < -1 || Imm > 126)
1506 return Error(IDLoc, "immediate operand value out of range");
1507 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001508 case Mips::ADDIUR2_MM:
1509 Opnd = Inst.getOperand(2);
1510 if (!Opnd.isImm())
1511 return Error(IDLoc, "expected immediate operand kind");
1512 Imm = Opnd.getImm();
1513 if (!(Imm == 1 || Imm == -1 ||
1514 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1515 return Error(IDLoc, "immediate operand value out of range");
1516 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001517 case Mips::ADDIUR1SP_MM:
1518 Opnd = Inst.getOperand(1);
1519 if (!Opnd.isImm())
1520 return Error(IDLoc, "expected immediate operand kind");
1521 Imm = Opnd.getImm();
1522 if (OffsetToAlignment(Imm, 4LL))
1523 return Error(IDLoc, "misaligned immediate operand value");
1524 if (Imm < 0 || Imm > 255)
1525 return Error(IDLoc, "immediate operand value out of range");
1526 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001527 case Mips::ANDI16_MM:
1528 Opnd = Inst.getOperand(2);
1529 if (!Opnd.isImm())
1530 return Error(IDLoc, "expected immediate operand kind");
1531 Imm = Opnd.getImm();
1532 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1533 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1534 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1535 return Error(IDLoc, "immediate operand value out of range");
1536 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001537 case Mips::LBU16_MM:
1538 Opnd = Inst.getOperand(2);
1539 if (!Opnd.isImm())
1540 return Error(IDLoc, "expected immediate operand kind");
1541 Imm = Opnd.getImm();
1542 if (Imm < -1 || Imm > 14)
1543 return Error(IDLoc, "immediate operand value out of range");
1544 break;
1545 case Mips::SB16_MM:
1546 Opnd = Inst.getOperand(2);
1547 if (!Opnd.isImm())
1548 return Error(IDLoc, "expected immediate operand kind");
1549 Imm = Opnd.getImm();
1550 if (Imm < 0 || Imm > 15)
1551 return Error(IDLoc, "immediate operand value out of range");
1552 break;
1553 case Mips::LHU16_MM:
1554 case Mips::SH16_MM:
1555 Opnd = Inst.getOperand(2);
1556 if (!Opnd.isImm())
1557 return Error(IDLoc, "expected immediate operand kind");
1558 Imm = Opnd.getImm();
1559 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1560 return Error(IDLoc, "immediate operand value out of range");
1561 break;
1562 case Mips::LW16_MM:
1563 case Mips::SW16_MM:
1564 Opnd = Inst.getOperand(2);
1565 if (!Opnd.isImm())
1566 return Error(IDLoc, "expected immediate operand kind");
1567 Imm = Opnd.getImm();
1568 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1569 return Error(IDLoc, "immediate operand value out of range");
1570 break;
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001571 case Mips::CACHE:
1572 case Mips::PREF:
1573 Opnd = Inst.getOperand(2);
1574 if (!Opnd.isImm())
1575 return Error(IDLoc, "expected immediate operand kind");
1576 Imm = Opnd.getImm();
1577 if (!isUInt<5>(Imm))
1578 return Error(IDLoc, "immediate operand value out of range");
1579 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001580 case Mips::ADDIUPC_MM:
1581 MCOperand Opnd = Inst.getOperand(1);
1582 if (!Opnd.isImm())
1583 return Error(IDLoc, "expected immediate operand kind");
1584 int Imm = Opnd.getImm();
1585 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1586 return Error(IDLoc, "immediate operand value out of range");
1587 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001588 }
1589 }
1590
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001591 if (needsExpansion(Inst)) {
1592 if (expandInstruction(Inst, IDLoc, Instructions))
1593 return true;
1594 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001595 Instructions.push_back(Inst);
1596
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001597 // If this instruction has a delay slot and .set reorder is active,
1598 // emit a NOP after it.
1599 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1600 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1601
Jack Carter9e65aa32013-03-22 00:05:30 +00001602 return false;
1603}
1604
Jack Carter30a59822012-10-04 04:03:53 +00001605bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1606
Jack Carterd0bd6422013-04-18 00:41:53 +00001607 switch (Inst.getOpcode()) {
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001608 case Mips::LoadImm32:
1609 case Mips::LoadImm64:
1610 case Mips::LoadAddrImm32:
1611 case Mips::LoadAddrReg32:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001612 case Mips::B_MM_Pseudo:
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001613 case Mips::LWM_MM:
1614 case Mips::SWM_MM:
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001615 case Mips::JalOneReg:
1616 case Mips::JalTwoReg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001617 return true;
1618 default:
1619 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001620 }
1621}
Jack Carter92995f12012-10-06 00:53:28 +00001622
Matheus Almeida3813d572014-06-19 14:39:14 +00001623bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001624 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001625 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001626 default: llvm_unreachable("unimplemented expansion");
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001627 case Mips::LoadImm32:
Toma Tabacu00e98672015-05-01 12:19:27 +00001628 return expandLoadImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001629 case Mips::LoadImm64:
Toma Tabacu00e98672015-05-01 12:19:27 +00001630 return expandLoadImm(Inst, false, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001631 case Mips::LoadAddrImm32:
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001632 return expandLoadAddressImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001633 case Mips::LoadAddrReg32:
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001634 return expandLoadAddressReg(Inst, true, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001635 case Mips::B_MM_Pseudo:
1636 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001637 case Mips::SWM_MM:
1638 case Mips::LWM_MM:
1639 return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001640 case Mips::JalOneReg:
1641 case Mips::JalTwoReg:
1642 return expandJalWithRegs(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001643 }
Jack Carter30a59822012-10-04 04:03:53 +00001644}
Jack Carter92995f12012-10-06 00:53:28 +00001645
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001646namespace {
Toma Tabacua2861db2015-05-01 10:26:47 +00001647template <unsigned ShiftAmount>
Toma Tabacu61145652015-04-28 13:16:06 +00001648void createLShiftOri(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001649 SmallVectorImpl<MCInst> &Instructions) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001650 MCInst tmpInst;
Toma Tabacua2861db2015-05-01 10:26:47 +00001651 if (ShiftAmount >= 32) {
1652 tmpInst.setOpcode(Mips::DSLL32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001653 tmpInst.addOperand(MCOperand::createReg(RegNo));
1654 tmpInst.addOperand(MCOperand::createReg(RegNo));
1655 tmpInst.addOperand(MCOperand::createImm(ShiftAmount - 32));
Toma Tabacua2861db2015-05-01 10:26:47 +00001656 tmpInst.setLoc(IDLoc);
1657 Instructions.push_back(tmpInst);
1658 tmpInst.clear();
1659 } else if (ShiftAmount > 0) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001660 tmpInst.setOpcode(Mips::DSLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00001661 tmpInst.addOperand(MCOperand::createReg(RegNo));
1662 tmpInst.addOperand(MCOperand::createReg(RegNo));
1663 tmpInst.addOperand(MCOperand::createImm(ShiftAmount));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001664 tmpInst.setLoc(IDLoc);
1665 Instructions.push_back(tmpInst);
1666 tmpInst.clear();
1667 }
Toma Tabacu7dea2e32015-04-28 14:06:35 +00001668 // There's no need for an ORi if the immediate is 0.
1669 if (Operand.isImm() && Operand.getImm() == 0)
1670 return;
1671
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001672 tmpInst.setOpcode(Mips::ORi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001673 tmpInst.addOperand(MCOperand::createReg(RegNo));
1674 tmpInst.addOperand(MCOperand::createReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001675 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001676 tmpInst.setLoc(IDLoc);
1677 Instructions.push_back(tmpInst);
1678}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001679
Toma Tabacua2861db2015-05-01 10:26:47 +00001680template <unsigned ShiftAmount>
Toma Tabacu61145652015-04-28 13:16:06 +00001681void createLShiftOri(int64_t Value, unsigned RegNo, SMLoc IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001682 SmallVectorImpl<MCInst> &Instructions) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001683 createLShiftOri<ShiftAmount>(MCOperand::createImm(Value), RegNo, IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001684 Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001685}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001686}
1687
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001688bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
1689 SmallVectorImpl<MCInst> &Instructions) {
1690 // Create a JALR instruction which is going to replace the pseudo-JAL.
1691 MCInst JalrInst;
1692 JalrInst.setLoc(IDLoc);
1693 const MCOperand FirstRegOp = Inst.getOperand(0);
1694 const unsigned Opcode = Inst.getOpcode();
1695
1696 if (Opcode == Mips::JalOneReg) {
1697 // jal $rs => jalr $rs
1698 if (inMicroMipsMode()) {
1699 JalrInst.setOpcode(Mips::JALR16_MM);
1700 JalrInst.addOperand(FirstRegOp);
1701 } else {
1702 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00001703 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001704 JalrInst.addOperand(FirstRegOp);
1705 }
1706 } else if (Opcode == Mips::JalTwoReg) {
1707 // jal $rd, $rs => jalr $rd, $rs
1708 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
1709 JalrInst.addOperand(FirstRegOp);
1710 const MCOperand SecondRegOp = Inst.getOperand(1);
1711 JalrInst.addOperand(SecondRegOp);
1712 }
1713 Instructions.push_back(JalrInst);
1714
1715 // If .set reorder is active, emit a NOP after it.
1716 if (AssemblerOptions.back()->isReorder()) {
1717 // This is a 32-bit NOP because these 2 pseudo-instructions
1718 // do not have a short delay slot.
1719 MCInst NopInst;
1720 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00001721 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
1722 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
1723 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001724 Instructions.push_back(NopInst);
1725 }
1726
1727 return false;
1728}
1729
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001730bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
1731 unsigned SrcReg, bool Is32BitImm, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001732 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00001733 if (!Is32BitImm && !isGP64bit()) {
1734 Error(IDLoc, "instruction requires a 64-bit architecture");
1735 return true;
1736 }
1737
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001738 bool UseSrcReg = false;
1739 if (SrcReg != Mips::NoRegister)
1740 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00001741
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001742 MCInst tmpInst;
1743
Jack Carter92995f12012-10-06 00:53:28 +00001744 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001745 // FIXME: gas has a special case for values that are 000...1111, which
1746 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001747 if (0 <= ImmValue && ImmValue <= 65535) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001748 // For unsigned and positive signed 16-bit values (0 <= j <= 65535):
Jack Carter30a59822012-10-04 04:03:53 +00001749 // li d,j => ori d,$zero,j
Toma Tabacudf7fd462015-05-13 16:02:41 +00001750 if (!UseSrcReg)
1751 SrcReg = isGP64bit() ? Mips::ZERO_64 : Mips::ZERO;
Jack Carter873c7242013-01-12 01:03:14 +00001752 tmpInst.setOpcode(Mips::ORi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001753 tmpInst.addOperand(MCOperand::createReg(DstReg));
1754 tmpInst.addOperand(MCOperand::createReg(SrcReg));
1755 tmpInst.addOperand(MCOperand::createImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001756 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001757 } else if (ImmValue < 0 && ImmValue >= -32768) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001758 // For negative signed 16-bit values (-32768 <= j < 0):
Jack Carter30a59822012-10-04 04:03:53 +00001759 // li d,j => addiu d,$zero,j
Toma Tabacudf7fd462015-05-13 16:02:41 +00001760 if (!UseSrcReg)
1761 SrcReg = Mips::ZERO;
Jack Carter873c7242013-01-12 01:03:14 +00001762 tmpInst.setOpcode(Mips::ADDiu);
Jim Grosbache9119e42015-05-13 18:37:00 +00001763 tmpInst.addOperand(MCOperand::createReg(DstReg));
1764 tmpInst.addOperand(MCOperand::createReg(SrcReg));
1765 tmpInst.addOperand(MCOperand::createImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001766 Instructions.push_back(tmpInst);
Toma Tabacua3d056f2015-05-15 09:42:11 +00001767 } else if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00001768 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00001769
Toma Tabacuae47f932015-04-10 13:28:16 +00001770 // For all other values which are representable as a 32-bit integer:
Jack Carter30a59822012-10-04 04:03:53 +00001771 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001772 // ori d,d,lo16(j)
Toma Tabacu79588102015-04-29 10:19:56 +00001773 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1774 uint16_t Bits15To0 = ImmValue & 0xffff;
1775
Toma Tabacua3d056f2015-05-15 09:42:11 +00001776 if (!Is32BitImm && !isInt<32>(ImmValue)) {
1777 // For DLI, expand to an ORi instead of a LUi to avoid sign-extending the
1778 // upper 32 bits.
1779 tmpInst.setOpcode(Mips::ORi);
1780 tmpInst.addOperand(MCOperand::createReg(DstReg));
1781 tmpInst.addOperand(MCOperand::createReg(Mips::ZERO));
1782 tmpInst.addOperand(MCOperand::createImm(Bits31To16));
1783 tmpInst.setLoc(IDLoc);
1784 Instructions.push_back(tmpInst);
1785 // Move the value to the upper 16 bits by doing a 16-bit left shift.
1786 createLShiftOri<16>(0, DstReg, IDLoc, Instructions);
1787 } else {
1788 tmpInst.setOpcode(Mips::LUi);
1789 tmpInst.addOperand(MCOperand::createReg(DstReg));
1790 tmpInst.addOperand(MCOperand::createImm(Bits31To16));
1791 Instructions.push_back(tmpInst);
1792 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001793 createLShiftOri<0>(Bits15To0, DstReg, IDLoc, Instructions);
1794
1795 if (UseSrcReg)
1796 createAddu(DstReg, DstReg, SrcReg, Instructions);
1797
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001798 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Toma Tabacu00e98672015-05-01 12:19:27 +00001799 if (Is32BitImm) {
1800 Error(IDLoc, "instruction requires a 32-bit immediate");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001801 return true;
1802 }
Toma Tabacu81496c12015-05-20 08:54:45 +00001803 warnIfNoMacro(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001804
1805 // <------- lo32 ------>
1806 // <------- hi32 ------>
1807 // <- hi16 -> <- lo16 ->
1808 // _________________________________
1809 // | | | |
Toma Tabacubda745f2015-04-27 15:21:38 +00001810 // | 16-bits | 16-bits | 16-bits |
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001811 // |__________|__________|__________|
1812 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001813 // For any 64-bit value that is representable as a 48-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001814 // li d,j => lui d,hi16(j)
1815 // ori d,d,hi16(lo32(j))
1816 // dsll d,d,16
1817 // ori d,d,lo16(lo32(j))
Toma Tabacu79588102015-04-29 10:19:56 +00001818 uint16_t Bits47To32 = (ImmValue >> 32) & 0xffff;
1819 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1820 uint16_t Bits15To0 = ImmValue & 0xffff;
1821
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001822 tmpInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001823 tmpInst.addOperand(MCOperand::createReg(DstReg));
1824 tmpInst.addOperand(MCOperand::createImm(Bits47To32));
Jack Carter30a59822012-10-04 04:03:53 +00001825 Instructions.push_back(tmpInst);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001826 createLShiftOri<0>(Bits31To16, DstReg, IDLoc, Instructions);
1827 createLShiftOri<16>(Bits15To0, DstReg, IDLoc, Instructions);
1828
1829 if (UseSrcReg)
1830 createAddu(DstReg, DstReg, SrcReg, Instructions);
1831
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001832 } else {
Toma Tabacu00e98672015-05-01 12:19:27 +00001833 if (Is32BitImm) {
1834 Error(IDLoc, "instruction requires a 32-bit immediate");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001835 return true;
1836 }
Toma Tabacu81496c12015-05-20 08:54:45 +00001837 warnIfNoMacro(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001838
1839 // <------- hi32 ------> <------- lo32 ------>
1840 // <- hi16 -> <- lo16 ->
1841 // ___________________________________________
1842 // | | | | |
Toma Tabacubda745f2015-04-27 15:21:38 +00001843 // | 16-bits | 16-bits | 16-bits | 16-bits |
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001844 // |__________|__________|__________|__________|
1845 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001846 // For all other values which are representable as a 64-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001847 // li d,j => lui d,hi16(j)
1848 // ori d,d,lo16(hi32(j))
1849 // dsll d,d,16
1850 // ori d,d,hi16(lo32(j))
1851 // dsll d,d,16
1852 // ori d,d,lo16(lo32(j))
Toma Tabacu79588102015-04-29 10:19:56 +00001853 uint16_t Bits63To48 = (ImmValue >> 48) & 0xffff;
1854 uint16_t Bits47To32 = (ImmValue >> 32) & 0xffff;
1855 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1856 uint16_t Bits15To0 = ImmValue & 0xffff;
1857
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001858 tmpInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001859 tmpInst.addOperand(MCOperand::createReg(DstReg));
1860 tmpInst.addOperand(MCOperand::createImm(Bits63To48));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001861 Instructions.push_back(tmpInst);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001862 createLShiftOri<0>(Bits47To32, DstReg, IDLoc, Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001863
1864 // When Bits31To16 is 0, do a left shift of 32 bits instead of doing
1865 // two left shifts of 16 bits.
1866 if (Bits31To16 == 0) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001867 createLShiftOri<32>(Bits15To0, DstReg, IDLoc, Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001868 } else {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001869 createLShiftOri<16>(Bits31To16, DstReg, IDLoc, Instructions);
1870 createLShiftOri<16>(Bits15To0, DstReg, IDLoc, Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001871 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001872
1873 if (UseSrcReg)
1874 createAddu(DstReg, DstReg, SrcReg, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001875 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001876 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001877}
Jack Carter92995f12012-10-06 00:53:28 +00001878
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001879bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
1880 SmallVectorImpl<MCInst> &Instructions) {
1881 const MCOperand &ImmOp = Inst.getOperand(1);
1882 assert(ImmOp.isImm() && "expected immediate operand kind");
1883 const MCOperand &DstRegOp = Inst.getOperand(0);
1884 assert(DstRegOp.isReg() && "expected register operand kind");
1885
1886 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
1887 Is32BitImm, IDLoc, Instructions))
1888 return true;
1889
1890 return false;
1891}
1892
Matheus Almeida3813d572014-06-19 14:39:14 +00001893bool
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001894MipsAsmParser::expandLoadAddressReg(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001895 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacub5592ee2015-05-14 10:02:58 +00001896 const MCOperand &DstRegOp = Inst.getOperand(0);
1897 assert(DstRegOp.isReg() && "expected register operand kind");
1898
Jack Carter543fdf82012-10-09 23:29:45 +00001899 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001900 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1901 "expected immediate operand kind");
1902 if (!ImmOp.isImm()) {
Toma Tabacuec1de822015-05-14 10:53:40 +00001903 expandLoadAddressSym(DstRegOp, ImmOp, Is32BitImm, IDLoc, Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001904 return false;
1905 }
Jack Carter543fdf82012-10-09 23:29:45 +00001906 const MCOperand &SrcRegOp = Inst.getOperand(1);
1907 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001908
1909 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), SrcRegOp.getReg(),
1910 Is32BitImm, IDLoc, Instructions))
1911 return true;
1912
Matheus Almeida3813d572014-06-19 14:39:14 +00001913 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001914}
1915
Matheus Almeida3813d572014-06-19 14:39:14 +00001916bool
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001917MipsAsmParser::expandLoadAddressImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001918 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacub5592ee2015-05-14 10:02:58 +00001919 const MCOperand &DstRegOp = Inst.getOperand(0);
1920 assert(DstRegOp.isReg() && "expected register operand kind");
1921
Jack Carter543fdf82012-10-09 23:29:45 +00001922 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001923 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1924 "expected immediate operand kind");
1925 if (!ImmOp.isImm()) {
Toma Tabacuec1de822015-05-14 10:53:40 +00001926 expandLoadAddressSym(DstRegOp, ImmOp, Is32BitImm, IDLoc, Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001927 return false;
1928 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001929
1930 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
1931 Is32BitImm, IDLoc, Instructions))
1932 return true;
1933
Matheus Almeida3813d572014-06-19 14:39:14 +00001934 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001935}
1936
Toma Tabacuec1de822015-05-14 10:53:40 +00001937void MipsAsmParser::expandLoadAddressSym(
1938 const MCOperand &DstRegOp, const MCOperand &SymOp, bool Is32BitSym,
1939 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00001940 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00001941
Toma Tabacuec1de822015-05-14 10:53:40 +00001942 if (Is32BitSym && isABI_N64())
1943 Warning(IDLoc, "instruction loads the 32-bit address of a 64-bit symbol");
1944
Toma Tabacu0d64b202014-08-14 10:29:17 +00001945 MCInst tmpInst;
Toma Tabacub5592ee2015-05-14 10:02:58 +00001946 unsigned RegNo = DstRegOp.getReg();
Toma Tabacu0d64b202014-08-14 10:29:17 +00001947 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1948 const MCSymbolRefExpr *HiExpr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00001949 MCSymbolRefExpr::create(Symbol->getSymbol().getName(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00001950 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1951 const MCSymbolRefExpr *LoExpr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00001952 MCSymbolRefExpr::create(Symbol->getSymbol().getName(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00001953 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
Toma Tabacuec1de822015-05-14 10:53:40 +00001954 if (!Is32BitSym) {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001955 // If it's a 64-bit architecture, expand to:
1956 // la d,sym => lui d,highest(sym)
1957 // ori d,d,higher(sym)
1958 // dsll d,d,16
1959 // ori d,d,hi16(sym)
1960 // dsll d,d,16
1961 // ori d,d,lo16(sym)
1962 const MCSymbolRefExpr *HighestExpr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00001963 MCSymbolRefExpr::create(Symbol->getSymbol().getName(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00001964 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1965 const MCSymbolRefExpr *HigherExpr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00001966 MCSymbolRefExpr::create(Symbol->getSymbol().getName(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00001967 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1968
1969 tmpInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001970 tmpInst.addOperand(MCOperand::createReg(RegNo));
1971 tmpInst.addOperand(MCOperand::createExpr(HighestExpr));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001972 Instructions.push_back(tmpInst);
1973
Jim Grosbache9119e42015-05-13 18:37:00 +00001974 createLShiftOri<0>(MCOperand::createExpr(HigherExpr), RegNo, SMLoc(),
Toma Tabacua2861db2015-05-01 10:26:47 +00001975 Instructions);
Jim Grosbache9119e42015-05-13 18:37:00 +00001976 createLShiftOri<16>(MCOperand::createExpr(HiExpr), RegNo, SMLoc(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00001977 Instructions);
Jim Grosbache9119e42015-05-13 18:37:00 +00001978 createLShiftOri<16>(MCOperand::createExpr(LoExpr), RegNo, SMLoc(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00001979 Instructions);
1980 } else {
1981 // Otherwise, expand to:
1982 // la d,sym => lui d,hi16(sym)
1983 // ori d,d,lo16(sym)
1984 tmpInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001985 tmpInst.addOperand(MCOperand::createReg(RegNo));
1986 tmpInst.addOperand(MCOperand::createExpr(HiExpr));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001987 Instructions.push_back(tmpInst);
1988
Jim Grosbache9119e42015-05-13 18:37:00 +00001989 createLShiftOri<0>(MCOperand::createExpr(LoExpr), RegNo, SMLoc(),
Toma Tabacua2861db2015-05-01 10:26:47 +00001990 Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001991 }
1992}
1993
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00001994bool MipsAsmParser::expandUncondBranchMMPseudo(
1995 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00001996 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
1997 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001998
1999 MCOperand Offset = Inst.getOperand(0);
2000 if (Offset.isExpr()) {
2001 Inst.clear();
2002 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002003 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2004 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2005 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002006 } else {
2007 assert(Offset.isImm() && "expected immediate operand kind");
2008 if (isIntN(11, Offset.getImm())) {
2009 // If offset fits into 11 bits then this instruction becomes microMIPS
2010 // 16-bit unconditional branch instruction.
2011 Inst.setOpcode(Mips::B16_MM);
2012 } else {
2013 if (!isIntN(17, Offset.getImm()))
2014 Error(IDLoc, "branch target out of range");
2015 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2016 Error(IDLoc, "branch to misaligned address");
2017 Inst.clear();
2018 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002019 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2020 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2021 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002022 }
2023 }
2024 Instructions.push_back(Inst);
2025
Toma Tabacu234482a2015-03-16 12:03:39 +00002026 // If .set reorder is active, emit a NOP after the branch instruction.
2027 if (AssemblerOptions.back()->isReorder())
2028 createNop(true, IDLoc, Instructions);
2029
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002030 return false;
2031}
2032
Jack Carter9e65aa32013-03-22 00:05:30 +00002033void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002034 SmallVectorImpl<MCInst> &Instructions,
2035 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002036 const MCSymbolRefExpr *SR;
2037 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00002038 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002039 const MCExpr *ExprOffset;
2040 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002041 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002042 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2043 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002044 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002045 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2046 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002047 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002048 if (isImmOpnd) {
2049 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2050 ImmOffset = Inst.getOperand(2).getImm();
2051 LoOffset = ImmOffset & 0x0000ffff;
2052 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002053 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002054 if (LoOffset & 0x8000)
2055 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002056 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002057 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002058 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002059 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002060 // These are some of the types of expansions we perform here:
2061 // 1) lw $8, sym => lui $8, %hi(sym)
2062 // lw $8, %lo(sym)($8)
2063 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2064 // add $8, $8, $9
2065 // lw $8, %lo(offset)($9)
2066 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2067 // add $at, $at, $8
2068 // lw $8, %lo(offset)($at)
2069 // 4) sw $8, sym => lui $at, %hi(sym)
2070 // sw $8, %lo(sym)($at)
2071 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2072 // add $at, $at, $8
2073 // sw $8, %lo(offset)($at)
2074 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2075 // ldc1 $f0, %lo(sym)($at)
2076 //
2077 // For load instructions we can use the destination register as a temporary
2078 // if base and dst are different (examples 1 and 2) and if the base register
2079 // is general purpose otherwise we must use $at (example 6) and error if it's
2080 // not available. For stores we must use $at (examples 4 and 5) because we
2081 // must not clobber the source register setting up the offset.
2082 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2083 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2084 unsigned RegClassIDOp0 =
2085 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2086 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2087 (RegClassIDOp0 == Mips::GPR64RegClassID);
2088 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002089 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002090 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002091 // At this point we need AT to perform the expansions and we exit if it is
2092 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002093 TmpRegNum = getATReg(IDLoc);
2094 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002095 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002096 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002097
Jack Carter9e65aa32013-03-22 00:05:30 +00002098 TempInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00002099 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002100 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002101 TempInst.addOperand(MCOperand::createImm(HiOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002102 else {
2103 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002104 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jim Grosbach13760bd2015-05-30 01:25:56 +00002105 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::create(
Jack Carterd0bd6422013-04-18 00:41:53 +00002106 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
2107 getContext());
Jim Grosbache9119e42015-05-13 18:37:00 +00002108 TempInst.addOperand(MCOperand::createExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002109 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002110 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jim Grosbache9119e42015-05-13 18:37:00 +00002111 TempInst.addOperand(MCOperand::createExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002112 }
2113 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002114 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002115 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002116 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002117 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002118 // Add temp register to base.
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002119 if (BaseRegNum != Mips::ZERO) {
2120 TempInst.setOpcode(Mips::ADDu);
Jim Grosbache9119e42015-05-13 18:37:00 +00002121 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2122 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2123 TempInst.addOperand(MCOperand::createReg(BaseRegNum));
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002124 Instructions.push_back(TempInst);
2125 TempInst.clear();
2126 }
Alp Tokercb402912014-01-24 17:20:08 +00002127 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002128 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002129 TempInst.setOpcode(Inst.getOpcode());
Jim Grosbache9119e42015-05-13 18:37:00 +00002130 TempInst.addOperand(MCOperand::createReg(RegOpNum));
2131 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002132 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002133 TempInst.addOperand(MCOperand::createImm(LoOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002134 else {
2135 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002136 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::create(
Jack Carterd0bd6422013-04-18 00:41:53 +00002137 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
2138 getContext());
Jim Grosbache9119e42015-05-13 18:37:00 +00002139 TempInst.addOperand(MCOperand::createExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002140 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002141 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jim Grosbache9119e42015-05-13 18:37:00 +00002142 TempInst.addOperand(MCOperand::createExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002143 }
2144 }
2145 Instructions.push_back(TempInst);
2146 TempInst.clear();
2147}
2148
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002149bool
2150MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2151 SmallVectorImpl<MCInst> &Instructions) {
2152 unsigned OpNum = Inst.getNumOperands();
2153 unsigned Opcode = Inst.getOpcode();
2154 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2155
2156 assert (Inst.getOperand(OpNum - 1).isImm() &&
2157 Inst.getOperand(OpNum - 2).isReg() &&
2158 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2159
2160 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2161 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2162 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2163 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2164 // It can be implemented as SWM16 or LWM16 instruction.
2165 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2166
2167 Inst.setOpcode(NewOpcode);
2168 Instructions.push_back(Inst);
2169 return false;
2170}
2171
Toma Tabacu234482a2015-03-16 12:03:39 +00002172void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
2173 SmallVectorImpl<MCInst> &Instructions) {
2174 MCInst NopInst;
2175 if (hasShortDelaySlot) {
2176 NopInst.setOpcode(Mips::MOVE16_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002177 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2178 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
Toma Tabacu234482a2015-03-16 12:03:39 +00002179 } else {
2180 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00002181 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2182 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2183 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu234482a2015-03-16 12:03:39 +00002184 }
2185 Instructions.push_back(NopInst);
2186}
2187
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002188void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
2189 unsigned TrgReg,
2190 SmallVectorImpl<MCInst> &Instructions) {
2191 MCInst AdduInst;
2192 AdduInst.setOpcode(Mips::ADDu);
Jim Grosbache9119e42015-05-13 18:37:00 +00002193 AdduInst.addOperand(MCOperand::createReg(DstReg));
2194 AdduInst.addOperand(MCOperand::createReg(SrcReg));
2195 AdduInst.addOperand(MCOperand::createReg(TrgReg));
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002196 Instructions.push_back(AdduInst);
2197}
2198
Matheus Almeida595fcab2014-06-11 15:05:56 +00002199unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
2200 // As described by the Mips32r2 spec, the registers Rd and Rs for
2201 // jalr.hb must be different.
2202 unsigned Opcode = Inst.getOpcode();
2203
2204 if (Opcode == Mips::JALR_HB &&
2205 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
2206 return Match_RequiresDifferentSrcAndDst;
2207
2208 return Match_Success;
2209}
2210
David Blaikie960ea3f2014-06-08 16:18:35 +00002211bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
2212 OperandVector &Operands,
2213 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00002214 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00002215 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00002216
Jack Carterb4dbc172012-09-05 23:34:03 +00002217 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00002218 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00002219 unsigned MatchResult =
2220 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00002221
2222 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002223 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002224 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00002225 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00002226 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00002227 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00002228 return false;
2229 }
2230 case Match_MissingFeature:
2231 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
2232 return true;
2233 case Match_InvalidOperand: {
2234 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00002235 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002236 if (ErrorInfo >= Operands.size())
2237 return Error(IDLoc, "too few operands for instruction");
2238
David Blaikie960ea3f2014-06-08 16:18:35 +00002239 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00002240 if (ErrorLoc == SMLoc())
2241 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00002242 }
2243
2244 return Error(ErrorLoc, "invalid operand for instruction");
2245 }
2246 case Match_MnemonicFail:
2247 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00002248 case Match_RequiresDifferentSrcAndDst:
2249 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00002250 }
Craig Topper589ceee2015-01-03 08:16:34 +00002251
2252 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00002253}
2254
Toma Tabacud9d344b2015-04-27 14:05:04 +00002255void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
2256 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
2257 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
2258 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002259}
2260
Toma Tabacu81496c12015-05-20 08:54:45 +00002261void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
2262 if (!AssemblerOptions.back()->isMacro())
2263 Warning(Loc, "macro instruction expanded into multiple instructions");
2264}
2265
Daniel Sandersef638fe2014-10-03 15:37:37 +00002266void
2267MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
2268 SMRange Range, bool ShowColors) {
2269 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00002270 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00002271 ShowColors);
2272}
2273
Jack Carter1ac53222013-02-20 23:11:17 +00002274int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002275 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002276
Vladimir Medic4c299852013-11-06 11:27:05 +00002277 CC = StringSwitch<unsigned>(Name)
2278 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002279 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00002280 .Case("a0", 4)
2281 .Case("a1", 5)
2282 .Case("a2", 6)
2283 .Case("a3", 7)
2284 .Case("v0", 2)
2285 .Case("v1", 3)
2286 .Case("s0", 16)
2287 .Case("s1", 17)
2288 .Case("s2", 18)
2289 .Case("s3", 19)
2290 .Case("s4", 20)
2291 .Case("s5", 21)
2292 .Case("s6", 22)
2293 .Case("s7", 23)
2294 .Case("k0", 26)
2295 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002296 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00002297 .Case("sp", 29)
2298 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002299 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00002300 .Case("ra", 31)
2301 .Case("t0", 8)
2302 .Case("t1", 9)
2303 .Case("t2", 10)
2304 .Case("t3", 11)
2305 .Case("t4", 12)
2306 .Case("t5", 13)
2307 .Case("t6", 14)
2308 .Case("t7", 15)
2309 .Case("t8", 24)
2310 .Case("t9", 25)
2311 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002312
Toma Tabacufda445c2014-09-15 15:33:01 +00002313 if (!(isABI_N32() || isABI_N64()))
2314 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002315
Daniel Sandersef638fe2014-10-03 15:37:37 +00002316 if (12 <= CC && CC <= 15) {
2317 // Name is one of t4-t7
2318 AsmToken RegTok = getLexer().peekTok();
2319 SMRange RegRange = RegTok.getLocRange();
2320
2321 StringRef FixedName = StringSwitch<StringRef>(Name)
2322 .Case("t4", "t0")
2323 .Case("t5", "t1")
2324 .Case("t6", "t2")
2325 .Case("t7", "t3")
2326 .Default("");
2327 assert(FixedName != "" && "Register name is not one of t4-t7.");
2328
2329 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
2330 "Did you mean $" + FixedName + "?", RegRange);
2331 }
2332
Toma Tabacufda445c2014-09-15 15:33:01 +00002333 // Although SGI documentation just cuts out t0-t3 for n32/n64,
2334 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
2335 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
2336 if (8 <= CC && CC <= 11)
2337 CC += 4;
2338
2339 if (CC == -1)
2340 CC = StringSwitch<unsigned>(Name)
2341 .Case("a4", 8)
2342 .Case("a5", 9)
2343 .Case("a6", 10)
2344 .Case("a7", 11)
2345 .Case("kt0", 26)
2346 .Case("kt1", 27)
2347 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002348
2349 return CC;
2350}
Jack Carterd0bd6422013-04-18 00:41:53 +00002351
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002352int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
2353 int CC;
2354
2355 CC = StringSwitch<unsigned>(Name)
2356 .Case("hwr_cpunum", 0)
2357 .Case("hwr_synci_step", 1)
2358 .Case("hwr_cc", 2)
2359 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00002360 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002361 .Default(-1);
2362
2363 return CC;
2364}
2365
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002366int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002367
Jack Cartera63b16a2012-09-07 00:23:42 +00002368 if (Name[0] == 'f') {
2369 StringRef NumString = Name.substr(1);
2370 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002371 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002372 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002373 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00002374 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002375 return IntVal;
2376 }
2377 return -1;
2378}
Jack Cartera63b16a2012-09-07 00:23:42 +00002379
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002380int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
2381
2382 if (Name.startswith("fcc")) {
2383 StringRef NumString = Name.substr(3);
2384 unsigned IntVal;
2385 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002386 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002387 if (IntVal > 7) // There are only 8 fcc registers.
2388 return -1;
2389 return IntVal;
2390 }
2391 return -1;
2392}
2393
2394int MipsAsmParser::matchACRegisterName(StringRef Name) {
2395
Akira Hatanaka274d24c2013-08-14 01:15:52 +00002396 if (Name.startswith("ac")) {
2397 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002398 unsigned IntVal;
2399 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002400 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002401 if (IntVal > 3) // There are only 3 acc registers.
2402 return -1;
2403 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00002404 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002405 return -1;
2406}
Jack Carterd0bd6422013-04-18 00:41:53 +00002407
Jack Carter5dc8ac92013-09-25 23:50:44 +00002408int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
2409 unsigned IntVal;
2410
2411 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2412 return -1;
2413
2414 if (IntVal > 31)
2415 return -1;
2416
2417 return IntVal;
2418}
2419
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002420int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
2421 int CC;
2422
2423 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00002424 .Case("msair", 0)
2425 .Case("msacsr", 1)
2426 .Case("msaaccess", 2)
2427 .Case("msasave", 3)
2428 .Case("msamodify", 4)
2429 .Case("msarequest", 5)
2430 .Case("msamap", 6)
2431 .Case("msaunmap", 7)
2432 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002433
2434 return CC;
2435}
2436
Toma Tabacu89a712b2015-04-15 10:48:56 +00002437unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00002438 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00002439 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002440 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00002441 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00002442 return 0;
2443 }
2444 unsigned AT = getReg(
2445 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00002446 return AT;
2447}
Jack Carter0b744b32012-10-04 02:29:46 +00002448
Jack Carterd0bd6422013-04-18 00:41:53 +00002449unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00002450 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00002451}
2452
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002453unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002454 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00002455 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002456}
2457
Jack Carter873c7242013-01-12 01:03:14 +00002458int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002459 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00002460 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00002461 return -1;
2462
Jack Carter873c7242013-01-12 01:03:14 +00002463 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00002464}
2465
Toma Tabacu13964452014-09-04 13:23:44 +00002466bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002467 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002468 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002469
Jack Carter30a59822012-10-04 04:03:53 +00002470 // Check if the current operand has a custom associated parser, if so, try to
2471 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00002472 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2473 if (ResTy == MatchOperand_Success)
2474 return false;
2475 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2476 // there was a match, but an error occurred, in which case, just return that
2477 // the operand parsing failed.
2478 if (ResTy == MatchOperand_ParseFail)
2479 return true;
2480
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002481 DEBUG(dbgs() << ".. Generic Parser\n");
2482
Jack Carterb4dbc172012-09-05 23:34:03 +00002483 switch (getLexer().getKind()) {
2484 default:
2485 Error(Parser.getTok().getLoc(), "unexpected token in operand");
2486 return true;
2487 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002488 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00002489 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00002490
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002491 // Almost all registers have been parsed by custom parsers. There is only
2492 // one exception to this. $zero (and it's alias $0) will reach this point
2493 // for div, divu, and similar instructions because it is not an operand
2494 // to the instruction definition but an explicit register. Special case
2495 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00002496 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00002497 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002498
Jack Carterd0bd6422013-04-18 00:41:53 +00002499 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00002500 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002501 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00002502 return true;
2503
Jack Carter873c7242013-01-12 01:03:14 +00002504 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00002505 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00002506 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00002507 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002508 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00002509
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002510 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002511 return false;
2512 }
Vladimir Medic4c299852013-11-06 11:27:05 +00002513 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00002514 case AsmToken::LParen:
2515 case AsmToken::Minus:
2516 case AsmToken::Plus:
2517 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002518 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00002519 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002520 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002521 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002522 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00002523 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00002524 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002525 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002526 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002527 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00002528 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00002529 return true;
2530
Jack Carter873c7242013-01-12 01:03:14 +00002531 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2532
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002533 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00002534 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002535 } // case AsmToken::Percent
2536 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00002537 return true;
2538}
2539
Vladimir Medic4c299852013-11-06 11:27:05 +00002540const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00002541 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00002542 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00002543 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002544 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00002545 // It's a constant, evaluate reloc value.
2546 int16_t Val;
2547 switch (getVariantKind(RelocStr)) {
2548 case MCSymbolRefExpr::VK_Mips_ABS_LO:
2549 // Get the 1st 16-bits.
2550 Val = MCE->getValue() & 0xffff;
2551 break;
2552 case MCSymbolRefExpr::VK_Mips_ABS_HI:
2553 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2554 // 16 bits being negative.
2555 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2556 break;
2557 case MCSymbolRefExpr::VK_Mips_HIGHER:
2558 // Get the 3rd 16-bits.
2559 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2560 break;
2561 case MCSymbolRefExpr::VK_Mips_HIGHEST:
2562 // Get the 4th 16-bits.
2563 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2564 break;
2565 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00002566 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00002567 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00002568 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002569 }
2570
Jack Carterb5cf5902013-04-17 00:18:04 +00002571 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002572 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00002573 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00002574 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00002575 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002576 return Res;
2577 }
2578
2579 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00002580 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2581
Sasa Stankovic06c47802014-04-03 10:37:45 +00002582 // Try to create target expression.
2583 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00002584 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002585
Jack Carterd0bd6422013-04-18 00:41:53 +00002586 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2587 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00002588 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002589 return Res;
2590 }
2591
2592 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002593 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00002594 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00002595 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002596 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002597 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002598 return Expr;
2599}
2600
2601bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2602
2603 switch (Expr->getKind()) {
2604 case MCExpr::Constant:
2605 return true;
2606 case MCExpr::SymbolRef:
2607 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2608 case MCExpr::Binary:
2609 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2610 if (!isEvaluated(BE->getLHS()))
2611 return false;
2612 return isEvaluated(BE->getRHS());
2613 }
2614 case MCExpr::Unary:
2615 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002616 case MCExpr::Target:
2617 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002618 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002619 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002620}
Jack Carterd0bd6422013-04-18 00:41:53 +00002621
Jack Carterb5cf5902013-04-17 00:18:04 +00002622bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002623 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00002624 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002625 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002626 if (Tok.isNot(AsmToken::Identifier))
2627 return true;
2628
Yaron Keren075759a2015-03-30 15:42:36 +00002629 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00002630
Jack Carterd0bd6422013-04-18 00:41:53 +00002631 Parser.Lex(); // Eat the identifier.
2632 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002633 const MCExpr *IdVal;
2634 SMLoc EndLoc;
2635
2636 if (getLexer().getKind() == AsmToken::LParen) {
2637 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002638 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002639 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002640 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002641 const AsmToken &nextTok = Parser.getTok();
2642 if (nextTok.isNot(AsmToken::Identifier))
2643 return true;
2644 Str += "(%";
2645 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002646 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002647 if (getLexer().getKind() != AsmToken::LParen)
2648 return true;
2649 } else
2650 break;
2651 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002652 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002653 return true;
2654
2655 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002656 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002657
2658 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002659 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002660
Jack Carterd0bd6422013-04-18 00:41:53 +00002661 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002662 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002663}
2664
Jack Carterb4dbc172012-09-05 23:34:03 +00002665bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2666 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002667 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002668 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002669 if (ResTy == MatchOperand_Success) {
2670 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002671 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002672 StartLoc = Operand.getStartLoc();
2673 EndLoc = Operand.getEndLoc();
2674
2675 // AFAIK, we only support numeric registers and named GPR's in CFI
2676 // directives.
2677 // Don't worry about eating tokens before failing. Using an unrecognised
2678 // register is a parse error.
2679 if (Operand.isGPRAsmReg()) {
2680 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002681 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002682 }
2683
2684 return (RegNo == (unsigned)-1);
2685 }
2686
2687 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002688 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002689}
2690
Jack Carterb5cf5902013-04-17 00:18:04 +00002691bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002692 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00002693 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002694 bool Result = true;
2695
2696 while (getLexer().getKind() == AsmToken::LParen)
2697 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002698
Jack Carterd0bd6422013-04-18 00:41:53 +00002699 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002700 default:
2701 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002702 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002703 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002704 case AsmToken::Integer:
2705 case AsmToken::Minus:
2706 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002707 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002708 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002709 else
2710 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002711 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002712 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002713 break;
Jack Carter873c7242013-01-12 01:03:14 +00002714 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002715 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002716 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002717 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002718}
2719
David Blaikie960ea3f2014-06-08 16:18:35 +00002720MipsAsmParser::OperandMatchResultTy
2721MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002722 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002723 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002724 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002725 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002726 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002727 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002728 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002729 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002730
Jack Carterb5cf5902013-04-17 00:18:04 +00002731 if (getLexer().getKind() == AsmToken::LParen) {
2732 Parser.Lex();
2733 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002734 }
2735
Jack Carterb5cf5902013-04-17 00:18:04 +00002736 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002737 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002738 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002739
Jack Carterd0bd6422013-04-18 00:41:53 +00002740 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002741 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002742 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2743 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002744 SMLoc E =
2745 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002746 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002747 return MatchOperand_Success;
2748 }
2749 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002750 SMLoc E =
2751 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002752
Jack Carterd0bd6422013-04-18 00:41:53 +00002753 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002754 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002755 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002756 S, E, *this);
2757 Operands.push_back(
2758 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002759 return MatchOperand_Success;
2760 }
2761 Error(Parser.getTok().getLoc(), "'(' expected");
2762 return MatchOperand_ParseFail;
2763 }
2764
Jack Carterd0bd6422013-04-18 00:41:53 +00002765 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002766 }
2767
Toma Tabacu13964452014-09-04 13:23:44 +00002768 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002769 if (Res != MatchOperand_Success)
2770 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002771
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002772 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002773 Error(Parser.getTok().getLoc(), "')' expected");
2774 return MatchOperand_ParseFail;
2775 }
2776
Jack Carter873c7242013-01-12 01:03:14 +00002777 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2778
Jack Carterd0bd6422013-04-18 00:41:53 +00002779 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002780
Craig Topper062a2ba2014-04-25 05:30:21 +00002781 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002782 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002783
Jack Carterd0bd6422013-04-18 00:41:53 +00002784 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002785 std::unique_ptr<MipsOperand> op(
2786 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002787 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002788 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002789 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002790 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002791 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2792 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00002793 if (IdVal->evaluateAsAbsolute(Imm))
2794 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002795 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002796 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00002797 getContext());
2798 }
2799
David Blaikie960ea3f2014-06-08 16:18:35 +00002800 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002801 return MatchOperand_Success;
2802}
2803
David Blaikie960ea3f2014-06-08 16:18:35 +00002804bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002805 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00002806 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00002807 if (Sym) {
2808 SMLoc S = Parser.getTok().getLoc();
2809 const MCExpr *Expr;
2810 if (Sym->isVariable())
2811 Expr = Sym->getVariableValue();
2812 else
2813 return false;
2814 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002815 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002816 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002817 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002818 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002819 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002820 if (ResTy == MatchOperand_Success) {
2821 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002822 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002823 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002824 llvm_unreachable("Should never ParseFail");
2825 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002826 }
2827 } else if (Expr->getKind() == MCExpr::Constant) {
2828 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002829 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002830 Operands.push_back(
2831 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002832 return true;
2833 }
2834 }
2835 return false;
2836}
Jack Carterd0bd6422013-04-18 00:41:53 +00002837
Jack Carter873c7242013-01-12 01:03:14 +00002838MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002839MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002840 StringRef Identifier,
2841 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002842 int Index = matchCPURegisterName(Identifier);
2843 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002844 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002845 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2846 return MatchOperand_Success;
2847 }
2848
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002849 Index = matchHWRegsRegisterName(Identifier);
2850 if (Index != -1) {
2851 Operands.push_back(MipsOperand::createHWRegsReg(
2852 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2853 return MatchOperand_Success;
2854 }
2855
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002856 Index = matchFPURegisterName(Identifier);
2857 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002858 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002859 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2860 return MatchOperand_Success;
2861 }
2862
2863 Index = matchFCCRegisterName(Identifier);
2864 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002865 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002866 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2867 return MatchOperand_Success;
2868 }
2869
2870 Index = matchACRegisterName(Identifier);
2871 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002872 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002873 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2874 return MatchOperand_Success;
2875 }
2876
2877 Index = matchMSA128RegisterName(Identifier);
2878 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002879 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002880 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2881 return MatchOperand_Success;
2882 }
2883
2884 Index = matchMSA128CtrlRegisterName(Identifier);
2885 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002886 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002887 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2888 return MatchOperand_Success;
2889 }
2890
2891 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002892}
2893
2894MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002895MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002896 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00002897 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002898
2899 if (Token.is(AsmToken::Identifier)) {
2900 DEBUG(dbgs() << ".. identifier\n");
2901 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002902 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002903 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002904 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002905 } else if (Token.is(AsmToken::Integer)) {
2906 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002907 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002908 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2909 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002910 return MatchOperand_Success;
2911 }
2912
2913 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2914
2915 return MatchOperand_NoMatch;
2916}
2917
David Blaikie960ea3f2014-06-08 16:18:35 +00002918MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002919MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002920 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002921 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002922
2923 auto Token = Parser.getTok();
2924
2925 SMLoc S = Token.getLoc();
2926
2927 if (Token.isNot(AsmToken::Dollar)) {
2928 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2929 if (Token.is(AsmToken::Identifier)) {
2930 if (searchSymbolAlias(Operands))
2931 return MatchOperand_Success;
2932 }
2933 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2934 return MatchOperand_NoMatch;
2935 }
2936 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002937
Toma Tabacu13964452014-09-04 13:23:44 +00002938 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002939 if (ResTy == MatchOperand_Success) {
2940 Parser.Lex(); // $
2941 Parser.Lex(); // identifier
2942 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002943 return ResTy;
2944}
2945
2946MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002947MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002948 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002949 switch (getLexer().getKind()) {
2950 default:
2951 return MatchOperand_NoMatch;
2952 case AsmToken::LParen:
2953 case AsmToken::Minus:
2954 case AsmToken::Plus:
2955 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002956 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002957 case AsmToken::String:
2958 break;
2959 }
2960
2961 const MCExpr *IdVal;
2962 SMLoc S = Parser.getTok().getLoc();
2963 if (getParser().parseExpression(IdVal))
2964 return MatchOperand_ParseFail;
2965
2966 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2967 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2968 return MatchOperand_Success;
2969}
2970
David Blaikie960ea3f2014-06-08 16:18:35 +00002971MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002972MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002973 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002974 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002975
2976 SMLoc S = getLexer().getLoc();
2977
2978 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002979 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002980 if (ResTy != MatchOperand_NoMatch)
2981 return ResTy;
2982
Daniel Sanders315386c2014-04-01 10:40:14 +00002983 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002984 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002985 if (ResTy != MatchOperand_NoMatch)
2986 return ResTy;
2987
Daniel Sandersffd84362014-04-01 10:41:48 +00002988 const MCExpr *Expr = nullptr;
2989 if (Parser.parseExpression(Expr)) {
2990 // We have no way of knowing if a symbol was consumed so we must ParseFail
2991 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002992 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002993 Operands.push_back(
2994 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002995 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002996}
2997
Vladimir Medic2b953d02013-10-01 09:48:56 +00002998MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002999MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003000 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00003001 const MCExpr *IdVal;
3002 // If the first token is '$' we may have register operand.
3003 if (Parser.getTok().is(AsmToken::Dollar))
3004 return MatchOperand_NoMatch;
3005 SMLoc S = Parser.getTok().getLoc();
3006 if (getParser().parseExpression(IdVal))
3007 return MatchOperand_ParseFail;
3008 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00003009 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00003010 int64_t Val = MCE->getValue();
3011 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3012 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003013 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00003014 return MatchOperand_Success;
3015}
3016
Matheus Almeida779c5932013-11-18 12:32:49 +00003017MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003018MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003019 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00003020 switch (getLexer().getKind()) {
3021 default:
3022 return MatchOperand_NoMatch;
3023 case AsmToken::LParen:
3024 case AsmToken::Plus:
3025 case AsmToken::Minus:
3026 case AsmToken::Integer:
3027 break;
3028 }
3029
3030 const MCExpr *Expr;
3031 SMLoc S = Parser.getTok().getLoc();
3032
3033 if (getParser().parseExpression(Expr))
3034 return MatchOperand_ParseFail;
3035
3036 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003037 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00003038 Error(S, "expected immediate value");
3039 return MatchOperand_ParseFail;
3040 }
3041
3042 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
3043 // and because the CPU always adds one to the immediate field, the allowed
3044 // range becomes 1..4. We'll only check the range here and will deal
3045 // with the addition/subtraction when actually decoding/encoding
3046 // the instruction.
3047 if (Val < 1 || Val > 4) {
3048 Error(S, "immediate not in range (1..4)");
3049 return MatchOperand_ParseFail;
3050 }
3051
Jack Carter3b2c96e2014-01-22 23:31:38 +00003052 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003053 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00003054 return MatchOperand_Success;
3055}
3056
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00003057MipsAsmParser::OperandMatchResultTy
3058MipsAsmParser::parseRegisterList(OperandVector &Operands) {
3059 MCAsmParser &Parser = getParser();
3060 SmallVector<unsigned, 10> Regs;
3061 unsigned RegNo;
3062 unsigned PrevReg = Mips::NoRegister;
3063 bool RegRange = false;
3064 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3065
3066 if (Parser.getTok().isNot(AsmToken::Dollar))
3067 return MatchOperand_ParseFail;
3068
3069 SMLoc S = Parser.getTok().getLoc();
3070 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
3071 SMLoc E = getLexer().getLoc();
3072 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
3073 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
3074 if (RegRange) {
3075 // Remove last register operand because registers from register range
3076 // should be inserted first.
3077 if (RegNo == Mips::RA) {
3078 Regs.push_back(RegNo);
3079 } else {
3080 unsigned TmpReg = PrevReg + 1;
3081 while (TmpReg <= RegNo) {
3082 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
3083 Error(E, "invalid register operand");
3084 return MatchOperand_ParseFail;
3085 }
3086
3087 PrevReg = TmpReg;
3088 Regs.push_back(TmpReg++);
3089 }
3090 }
3091
3092 RegRange = false;
3093 } else {
3094 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
3095 (RegNo != Mips::RA)) {
3096 Error(E, "$16 or $31 expected");
3097 return MatchOperand_ParseFail;
3098 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
3099 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3100 Error(E, "invalid register operand");
3101 return MatchOperand_ParseFail;
3102 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
3103 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3104 Error(E, "consecutive register numbers expected");
3105 return MatchOperand_ParseFail;
3106 }
3107
3108 Regs.push_back(RegNo);
3109 }
3110
3111 if (Parser.getTok().is(AsmToken::Minus))
3112 RegRange = true;
3113
3114 if (!Parser.getTok().isNot(AsmToken::Minus) &&
3115 !Parser.getTok().isNot(AsmToken::Comma)) {
3116 Error(E, "',' or '-' expected");
3117 return MatchOperand_ParseFail;
3118 }
3119
3120 Lex(); // Consume comma or minus
3121 if (Parser.getTok().isNot(AsmToken::Dollar))
3122 break;
3123
3124 PrevReg = RegNo;
3125 }
3126
3127 SMLoc E = Parser.getTok().getLoc();
3128 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3129 parseMemOperand(Operands);
3130 return MatchOperand_Success;
3131}
3132
Zoran Jovanovic2deca342014-12-16 14:59:10 +00003133MipsAsmParser::OperandMatchResultTy
3134MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
3135 MCAsmParser &Parser = getParser();
3136
3137 SMLoc S = Parser.getTok().getLoc();
3138 if (parseAnyRegister(Operands) != MatchOperand_Success)
3139 return MatchOperand_ParseFail;
3140
3141 SMLoc E = Parser.getTok().getLoc();
3142 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
3143 unsigned Reg = Op.getGPR32Reg();
3144 Operands.pop_back();
3145 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
3146 return MatchOperand_Success;
3147}
3148
Zoran Jovanovic41688672015-02-10 16:36:20 +00003149MipsAsmParser::OperandMatchResultTy
3150MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
3151 MCAsmParser &Parser = getParser();
3152 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3153 SmallVector<unsigned, 10> Regs;
3154
3155 if (Parser.getTok().isNot(AsmToken::Dollar))
3156 return MatchOperand_ParseFail;
3157
3158 SMLoc S = Parser.getTok().getLoc();
3159
3160 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3161 return MatchOperand_ParseFail;
3162
3163 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3164 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3165 Regs.push_back(RegNo);
3166
3167 SMLoc E = Parser.getTok().getLoc();
3168 if (Parser.getTok().isNot(AsmToken::Comma)) {
3169 Error(E, "',' expected");
3170 return MatchOperand_ParseFail;
3171 }
3172
3173 // Remove comma.
3174 Parser.Lex();
3175
3176 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3177 return MatchOperand_ParseFail;
3178
3179 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3180 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3181 Regs.push_back(RegNo);
3182
3183 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3184
3185 return MatchOperand_Success;
3186}
3187
Jack Carterdc1e35d2012-09-06 20:00:02 +00003188MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
3189
Vladimir Medic4c299852013-11-06 11:27:05 +00003190 MCSymbolRefExpr::VariantKind VK =
3191 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
3192 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
3193 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
3194 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
3195 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
3196 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
3197 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
3198 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
3199 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
3200 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
3201 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
3202 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
3203 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
3204 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
3205 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
3206 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
3207 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
3208 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00003209 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
3210 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
3211 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
3212 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
3213 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
3214 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00003215 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
3216 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00003217 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003218
Matheus Almeida2852af82014-04-22 10:15:54 +00003219 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00003220
Jack Carterdc1e35d2012-09-06 20:00:02 +00003221 return VK;
3222}
Jack Cartera63b16a2012-09-07 00:23:42 +00003223
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003224/// Sometimes (i.e. load/stores) the operand may be followed immediately by
3225/// either this.
3226/// ::= '(', register, ')'
3227/// handle it before we iterate so we don't get tripped up by the lack of
3228/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003229bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003230 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003231 if (getLexer().is(AsmToken::LParen)) {
3232 Operands.push_back(
3233 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
3234 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003235 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003236 SMLoc Loc = getLexer().getLoc();
3237 Parser.eatToEndOfStatement();
3238 return Error(Loc, "unexpected token in argument list");
3239 }
3240 if (Parser.getTok().isNot(AsmToken::RParen)) {
3241 SMLoc Loc = getLexer().getLoc();
3242 Parser.eatToEndOfStatement();
3243 return Error(Loc, "unexpected token, expected ')'");
3244 }
3245 Operands.push_back(
3246 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
3247 Parser.Lex();
3248 }
3249 return false;
3250}
3251
3252/// Sometimes (i.e. in MSA) the operand may be followed immediately by
3253/// either one of these.
3254/// ::= '[', register, ']'
3255/// ::= '[', integer, ']'
3256/// handle it before we iterate so we don't get tripped up by the lack of
3257/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003258bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00003259 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003260 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003261 if (getLexer().is(AsmToken::LBrac)) {
3262 Operands.push_back(
3263 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
3264 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003265 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003266 SMLoc Loc = getLexer().getLoc();
3267 Parser.eatToEndOfStatement();
3268 return Error(Loc, "unexpected token in argument list");
3269 }
3270 if (Parser.getTok().isNot(AsmToken::RBrac)) {
3271 SMLoc Loc = getLexer().getLoc();
3272 Parser.eatToEndOfStatement();
3273 return Error(Loc, "unexpected token, expected ']'");
3274 }
3275 Operands.push_back(
3276 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
3277 Parser.Lex();
3278 }
3279 return false;
3280}
3281
David Blaikie960ea3f2014-06-08 16:18:35 +00003282bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
3283 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003284 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003285 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003286
3287 // We have reached first instruction, module directive are now forbidden.
3288 getTargetStreamer().forbidModuleDirective();
3289
Vladimir Medic74593e62013-07-17 15:00:42 +00003290 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00003291 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00003292 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00003293 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00003294 }
Vladimir Medic64828a12013-07-16 10:07:14 +00003295 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003296 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003297
3298 // Read the remaining operands.
3299 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3300 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003301 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003302 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003303 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003304 return Error(Loc, "unexpected token in argument list");
3305 }
Toma Tabacu13964452014-09-04 13:23:44 +00003306 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003307 return true;
3308 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00003309
Jack Carterd0bd6422013-04-18 00:41:53 +00003310 while (getLexer().is(AsmToken::Comma)) {
3311 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00003312 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003313 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003314 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003315 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003316 return Error(Loc, "unexpected token in argument list");
3317 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003318 // Parse bracket and parenthesis suffixes before we iterate
3319 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00003320 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003321 return true;
3322 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00003323 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003324 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003325 }
3326 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003327 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3328 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003329 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003330 return Error(Loc, "unexpected token in argument list");
3331 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003332 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00003333 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00003334}
3335
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003336bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003337 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003338 SMLoc Loc = getLexer().getLoc();
3339 Parser.eatToEndOfStatement();
3340 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00003341}
3342
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003343bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003344 return Error(Loc, ErrorMsg);
3345}
3346
Jack Carter0b744b32012-10-04 02:29:46 +00003347bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003348 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003349 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00003350
3351 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00003352 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00003353
3354 Parser.Lex(); // Eat "noat".
3355
Jack Carterd0bd6422013-04-18 00:41:53 +00003356 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003357 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003358 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003359 return false;
3360 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003361
3362 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003363 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003364 return false;
3365}
Jack Carterd0bd6422013-04-18 00:41:53 +00003366
Jack Carter0b744b32012-10-04 02:29:46 +00003367bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00003368 // Line can be: ".set at", which sets $at to $1
3369 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00003370 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00003371 Parser.Lex(); // Eat "at".
3372
Jack Carter0b744b32012-10-04 02:29:46 +00003373 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003374 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00003375 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00003376
3377 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003378 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003379 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00003380 }
3381
3382 if (getLexer().isNot(AsmToken::Equal)) {
3383 reportParseError("unexpected token, expected equals sign");
3384 return false;
3385 }
3386 Parser.Lex(); // Eat "=".
3387
3388 if (getLexer().isNot(AsmToken::Dollar)) {
3389 if (getLexer().is(AsmToken::EndOfStatement)) {
3390 reportParseError("no register specified");
3391 return false;
3392 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00003393 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00003394 return false;
3395 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003396 }
3397 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00003398
Toma Tabacu16a74492015-02-13 10:30:57 +00003399 // Find out what "reg" is.
3400 unsigned AtRegNo;
3401 const AsmToken &Reg = Parser.getTok();
3402 if (Reg.is(AsmToken::Identifier)) {
3403 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
3404 } else if (Reg.is(AsmToken::Integer)) {
3405 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00003406 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00003407 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00003408 return false;
3409 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003410
3411 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00003412 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003413 reportParseError("invalid register");
3414 return false;
3415 }
3416 Parser.Lex(); // Eat "reg".
3417
3418 // If this is not the end of the statement, report an error.
3419 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3420 reportParseError("unexpected token, expected end of statement");
3421 return false;
3422 }
3423
3424 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
3425
3426 Parser.Lex(); // Consume the EndOfStatement.
3427 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003428}
3429
3430bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003431 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003432 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003433 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003434 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003435 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003436 return false;
3437 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003438 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00003439 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003440 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003441 return false;
3442}
3443
3444bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003445 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003446 Parser.Lex();
3447 // If this is not the end of the statement, report an error.
3448 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003449 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003450 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003451 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003452 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00003453 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003454 Parser.Lex(); // Consume the EndOfStatement.
3455 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003456}
3457
3458bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003459 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003460 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003461 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003462 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003463 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003464 return false;
3465 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003466 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00003467 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003468 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003469 return false;
3470}
3471
3472bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003473 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003474 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003475 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003476 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003477 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003478 return false;
3479 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003480 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00003481 reportParseError("`noreorder' must be set before `nomacro'");
3482 return false;
3483 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003484 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00003485 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003486 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003487 return false;
3488}
Jack Carterd76b2372013-03-21 21:44:16 +00003489
Daniel Sanders44934432014-08-07 12:03:36 +00003490bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003491 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003492 Parser.Lex();
3493
3494 // If this is not the end of the statement, report an error.
3495 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003496 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003497
3498 setFeatureBits(Mips::FeatureMSA, "msa");
3499 getTargetStreamer().emitDirectiveSetMsa();
3500 return false;
3501}
3502
3503bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003504 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003505 Parser.Lex();
3506
3507 // If this is not the end of the statement, report an error.
3508 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003509 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003510
3511 clearFeatureBits(Mips::FeatureMSA, "msa");
3512 getTargetStreamer().emitDirectiveSetNoMsa();
3513 return false;
3514}
3515
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003516bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003517 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003518 Parser.Lex(); // Eat "nodsp".
3519
3520 // If this is not the end of the statement, report an error.
3521 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3522 reportParseError("unexpected token, expected end of statement");
3523 return false;
3524 }
3525
3526 clearFeatureBits(Mips::FeatureDSP, "dsp");
3527 getTargetStreamer().emitDirectiveSetNoDsp();
3528 return false;
3529}
3530
Toma Tabacucc2502d2014-11-04 17:18:07 +00003531bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003532 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003533 Parser.Lex(); // Eat "mips16".
3534
Jack Carter39536722014-01-22 23:08:42 +00003535 // If this is not the end of the statement, report an error.
3536 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003537 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00003538 return false;
3539 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00003540
3541 setFeatureBits(Mips::FeatureMips16, "mips16");
3542 getTargetStreamer().emitDirectiveSetMips16();
3543 Parser.Lex(); // Consume the EndOfStatement.
3544 return false;
3545}
3546
3547bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003548 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003549 Parser.Lex(); // Eat "nomips16".
3550
3551 // If this is not the end of the statement, report an error.
3552 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3553 reportParseError("unexpected token, expected end of statement");
3554 return false;
3555 }
3556
3557 clearFeatureBits(Mips::FeatureMips16, "mips16");
3558 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00003559 Parser.Lex(); // Consume the EndOfStatement.
3560 return false;
3561}
3562
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003563bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003564 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003565 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003566 // Line can be: .set fp=32
3567 // .set fp=xx
3568 // .set fp=64
3569 Parser.Lex(); // Eat fp token
3570 AsmToken Tok = Parser.getTok();
3571 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003572 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003573 return false;
3574 }
3575 Parser.Lex(); // Eat '=' token.
3576 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003577
3578 if (!parseFpABIValue(FpAbiVal, ".set"))
3579 return false;
3580
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003581 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003582 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003583 return false;
3584 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003585 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003586 Parser.Lex(); // Consume the EndOfStatement.
3587 return false;
3588}
3589
Toma Tabacu9db22db2014-09-09 10:15:38 +00003590bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003591 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003592 SMLoc Loc = getLexer().getLoc();
3593
3594 Parser.Lex();
3595 if (getLexer().isNot(AsmToken::EndOfStatement))
3596 return reportParseError("unexpected token, expected end of statement");
3597
3598 // Always keep an element on the options "stack" to prevent the user
3599 // from changing the initial options. This is how we remember them.
3600 if (AssemblerOptions.size() == 2)
3601 return reportParseError(Loc, ".set pop with no .set push");
3602
3603 AssemblerOptions.pop_back();
3604 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
3605
3606 getTargetStreamer().emitDirectiveSetPop();
3607 return false;
3608}
3609
3610bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003611 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003612 Parser.Lex();
3613 if (getLexer().isNot(AsmToken::EndOfStatement))
3614 return reportParseError("unexpected token, expected end of statement");
3615
3616 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00003617 AssemblerOptions.push_back(
3618 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00003619
3620 getTargetStreamer().emitDirectiveSetPush();
3621 return false;
3622}
3623
Jack Carterd76b2372013-03-21 21:44:16 +00003624bool MipsAsmParser::parseSetAssignment() {
3625 StringRef Name;
3626 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00003627 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00003628
3629 if (Parser.parseIdentifier(Name))
3630 reportParseError("expected identifier after .set");
3631
3632 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003633 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00003634 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00003635
Jack Carter3b2c96e2014-01-22 23:31:38 +00003636 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00003637 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00003638
Jim Grosbach6f482002015-05-18 18:43:14 +00003639 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00003640 Sym->setVariableValue(Value);
3641
3642 return false;
3643}
Jack Carterd0bd6422013-04-18 00:41:53 +00003644
Toma Tabacu26647792014-09-09 12:52:14 +00003645bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003646 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00003647 Parser.Lex();
3648 if (getLexer().isNot(AsmToken::EndOfStatement))
3649 return reportParseError("unexpected token, expected end of statement");
3650
3651 // Reset assembler options to their initial values.
3652 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
3653 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
3654
3655 getTargetStreamer().emitDirectiveSetMips0();
3656 return false;
3657}
3658
Toma Tabacu85618b32014-08-19 14:22:52 +00003659bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003660 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00003661 Parser.Lex();
3662 if (getLexer().isNot(AsmToken::Equal))
3663 return reportParseError("unexpected token, expected equals sign");
3664
3665 Parser.Lex();
3666 StringRef Arch;
3667 if (Parser.parseIdentifier(Arch))
3668 return reportParseError("expected arch identifier");
3669
3670 StringRef ArchFeatureName =
3671 StringSwitch<StringRef>(Arch)
3672 .Case("mips1", "mips1")
3673 .Case("mips2", "mips2")
3674 .Case("mips3", "mips3")
3675 .Case("mips4", "mips4")
3676 .Case("mips5", "mips5")
3677 .Case("mips32", "mips32")
3678 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003679 .Case("mips32r3", "mips32r3")
3680 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003681 .Case("mips32r6", "mips32r6")
3682 .Case("mips64", "mips64")
3683 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003684 .Case("mips64r3", "mips64r3")
3685 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003686 .Case("mips64r6", "mips64r6")
3687 .Case("cnmips", "cnmips")
3688 .Case("r4000", "mips3") // This is an implementation of Mips3.
3689 .Default("");
3690
3691 if (ArchFeatureName.empty())
3692 return reportParseError("unsupported architecture");
3693
3694 selectArch(ArchFeatureName);
3695 getTargetStreamer().emitDirectiveSetArch(Arch);
3696 return false;
3697}
3698
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003699bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003700 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003701 Parser.Lex();
3702 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003703 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003704
Matheus Almeida2852af82014-04-22 10:15:54 +00003705 switch (Feature) {
3706 default:
3707 llvm_unreachable("Unimplemented feature");
3708 case Mips::FeatureDSP:
3709 setFeatureBits(Mips::FeatureDSP, "dsp");
3710 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003711 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003712 case Mips::FeatureMicroMips:
3713 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003714 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003715 case Mips::FeatureMips1:
3716 selectArch("mips1");
3717 getTargetStreamer().emitDirectiveSetMips1();
3718 break;
3719 case Mips::FeatureMips2:
3720 selectArch("mips2");
3721 getTargetStreamer().emitDirectiveSetMips2();
3722 break;
3723 case Mips::FeatureMips3:
3724 selectArch("mips3");
3725 getTargetStreamer().emitDirectiveSetMips3();
3726 break;
3727 case Mips::FeatureMips4:
3728 selectArch("mips4");
3729 getTargetStreamer().emitDirectiveSetMips4();
3730 break;
3731 case Mips::FeatureMips5:
3732 selectArch("mips5");
3733 getTargetStreamer().emitDirectiveSetMips5();
3734 break;
3735 case Mips::FeatureMips32:
3736 selectArch("mips32");
3737 getTargetStreamer().emitDirectiveSetMips32();
3738 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003739 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003740 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003741 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003742 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003743 case Mips::FeatureMips32r3:
3744 selectArch("mips32r3");
3745 getTargetStreamer().emitDirectiveSetMips32R3();
3746 break;
3747 case Mips::FeatureMips32r5:
3748 selectArch("mips32r5");
3749 getTargetStreamer().emitDirectiveSetMips32R5();
3750 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003751 case Mips::FeatureMips32r6:
3752 selectArch("mips32r6");
3753 getTargetStreamer().emitDirectiveSetMips32R6();
3754 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003755 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003756 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00003757 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003758 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003759 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003760 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003761 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003762 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003763 case Mips::FeatureMips64r3:
3764 selectArch("mips64r3");
3765 getTargetStreamer().emitDirectiveSetMips64R3();
3766 break;
3767 case Mips::FeatureMips64r5:
3768 selectArch("mips64r5");
3769 getTargetStreamer().emitDirectiveSetMips64R5();
3770 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003771 case Mips::FeatureMips64r6:
3772 selectArch("mips64r6");
3773 getTargetStreamer().emitDirectiveSetMips64R6();
3774 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003775 }
3776 return false;
3777}
3778
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003779bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003780 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003781 if (getLexer().isNot(AsmToken::Comma)) {
3782 SMLoc Loc = getLexer().getLoc();
3783 Parser.eatToEndOfStatement();
3784 return Error(Loc, ErrorStr);
3785 }
3786
Matheus Almeida2852af82014-04-22 10:15:54 +00003787 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003788 return true;
3789}
3790
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003791bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003792 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00003793 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003794
Toma Tabacudde4c462014-11-06 10:02:45 +00003795 if (inMips16Mode()) {
3796 reportParseError(".cpload is not supported in Mips16 mode");
3797 return false;
3798 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003799
David Blaikie960ea3f2014-06-08 16:18:35 +00003800 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00003801 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003802 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3803 reportParseError("expected register containing function address");
3804 return false;
3805 }
3806
David Blaikie960ea3f2014-06-08 16:18:35 +00003807 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
3808 if (!RegOpnd.isGPRAsmReg()) {
3809 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003810 return false;
3811 }
3812
Toma Tabacudde4c462014-11-06 10:02:45 +00003813 // If this is not the end of the statement, report an error.
3814 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3815 reportParseError("unexpected token, expected end of statement");
3816 return false;
3817 }
3818
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003819 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003820 return false;
3821}
3822
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003823bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003824 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003825 unsigned FuncReg;
3826 unsigned Save;
3827 bool SaveIsReg = true;
3828
Matheus Almeida7e815762014-06-18 13:08:59 +00003829 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003830 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003831 if (ResTy == MatchOperand_NoMatch) {
3832 reportParseError("expected register containing function address");
3833 Parser.eatToEndOfStatement();
3834 return false;
3835 }
3836
3837 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3838 if (!FuncRegOpnd.isGPRAsmReg()) {
3839 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3840 Parser.eatToEndOfStatement();
3841 return false;
3842 }
3843
3844 FuncReg = FuncRegOpnd.getGPR32Reg();
3845 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003846
Toma Tabacu65f10572014-09-16 15:00:52 +00003847 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003848 return true;
3849
Toma Tabacu13964452014-09-04 13:23:44 +00003850 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003851 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003852 const AsmToken &Tok = Parser.getTok();
3853 if (Tok.is(AsmToken::Integer)) {
3854 Save = Tok.getIntVal();
3855 SaveIsReg = false;
3856 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003857 } else {
3858 reportParseError("expected save register or stack offset");
3859 Parser.eatToEndOfStatement();
3860 return false;
3861 }
3862 } else {
3863 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3864 if (!SaveOpnd.isGPRAsmReg()) {
3865 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3866 Parser.eatToEndOfStatement();
3867 return false;
3868 }
3869 Save = SaveOpnd.getGPR32Reg();
3870 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003871
Toma Tabacu65f10572014-09-16 15:00:52 +00003872 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003873 return true;
3874
Toma Tabacu8874eac2015-02-18 13:46:53 +00003875 const MCExpr *Expr;
3876 if (Parser.parseExpression(Expr)) {
3877 reportParseError("expected expression");
3878 return false;
3879 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003880
Toma Tabacu8874eac2015-02-18 13:46:53 +00003881 if (Expr->getKind() != MCExpr::SymbolRef) {
3882 reportParseError("expected symbol");
3883 return false;
3884 }
3885 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
3886
3887 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
3888 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003889 return false;
3890}
3891
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003892bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003893 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003894 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3895 const AsmToken &Tok = Parser.getTok();
3896
3897 if (Tok.getString() == "2008") {
3898 Parser.Lex();
3899 getTargetStreamer().emitDirectiveNaN2008();
3900 return false;
3901 } else if (Tok.getString() == "legacy") {
3902 Parser.Lex();
3903 getTargetStreamer().emitDirectiveNaNLegacy();
3904 return false;
3905 }
3906 }
3907 // If we don't recognize the option passed to the .nan
3908 // directive (e.g. no option or unknown option), emit an error.
3909 reportParseError("invalid option in .nan directive");
3910 return false;
3911}
3912
Jack Carter0b744b32012-10-04 02:29:46 +00003913bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003914 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003915 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003916 const AsmToken &Tok = Parser.getTok();
3917
3918 if (Tok.getString() == "noat") {
3919 return parseSetNoAtDirective();
3920 } else if (Tok.getString() == "at") {
3921 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003922 } else if (Tok.getString() == "arch") {
3923 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003924 } else if (Tok.getString() == "fp") {
3925 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003926 } else if (Tok.getString() == "pop") {
3927 return parseSetPopDirective();
3928 } else if (Tok.getString() == "push") {
3929 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003930 } else if (Tok.getString() == "reorder") {
3931 return parseSetReorderDirective();
3932 } else if (Tok.getString() == "noreorder") {
3933 return parseSetNoReorderDirective();
3934 } else if (Tok.getString() == "macro") {
3935 return parseSetMacroDirective();
3936 } else if (Tok.getString() == "nomacro") {
3937 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003938 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00003939 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003940 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003941 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003942 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003943 getTargetStreamer().emitDirectiveSetNoMicroMips();
3944 Parser.eatToEndOfStatement();
3945 return false;
3946 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003947 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003948 } else if (Tok.getString() == "mips0") {
3949 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003950 } else if (Tok.getString() == "mips1") {
3951 return parseSetFeature(Mips::FeatureMips1);
3952 } else if (Tok.getString() == "mips2") {
3953 return parseSetFeature(Mips::FeatureMips2);
3954 } else if (Tok.getString() == "mips3") {
3955 return parseSetFeature(Mips::FeatureMips3);
3956 } else if (Tok.getString() == "mips4") {
3957 return parseSetFeature(Mips::FeatureMips4);
3958 } else if (Tok.getString() == "mips5") {
3959 return parseSetFeature(Mips::FeatureMips5);
3960 } else if (Tok.getString() == "mips32") {
3961 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003962 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003963 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003964 } else if (Tok.getString() == "mips32r3") {
3965 return parseSetFeature(Mips::FeatureMips32r3);
3966 } else if (Tok.getString() == "mips32r5") {
3967 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003968 } else if (Tok.getString() == "mips32r6") {
3969 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003970 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003971 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003972 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003973 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003974 } else if (Tok.getString() == "mips64r3") {
3975 return parseSetFeature(Mips::FeatureMips64r3);
3976 } else if (Tok.getString() == "mips64r5") {
3977 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003978 } else if (Tok.getString() == "mips64r6") {
3979 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003980 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003981 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003982 } else if (Tok.getString() == "nodsp") {
3983 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003984 } else if (Tok.getString() == "msa") {
3985 return parseSetMsaDirective();
3986 } else if (Tok.getString() == "nomsa") {
3987 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003988 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003989 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003990 parseSetAssignment();
3991 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003992 }
Jack Carter07c818d2013-01-25 01:31:34 +00003993
Jack Carter0b744b32012-10-04 02:29:46 +00003994 return true;
3995}
3996
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003997/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003998/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003999bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004000 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004001 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4002 for (;;) {
4003 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004004 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00004005 return true;
4006
4007 getParser().getStreamer().EmitValue(Value, Size);
4008
4009 if (getLexer().is(AsmToken::EndOfStatement))
4010 break;
4011
Jack Carter07c818d2013-01-25 01:31:34 +00004012 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004013 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00004014 Parser.Lex();
4015 }
4016 }
4017
4018 Parser.Lex();
4019 return false;
4020}
4021
Vladimir Medic4c299852013-11-06 11:27:05 +00004022/// parseDirectiveGpWord
4023/// ::= .gpword local_sym
4024bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004025 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004026 const MCExpr *Value;
4027 // EmitGPRel32Value requires an expression, so we are using base class
4028 // method to evaluate the expression.
4029 if (getParser().parseExpression(Value))
4030 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00004031 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00004032
Vladimir Medice10c1122013-11-13 13:18:04 +00004033 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004034 return Error(getLexer().getLoc(),
4035 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00004036 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00004037 return false;
4038}
4039
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004040/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00004041/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004042bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004043 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004044 const MCExpr *Value;
4045 // EmitGPRel64Value requires an expression, so we are using base class
4046 // method to evaluate the expression.
4047 if (getParser().parseExpression(Value))
4048 return true;
4049 getParser().getStreamer().EmitGPRel64Value(Value);
4050
4051 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004052 return Error(getLexer().getLoc(),
4053 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00004054 Parser.Lex(); // Eat EndOfStatement token.
4055 return false;
4056}
4057
Jack Carter0cd3c192014-01-06 23:27:31 +00004058bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004059 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00004060 // Get the option token.
4061 AsmToken Tok = Parser.getTok();
4062 // At the moment only identifiers are supported.
4063 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004064 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00004065 Parser.eatToEndOfStatement();
4066 return false;
4067 }
4068
4069 StringRef Option = Tok.getIdentifier();
4070
4071 if (Option == "pic0") {
4072 getTargetStreamer().emitDirectiveOptionPic0();
4073 Parser.Lex();
4074 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4075 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004076 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004077 Parser.eatToEndOfStatement();
4078 }
4079 return false;
4080 }
4081
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004082 if (Option == "pic2") {
4083 getTargetStreamer().emitDirectiveOptionPic2();
4084 Parser.Lex();
4085 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4086 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004087 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004088 Parser.eatToEndOfStatement();
4089 }
4090 return false;
4091 }
4092
Jack Carter0cd3c192014-01-06 23:27:31 +00004093 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00004094 Warning(Parser.getTok().getLoc(),
4095 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00004096 Parser.eatToEndOfStatement();
4097 return false;
4098}
4099
Toma Tabacu9ca50962015-04-16 09:53:47 +00004100/// parseInsnDirective
4101/// ::= .insn
4102bool MipsAsmParser::parseInsnDirective() {
4103 // If this is not the end of the statement, report an error.
4104 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4105 reportParseError("unexpected token, expected end of statement");
4106 return false;
4107 }
4108
4109 // The actual label marking happens in
4110 // MipsELFStreamer::createPendingLabelRelocs().
4111 getTargetStreamer().emitDirectiveInsn();
4112
4113 getParser().Lex(); // Eat EndOfStatement token.
4114 return false;
4115}
4116
Daniel Sanders7e527422014-07-10 13:38:23 +00004117/// parseDirectiveModule
4118/// ::= .module oddspreg
4119/// ::= .module nooddspreg
4120/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004121bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004122 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004123 MCAsmLexer &Lexer = getLexer();
4124 SMLoc L = Lexer.getLoc();
4125
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004126 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004127 // TODO : get a better message.
4128 reportParseError(".module directive must appear before any code");
4129 return false;
4130 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004131
Toma Tabacuc405c822015-01-23 10:40:19 +00004132 StringRef Option;
4133 if (Parser.parseIdentifier(Option)) {
4134 reportParseError("expected .module option identifier");
4135 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004136 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004137
Toma Tabacuc405c822015-01-23 10:40:19 +00004138 if (Option == "oddspreg") {
4139 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
4140 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4141
4142 // If this is not the end of the statement, report an error.
4143 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4144 reportParseError("unexpected token, expected end of statement");
4145 return false;
4146 }
4147
4148 return false; // parseDirectiveModule has finished successfully.
4149 } else if (Option == "nooddspreg") {
4150 if (!isABI_O32()) {
4151 Error(L, "'.module nooddspreg' requires the O32 ABI");
4152 return false;
4153 }
4154
4155 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
4156 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4157
4158 // If this is not the end of the statement, report an error.
4159 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4160 reportParseError("unexpected token, expected end of statement");
4161 return false;
4162 }
4163
4164 return false; // parseDirectiveModule has finished successfully.
4165 } else if (Option == "fp") {
4166 return parseDirectiveModuleFP();
4167 } else {
4168 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
4169 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004170}
4171
4172/// parseDirectiveModuleFP
4173/// ::= =32
4174/// ::= =xx
4175/// ::= =64
4176bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004177 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004178 MCAsmLexer &Lexer = getLexer();
4179
4180 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004181 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004182 return false;
4183 }
4184 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004185
Daniel Sanders7e527422014-07-10 13:38:23 +00004186 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004187 if (!parseFpABIValue(FpABI, ".module"))
4188 return false;
4189
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004190 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004191 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004192 return false;
4193 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004194
Daniel Sanders7201a3e2014-07-08 10:35:52 +00004195 // Emit appropriate flags.
4196 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00004197 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004198 return false;
4199}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004200
Daniel Sanders7e527422014-07-10 13:38:23 +00004201bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004202 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004203 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004204 MCAsmLexer &Lexer = getLexer();
4205
4206 if (Lexer.is(AsmToken::Identifier)) {
4207 StringRef Value = Parser.getTok().getString();
4208 Parser.Lex();
4209
4210 if (Value != "xx") {
4211 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4212 return false;
4213 }
4214
4215 if (!isABI_O32()) {
4216 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
4217 return false;
4218 }
4219
Daniel Sanders7e527422014-07-10 13:38:23 +00004220 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004221 return true;
4222 }
4223
4224 if (Lexer.is(AsmToken::Integer)) {
4225 unsigned Value = Parser.getTok().getIntVal();
4226 Parser.Lex();
4227
4228 if (Value != 32 && Value != 64) {
4229 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4230 return false;
4231 }
4232
4233 if (Value == 32) {
4234 if (!isABI_O32()) {
4235 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
4236 return false;
4237 }
4238
Daniel Sanders7e527422014-07-10 13:38:23 +00004239 FpABI = MipsABIFlagsSection::FpABIKind::S32;
4240 } else
4241 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004242
Daniel Sanders7e527422014-07-10 13:38:23 +00004243 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004244 }
4245
4246 return false;
4247}
4248
Jack Carter0b744b32012-10-04 02:29:46 +00004249bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004250 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004251 StringRef IDVal = DirectiveID.getString();
4252
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004253 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004254 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00004255 if (IDVal == ".dword") {
4256 parseDataDirective(8, DirectiveID.getLoc());
4257 return false;
4258 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004259 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004260 StringRef SymbolName;
4261
4262 if (Parser.parseIdentifier(SymbolName)) {
4263 reportParseError("expected identifier after .ent");
4264 return false;
4265 }
4266
4267 // There's an undocumented extension that allows an integer to
4268 // follow the name of the procedure which AFAICS is ignored by GAS.
4269 // Example: .ent foo,2
4270 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4271 if (getLexer().isNot(AsmToken::Comma)) {
4272 // Even though we accept this undocumented extension for compatibility
4273 // reasons, the additional integer argument does not actually change
4274 // the behaviour of the '.ent' directive, so we would like to discourage
4275 // its use. We do this by not referring to the extended version in
4276 // error messages which are not directly related to its use.
4277 reportParseError("unexpected token, expected end of statement");
4278 return false;
4279 }
4280 Parser.Lex(); // Eat the comma.
4281 const MCExpr *DummyNumber;
4282 int64_t DummyNumberVal;
4283 // If the user was explicitly trying to use the extended version,
4284 // we still give helpful extension-related error messages.
4285 if (Parser.parseExpression(DummyNumber)) {
4286 reportParseError("expected number after comma");
4287 return false;
4288 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00004289 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004290 reportParseError("expected an absolute expression after comma");
4291 return false;
4292 }
4293 }
4294
4295 // If this is not the end of the statement, report an error.
4296 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4297 reportParseError("unexpected token, expected end of statement");
4298 return false;
4299 }
4300
Jim Grosbach6f482002015-05-18 18:43:14 +00004301 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004302
4303 getTargetStreamer().emitDirectiveEnt(*Sym);
4304 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00004305 return false;
4306 }
4307
Jack Carter07c818d2013-01-25 01:31:34 +00004308 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004309 StringRef SymbolName;
4310
4311 if (Parser.parseIdentifier(SymbolName)) {
4312 reportParseError("expected identifier after .end");
4313 return false;
4314 }
4315
4316 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4317 reportParseError("unexpected token, expected end of statement");
4318 return false;
4319 }
4320
4321 if (CurrentFn == nullptr) {
4322 reportParseError(".end used without .ent");
4323 return false;
4324 }
4325
4326 if ((SymbolName != CurrentFn->getName())) {
4327 reportParseError(".end symbol does not match .ent symbol");
4328 return false;
4329 }
4330
4331 getTargetStreamer().emitDirectiveEnd(SymbolName);
4332 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00004333 return false;
4334 }
4335
Jack Carter07c818d2013-01-25 01:31:34 +00004336 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004337 // .frame $stack_reg, frame_size_in_bytes, $return_reg
4338 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004339 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004340 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4341 reportParseError("expected stack register");
4342 return false;
4343 }
4344
4345 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4346 if (!StackRegOpnd.isGPRAsmReg()) {
4347 reportParseError(StackRegOpnd.getStartLoc(),
4348 "expected general purpose register");
4349 return false;
4350 }
4351 unsigned StackReg = StackRegOpnd.getGPR32Reg();
4352
4353 if (Parser.getTok().is(AsmToken::Comma))
4354 Parser.Lex();
4355 else {
4356 reportParseError("unexpected token, expected comma");
4357 return false;
4358 }
4359
4360 // Parse the frame size.
4361 const MCExpr *FrameSize;
4362 int64_t FrameSizeVal;
4363
4364 if (Parser.parseExpression(FrameSize)) {
4365 reportParseError("expected frame size value");
4366 return false;
4367 }
4368
Jim Grosbach13760bd2015-05-30 01:25:56 +00004369 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004370 reportParseError("frame size not an absolute expression");
4371 return false;
4372 }
4373
4374 if (Parser.getTok().is(AsmToken::Comma))
4375 Parser.Lex();
4376 else {
4377 reportParseError("unexpected token, expected comma");
4378 return false;
4379 }
4380
4381 // Parse the return register.
4382 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00004383 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004384 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4385 reportParseError("expected return register");
4386 return false;
4387 }
4388
4389 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4390 if (!ReturnRegOpnd.isGPRAsmReg()) {
4391 reportParseError(ReturnRegOpnd.getStartLoc(),
4392 "expected general purpose register");
4393 return false;
4394 }
4395
4396 // If this is not the end of the statement, report an error.
4397 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4398 reportParseError("unexpected token, expected end of statement");
4399 return false;
4400 }
4401
4402 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
4403 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00004404 return false;
4405 }
4406
Jack Carter07c818d2013-01-25 01:31:34 +00004407 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00004408 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00004409 }
4410
Daniel Sandersd97a6342014-08-13 10:07:34 +00004411 if (IDVal == ".mask" || IDVal == ".fmask") {
4412 // .mask bitmask, frame_offset
4413 // bitmask: One bit for each register used.
4414 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
4415 // first register is expected to be saved.
4416 // Examples:
4417 // .mask 0x80000000, -4
4418 // .fmask 0x80000000, -4
4419 //
Jack Carterbe332172012-09-07 00:48:02 +00004420
Daniel Sandersd97a6342014-08-13 10:07:34 +00004421 // Parse the bitmask
4422 const MCExpr *BitMask;
4423 int64_t BitMaskVal;
4424
4425 if (Parser.parseExpression(BitMask)) {
4426 reportParseError("expected bitmask value");
4427 return false;
4428 }
4429
Jim Grosbach13760bd2015-05-30 01:25:56 +00004430 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004431 reportParseError("bitmask not an absolute expression");
4432 return false;
4433 }
4434
4435 if (Parser.getTok().is(AsmToken::Comma))
4436 Parser.Lex();
4437 else {
4438 reportParseError("unexpected token, expected comma");
4439 return false;
4440 }
4441
4442 // Parse the frame_offset
4443 const MCExpr *FrameOffset;
4444 int64_t FrameOffsetVal;
4445
4446 if (Parser.parseExpression(FrameOffset)) {
4447 reportParseError("expected frame offset value");
4448 return false;
4449 }
4450
Jim Grosbach13760bd2015-05-30 01:25:56 +00004451 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004452 reportParseError("frame offset not an absolute expression");
4453 return false;
4454 }
4455
4456 // If this is not the end of the statement, report an error.
4457 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4458 reportParseError("unexpected token, expected end of statement");
4459 return false;
4460 }
4461
4462 if (IDVal == ".mask")
4463 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
4464 else
4465 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00004466 return false;
4467 }
4468
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004469 if (IDVal == ".nan")
4470 return parseDirectiveNaN();
4471
Jack Carter07c818d2013-01-25 01:31:34 +00004472 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004473 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00004474 return false;
4475 }
4476
Rafael Espindolab59fb732014-03-28 18:50:26 +00004477 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004478 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004479 return false;
4480 }
4481
Jack Carter07c818d2013-01-25 01:31:34 +00004482 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004483 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00004484 return false;
4485 }
4486
Jack Carter0cd3c192014-01-06 23:27:31 +00004487 if (IDVal == ".option")
4488 return parseDirectiveOption();
4489
4490 if (IDVal == ".abicalls") {
4491 getTargetStreamer().emitDirectiveAbiCalls();
4492 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004493 Error(Parser.getTok().getLoc(),
4494 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004495 // Clear line
4496 Parser.eatToEndOfStatement();
4497 }
4498 return false;
4499 }
4500
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004501 if (IDVal == ".cpsetup")
4502 return parseDirectiveCPSetup();
4503
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004504 if (IDVal == ".module")
4505 return parseDirectiveModule();
4506
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004507 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
4508 return parseInternalDirectiveReallowModule();
4509
Toma Tabacu9ca50962015-04-16 09:53:47 +00004510 if (IDVal == ".insn")
4511 return parseInsnDirective();
4512
Rafael Espindola870c4e92012-01-11 03:56:41 +00004513 return true;
4514}
4515
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004516bool MipsAsmParser::parseInternalDirectiveReallowModule() {
4517 // If this is not the end of the statement, report an error.
4518 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4519 reportParseError("unexpected token, expected end of statement");
4520 return false;
4521 }
4522
4523 getTargetStreamer().reallowModuleDirective();
4524
4525 getParser().Lex(); // Eat EndOfStatement token.
4526 return false;
4527}
4528
Rafael Espindola870c4e92012-01-11 03:56:41 +00004529extern "C" void LLVMInitializeMipsAsmParser() {
4530 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
4531 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
4532 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
4533 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
4534}
Jack Carterb4dbc172012-09-05 23:34:03 +00004535
4536#define GET_REGISTER_MATCHER
4537#define GET_MATCHER_IMPLEMENTATION
4538#include "MipsGenAsmMatcher.inc"