blob: 7750441534cb166aa90fc62135976a40cfbc2ea7 [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 Tabacu465acfd2015-06-09 13:33:26 +000046 MipsAssemblerOptions(const FeatureBitset &Features_) :
Toma Tabacu9db22db2014-09-09 10:15:38 +000047 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 Tabacu465acfd2015-06-09 13:33:26 +000073 const FeatureBitset &getFeatures() const { return Features; }
74 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000075
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 Tabacu465acfd2015-06-09 13:33:26 +000087 FeatureBitset 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 Tabacu674825c2015-06-16 12:16:24 +0000189 bool loadSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
190 bool Is32BitSym, SMLoc IDLoc,
191 SmallVectorImpl<MCInst> &Instructions);
192
Toma Tabacu00e98672015-05-01 12:19:27 +0000193 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000194 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000195
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000196 bool expandLoadAddressImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000197 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000198
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000199 bool expandLoadAddressReg(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000200 SmallVectorImpl<MCInst> &Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000201 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
202 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +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 Tabacue1e460d2015-06-11 10:36:10 +0000211 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc,
212 SmallVectorImpl<MCInst> &Instructions);
213
Toma Tabacu234482a2015-03-16 12:03:39 +0000214 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
215 SmallVectorImpl<MCInst> &Instructions);
216
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000217 void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
218 SmallVectorImpl<MCInst> &Instructions);
219
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000220 bool reportParseError(Twine ErrorMsg);
221 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000222
Jack Carterb5cf5902013-04-17 00:18:04 +0000223 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000224 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000225
Vladimir Medic4c299852013-11-06 11:27:05 +0000226 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000227
228 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000229 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000230 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000231 bool parseSetFeature(uint64_t Feature);
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000232 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000233 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000234 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000235 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000236 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000237 bool parseInsnDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000238
239 bool parseSetAtDirective();
240 bool parseSetNoAtDirective();
241 bool parseSetMacroDirective();
242 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000243 bool parseSetMsaDirective();
244 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000245 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000246 bool parseSetReorderDirective();
247 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000248 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000249 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000250 bool parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000251 bool parseSetPopDirective();
252 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000253 bool parseSetSoftFloatDirective();
254 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000255
Jack Carterd76b2372013-03-21 21:44:16 +0000256 bool parseSetAssignment();
257
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000258 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000259 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000260 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000261 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000262 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000263 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
264 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000265
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000266 bool parseInternalDirectiveReallowModule();
267
Jack Carterdc1e35d2012-09-06 20:00:02 +0000268 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000269
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000270 bool eatComma(StringRef ErrorStr);
271
Jack Carter1ac53222013-02-20 23:11:17 +0000272 int matchCPURegisterName(StringRef Symbol);
273
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000274 int matchHWRegsRegisterName(StringRef Symbol);
275
Jack Carter873c7242013-01-12 01:03:14 +0000276 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000277
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000278 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000279
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000280 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000281
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000282 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000283
Jack Carter5dc8ac92013-09-25 23:50:44 +0000284 int matchMSA128RegisterName(StringRef Name);
285
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000286 int matchMSA128CtrlRegisterName(StringRef Name);
287
Jack Carterd0bd6422013-04-18 00:41:53 +0000288 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000289
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000290 unsigned getGPR(int RegNo);
291
Toma Tabacu89a712b2015-04-15 10:48:56 +0000292 /// Returns the internal register number for the current AT. Also checks if
293 /// the current AT is unavailable (set to $0) and gives an error if it is.
294 /// This should be used in pseudo-instruction expansions which need AT.
295 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000296
297 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000298 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000299
300 // Helper function that checks if the value of a vector index is within the
301 // boundaries of accepted values for each RegisterKind
302 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
303 bool validateMSAIndex(int Val, int RegKind);
304
Daniel Sandersf0df2212014-08-04 12:20:00 +0000305 // Selects a new architecture by updating the FeatureBits with the necessary
306 // info including implied dependencies.
307 // Internally, it clears all the feature bits related to *any* architecture
308 // and selects the new one using the ToggleFeature functionality of the
309 // MCSubtargetInfo object that handles implied dependencies. The reason we
310 // clear all the arch related bits manually is because ToggleFeature only
311 // clears the features that imply the feature being cleared and not the
312 // features implied by the feature being cleared. This is easier to see
313 // with an example:
314 // --------------------------------------------------
315 // | Feature | Implies |
316 // | -------------------------------------------------|
317 // | FeatureMips1 | None |
318 // | FeatureMips2 | FeatureMips1 |
319 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
320 // | FeatureMips4 | FeatureMips3 |
321 // | ... | |
322 // --------------------------------------------------
323 //
324 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
325 // FeatureMipsGP64 | FeatureMips1)
326 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
327 void selectArch(StringRef ArchFeature) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000328 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000329 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
330 STI.setFeatureBits(FeatureBits);
331 setAvailableFeatures(
332 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000333 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000334 }
335
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000336 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000337 if (!(STI.getFeatureBits()[Feature])) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000338 setAvailableFeatures(
339 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000340 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000341 }
342 }
343
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000344 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000345 if (STI.getFeatureBits()[Feature]) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000346 setAvailableFeatures(
347 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000348 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000349 }
350 }
351
Rafael Espindola870c4e92012-01-11 03:56:41 +0000352public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000353 enum MipsMatchResultTy {
354 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
355#define GET_OPERAND_DIAGNOSTIC_TYPES
356#include "MipsGenAsmMatcher.inc"
357#undef GET_OPERAND_DIAGNOSTIC_TYPES
358
359 };
360
Joey Gouly0e76fa72013-09-12 10:28:05 +0000361 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000362 const MCInstrInfo &MII, const MCTargetOptions &Options)
Eric Christophera5762812015-01-26 17:33:46 +0000363 : MCTargetAsmParser(), STI(sti),
364 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
365 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000366 MCAsmParserExtension::Initialize(parser);
367
Toma Tabacu11e14a92015-04-21 11:50:52 +0000368 parser.addAliasForDirective(".asciiz", ".asciz");
369
Jack Carterb4dbc172012-09-05 23:34:03 +0000370 // Initialize the set of available features.
371 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000372
373 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000374 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000375 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000376
377 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000378 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000379 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000380
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000381 getTargetStreamer().updateABIInfo(*this);
382
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000383 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000384 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000385
386 CurrentFn = nullptr;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000387 }
388
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000389 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
390 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
391
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000392 bool isGP64bit() const { return STI.getFeatureBits()[Mips::FeatureGP64Bit]; }
393 bool isFP64bit() const { return STI.getFeatureBits()[Mips::FeatureFP64Bit]; }
Eric Christophera5762812015-01-26 17:33:46 +0000394 const MipsABIInfo &getABI() const { return ABI; }
395 bool isABI_N32() const { return ABI.IsN32(); }
396 bool isABI_N64() const { return ABI.IsN64(); }
397 bool isABI_O32() const { return ABI.IsO32(); }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000398 bool isABI_FPXX() const { return STI.getFeatureBits()[Mips::FeatureFPXX]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000399
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000400 bool useOddSPReg() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000401 return !(STI.getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000402 }
403
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000404 bool inMicroMipsMode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000405 return STI.getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000406 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000407 bool hasMips1() const { return STI.getFeatureBits()[Mips::FeatureMips1]; }
408 bool hasMips2() const { return STI.getFeatureBits()[Mips::FeatureMips2]; }
409 bool hasMips3() const { return STI.getFeatureBits()[Mips::FeatureMips3]; }
410 bool hasMips4() const { return STI.getFeatureBits()[Mips::FeatureMips4]; }
411 bool hasMips5() const { return STI.getFeatureBits()[Mips::FeatureMips5]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000412 bool hasMips32() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000413 return STI.getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000414 }
415 bool hasMips64() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000416 return STI.getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000417 }
418 bool hasMips32r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000419 return STI.getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000420 }
421 bool hasMips64r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000422 return STI.getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000423 }
Daniel Sanders17793142015-02-18 16:24:50 +0000424 bool hasMips32r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000425 return (STI.getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000426 }
427 bool hasMips64r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000428 return (STI.getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000429 }
430 bool hasMips32r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000431 return (STI.getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000432 }
433 bool hasMips64r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000434 return (STI.getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000435 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000436 bool hasMips32r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000437 return STI.getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000438 }
439 bool hasMips64r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000440 return STI.getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000441 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000442
443 bool hasDSP() const { return STI.getFeatureBits()[Mips::FeatureDSP]; }
444 bool hasDSPR2() const { return STI.getFeatureBits()[Mips::FeatureDSPR2]; }
445 bool hasMSA() const { return STI.getFeatureBits()[Mips::FeatureMSA]; }
Kai Nackee0245392015-01-27 19:11:28 +0000446 bool hasCnMips() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000447 return (STI.getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000448 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000449
450 bool inMips16Mode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000451 return STI.getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000452 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000453
Eric Christophere8ae3e32015-05-07 23:10:21 +0000454 bool useSoftFloat() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000455 return STI.getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000456 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000457
Toma Tabacud9d344b2015-04-27 14:05:04 +0000458 /// Warn if RegIndex is the same as the current AT.
459 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000460
461 void warnIfNoMacro(SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000462};
463}
464
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000465namespace {
466
467/// MipsOperand - Instances of this class represent a parsed Mips machine
468/// instruction.
469class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000470public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000471 /// Broad categories of register classes
472 /// The exact class is finalized by the render method.
473 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000474 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000475 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000476 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000477 RegKind_FCC = 4, /// FCC
478 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
479 RegKind_MSACtrl = 16, /// MSA control registers
480 RegKind_COP2 = 32, /// COP2
481 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
482 /// context).
483 RegKind_CCR = 128, /// CCR
484 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000485 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000486
487 /// Potentially any (e.g. $1)
488 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
489 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000490 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000491 };
492
493private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000494 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000495 k_Immediate, /// An immediate (possibly involving symbol references)
496 k_Memory, /// Base + Offset Memory Address
497 k_PhysRegister, /// A physical register from the Mips namespace
498 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000499 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000500 k_RegList, /// A physical register list
501 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000502 } Kind;
503
David Blaikie960ea3f2014-06-08 16:18:35 +0000504public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000505 MipsOperand(KindTy K, MipsAsmParser &Parser)
506 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
507
David Blaikie960ea3f2014-06-08 16:18:35 +0000508private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000509 /// For diagnostics, and checking the assembler temporary
510 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000511
Eric Christopher8996c5d2013-03-15 00:42:55 +0000512 struct Token {
513 const char *Data;
514 unsigned Length;
515 };
516
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000517 struct PhysRegOp {
518 unsigned Num; /// Register Number
519 };
520
521 struct RegIdxOp {
522 unsigned Index; /// Index into the register class
523 RegKind Kind; /// Bitfield of the kinds it could possibly be
524 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000525 };
526
527 struct ImmOp {
528 const MCExpr *Val;
529 };
530
531 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000532 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000533 const MCExpr *Off;
534 };
535
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000536 struct RegListOp {
537 SmallVector<unsigned, 10> *List;
538 };
539
Jack Carterb4dbc172012-09-05 23:34:03 +0000540 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000541 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000542 struct PhysRegOp PhysReg;
543 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000544 struct ImmOp Imm;
545 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000546 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000547 };
548
549 SMLoc StartLoc, EndLoc;
550
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000551 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000552 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
553 const MCRegisterInfo *RegInfo,
554 SMLoc S, SMLoc E,
555 MipsAsmParser &Parser) {
556 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000557 Op->RegIdx.Index = Index;
558 Op->RegIdx.RegInfo = RegInfo;
559 Op->RegIdx.Kind = RegKind;
560 Op->StartLoc = S;
561 Op->EndLoc = E;
562 return Op;
563 }
564
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000565public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000566 /// Coerce the register to GPR32 and return the real register for the current
567 /// target.
568 unsigned getGPR32Reg() const {
569 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000570 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000571 unsigned ClassID = Mips::GPR32RegClassID;
572 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000573 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000574
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000575 /// Coerce the register to GPR32 and return the real register for the current
576 /// target.
577 unsigned getGPRMM16Reg() const {
578 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
579 unsigned ClassID = Mips::GPR32RegClassID;
580 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
581 }
582
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000583 /// Coerce the register to GPR64 and return the real register for the current
584 /// target.
585 unsigned getGPR64Reg() const {
586 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
587 unsigned ClassID = Mips::GPR64RegClassID;
588 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000589 }
590
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000591private:
592 /// Coerce the register to AFGR64 and return the real register for the current
593 /// target.
594 unsigned getAFGR64Reg() const {
595 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
596 if (RegIdx.Index % 2 != 0)
597 AsmParser.Warning(StartLoc, "Float register should be even.");
598 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
599 .getRegister(RegIdx.Index / 2);
600 }
601
602 /// Coerce the register to FGR64 and return the real register for the current
603 /// target.
604 unsigned getFGR64Reg() const {
605 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
606 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
607 .getRegister(RegIdx.Index);
608 }
609
610 /// Coerce the register to FGR32 and return the real register for the current
611 /// target.
612 unsigned getFGR32Reg() const {
613 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
614 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
615 .getRegister(RegIdx.Index);
616 }
617
618 /// Coerce the register to FGRH32 and return the real register for the current
619 /// target.
620 unsigned getFGRH32Reg() const {
621 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
622 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
623 .getRegister(RegIdx.Index);
624 }
625
626 /// Coerce the register to FCC and return the real register for the current
627 /// target.
628 unsigned getFCCReg() const {
629 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
630 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
631 .getRegister(RegIdx.Index);
632 }
633
634 /// Coerce the register to MSA128 and return the real register for the current
635 /// target.
636 unsigned getMSA128Reg() const {
637 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
638 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
639 // identical
640 unsigned ClassID = Mips::MSA128BRegClassID;
641 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
642 }
643
644 /// Coerce the register to MSACtrl and return the real register for the
645 /// current target.
646 unsigned getMSACtrlReg() const {
647 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
648 unsigned ClassID = Mips::MSACtrlRegClassID;
649 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
650 }
651
652 /// Coerce the register to COP2 and return the real register for the
653 /// current target.
654 unsigned getCOP2Reg() const {
655 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
656 unsigned ClassID = Mips::COP2RegClassID;
657 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
658 }
659
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000660 /// Coerce the register to COP3 and return the real register for the
661 /// current target.
662 unsigned getCOP3Reg() const {
663 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
664 unsigned ClassID = Mips::COP3RegClassID;
665 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
666 }
667
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000668 /// Coerce the register to ACC64DSP and return the real register for the
669 /// current target.
670 unsigned getACC64DSPReg() const {
671 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
672 unsigned ClassID = Mips::ACC64DSPRegClassID;
673 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
674 }
675
676 /// Coerce the register to HI32DSP and return the real register for the
677 /// current target.
678 unsigned getHI32DSPReg() const {
679 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
680 unsigned ClassID = Mips::HI32DSPRegClassID;
681 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
682 }
683
684 /// Coerce the register to LO32DSP and return the real register for the
685 /// current target.
686 unsigned getLO32DSPReg() const {
687 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
688 unsigned ClassID = Mips::LO32DSPRegClassID;
689 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
690 }
691
692 /// Coerce the register to CCR and return the real register for the
693 /// current target.
694 unsigned getCCRReg() const {
695 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
696 unsigned ClassID = Mips::CCRRegClassID;
697 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
698 }
699
700 /// Coerce the register to HWRegs and return the real register for the
701 /// current target.
702 unsigned getHWRegsReg() const {
703 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
704 unsigned ClassID = Mips::HWRegsRegClassID;
705 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
706 }
707
708public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000709 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000710 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000711 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000712 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000713 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000714 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000715 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000716 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000717 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000718
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000719 void addRegOperands(MCInst &Inst, unsigned N) const {
720 llvm_unreachable("Use a custom parser instead");
721 }
722
Daniel Sanders21bce302014-04-01 12:35:23 +0000723 /// Render the operand to an MCInst as a GPR32
724 /// Asserts if the wrong number of operands are requested, or the operand
725 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000726 void addGPR32AsmRegOperands(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(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000729 }
730
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000731 void addGPRMM16AsmRegOperands(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()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000734 }
735
Jozef Kolek1904fa22014-11-24 14:25:53 +0000736 void addGPRMM16AsmRegZeroOperands(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()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000739 }
740
Zoran Jovanovic41688672015-02-10 16:36:20 +0000741 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
742 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000743 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000744 }
745
Daniel Sanders21bce302014-04-01 12:35:23 +0000746 /// Render the operand to an MCInst as a GPR64
747 /// Asserts if the wrong number of operands are requested, or the operand
748 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000749 void addGPR64AsmRegOperands(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(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000752 }
753
754 void addAFGR64AsmRegOperands(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(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000757 }
758
759 void addFGR64AsmRegOperands(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(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000762 }
763
764 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
765 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000766 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000767 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000768 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000769 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
770 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000771 }
772
773 void addFGRH32AsmRegOperands(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(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000776 }
777
778 void addFCCAsmRegOperands(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(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000781 }
782
783 void addMSA128AsmRegOperands(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(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000786 }
787
788 void addMSACtrlAsmRegOperands(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(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000791 }
792
793 void addCOP2AsmRegOperands(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(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000796 }
797
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000798 void addCOP3AsmRegOperands(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(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000801 }
802
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000803 void addACC64DSPAsmRegOperands(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(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000806 }
807
808 void addHI32DSPAsmRegOperands(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(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000811 }
812
813 void addLO32DSPAsmRegOperands(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(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000816 }
817
818 void addCCRAsmRegOperands(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(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000821 }
822
823 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
824 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000825 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000826 }
827
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000828 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000829 assert(N == 1 && "Invalid number of operands!");
830 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000831 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000832 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000833
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000834 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000835 assert(N == 2 && "Invalid number of operands!");
836
Jim Grosbache9119e42015-05-13 18:37:00 +0000837 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000838
839 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000840 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000841 }
842
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000843 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
844 assert(N == 2 && "Invalid number of operands!");
845
Jim Grosbache9119e42015-05-13 18:37:00 +0000846 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000847
848 const MCExpr *Expr = getMemOff();
849 addExpr(Inst, Expr);
850 }
851
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000852 void addRegListOperands(MCInst &Inst, unsigned N) const {
853 assert(N == 1 && "Invalid number of operands!");
854
855 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000856 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000857 }
858
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000859 void addRegPairOperands(MCInst &Inst, unsigned N) const {
860 assert(N == 2 && "Invalid number of operands!");
861 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +0000862 Inst.addOperand(MCOperand::createReg(RegNo++));
863 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000864 }
865
Zoran Jovanovic41688672015-02-10 16:36:20 +0000866 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
867 assert(N == 2 && "Invalid number of operands!");
868 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000869 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000870 }
871
Craig Topper56c590a2014-04-29 07:58:02 +0000872 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000873 // As a special case until we sort out the definition of div/divu, pretend
874 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
875 if (isGPRAsmReg() && RegIdx.Index == 0)
876 return true;
877
878 return Kind == k_PhysRegister;
879 }
880 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000881 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000882 bool isConstantImm() const {
883 return isImm() && dyn_cast<MCConstantExpr>(getImm());
884 }
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +0000885 template <unsigned Bits> bool isUImm() const {
886 return isImm() && isConstantImm() && isUInt<Bits>(getConstantImm());
887 }
Craig Topper56c590a2014-04-29 07:58:02 +0000888 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000889 // Note: It's not possible to pretend that other operand kinds are tokens.
890 // The matcher emitter checks tokens first.
891 return Kind == k_Token;
892 }
Craig Topper56c590a2014-04-29 07:58:02 +0000893 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000894 bool isConstantMemOff() const {
895 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
896 }
897 template <unsigned Bits> bool isMemWithSimmOffset() const {
898 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
899 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000900 bool isMemWithGRPMM16Base() const {
901 return isMem() && getMemBase()->isMM16AsmReg();
902 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000903 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
904 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
905 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
906 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000907 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
908 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
909 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
910 && (getMemBase()->getGPR32Reg() == Mips::SP);
911 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000912 bool isRegList16() const {
913 if (!isRegList())
914 return false;
915
916 int Size = RegList.List->size();
917 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
918 RegList.List->back() != Mips::RA)
919 return false;
920
921 int PrevReg = *RegList.List->begin();
922 for (int i = 1; i < Size - 1; i++) {
923 int Reg = (*(RegList.List))[i];
924 if ( Reg != PrevReg + 1)
925 return false;
926 PrevReg = Reg;
927 }
928
929 return true;
930 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000931 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000932 bool isLSAImm() const {
933 if (!isConstantImm())
934 return false;
935 int64_t Val = getConstantImm();
936 return 1 <= Val && Val <= 4;
937 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000938 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +0000939 bool isMovePRegPair() const {
940 if (Kind != k_RegList || RegList.List->size() != 2)
941 return false;
942
943 unsigned R0 = RegList.List->front();
944 unsigned R1 = RegList.List->back();
945
946 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
947 (R0 == Mips::A1 && R1 == Mips::A3) ||
948 (R0 == Mips::A2 && R1 == Mips::A3) ||
949 (R0 == Mips::A0 && R1 == Mips::S5) ||
950 (R0 == Mips::A0 && R1 == Mips::S6) ||
951 (R0 == Mips::A0 && R1 == Mips::A1) ||
952 (R0 == Mips::A0 && R1 == Mips::A2) ||
953 (R0 == Mips::A0 && R1 == Mips::A3))
954 return true;
955
956 return false;
957 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000958
959 StringRef getToken() const {
960 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000961 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000962 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000963 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000964
Craig Topper56c590a2014-04-29 07:58:02 +0000965 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000966 // As a special case until we sort out the definition of div/divu, pretend
967 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
968 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
969 RegIdx.Kind & RegKind_GPR)
970 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000971
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000972 assert(Kind == k_PhysRegister && "Invalid access!");
973 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000974 }
975
Jack Carterb4dbc172012-09-05 23:34:03 +0000976 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000977 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000978 return Imm.Val;
979 }
980
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000981 int64_t getConstantImm() const {
982 const MCExpr *Val = getImm();
983 return static_cast<const MCConstantExpr *>(Val)->getValue();
984 }
985
986 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000987 assert((Kind == k_Memory) && "Invalid access!");
988 return Mem.Base;
989 }
990
991 const MCExpr *getMemOff() const {
992 assert((Kind == k_Memory) && "Invalid access!");
993 return Mem.Off;
994 }
995
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000996 int64_t getConstantMemOff() const {
997 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
998 }
999
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001000 const SmallVectorImpl<unsigned> &getRegList() const {
1001 assert((Kind == k_RegList) && "Invalid access!");
1002 return *(RegList.List);
1003 }
1004
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001005 unsigned getRegPair() const {
1006 assert((Kind == k_RegPair) && "Invalid access!");
1007 return RegIdx.Index;
1008 }
1009
David Blaikie960ea3f2014-06-08 16:18:35 +00001010 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1011 MipsAsmParser &Parser) {
1012 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001013 Op->Tok.Data = Str.data();
1014 Op->Tok.Length = Str.size();
1015 Op->StartLoc = S;
1016 Op->EndLoc = S;
1017 return Op;
1018 }
1019
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001020 /// Create a numeric register (e.g. $1). The exact register remains
1021 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001022 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001023 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001024 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001025 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001026 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001027 }
1028
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001029 /// Create a register that is definitely a GPR.
1030 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001031 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001032 createGPRReg(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_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001035 }
1036
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001037 /// Create a register that is definitely a FGR.
1038 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001039 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001040 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001041 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001042 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1043 }
1044
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001045 /// Create a register that is definitely a HWReg.
1046 /// This is typically only used for named registers such as $hwr_cpunum.
1047 static std::unique_ptr<MipsOperand>
1048 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1049 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1050 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1051 }
1052
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001053 /// Create a register that is definitely an FCC.
1054 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001055 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001056 createFCCReg(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_FCC, RegInfo, S, E, Parser);
1059 }
1060
1061 /// Create a register that is definitely an ACC.
1062 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001063 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001064 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001065 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001066 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1067 }
1068
1069 /// Create a register that is definitely an MSA128.
1070 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001071 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001072 createMSA128Reg(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_MSA128, RegInfo, S, E, Parser);
1075 }
1076
1077 /// Create a register that is definitely an MSACtrl.
1078 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001079 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001080 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001081 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001082 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1083 }
1084
David Blaikie960ea3f2014-06-08 16:18:35 +00001085 static std::unique_ptr<MipsOperand>
1086 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1087 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001088 Op->Imm.Val = Val;
1089 Op->StartLoc = S;
1090 Op->EndLoc = E;
1091 return Op;
1092 }
1093
David Blaikie960ea3f2014-06-08 16:18:35 +00001094 static std::unique_ptr<MipsOperand>
1095 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1096 SMLoc E, MipsAsmParser &Parser) {
1097 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1098 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001099 Op->Mem.Off = Off;
1100 Op->StartLoc = S;
1101 Op->EndLoc = E;
1102 return Op;
1103 }
1104
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001105 static std::unique_ptr<MipsOperand>
1106 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1107 MipsAsmParser &Parser) {
1108 assert (Regs.size() > 0 && "Empty list not allowed");
1109
1110 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001111 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001112 Op->StartLoc = StartLoc;
1113 Op->EndLoc = EndLoc;
1114 return Op;
1115 }
1116
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001117 static std::unique_ptr<MipsOperand>
1118 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1119 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1120 Op->RegIdx.Index = RegNo;
1121 Op->StartLoc = S;
1122 Op->EndLoc = E;
1123 return Op;
1124 }
1125
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001126 bool isGPRAsmReg() const {
1127 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001128 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001129 bool isMM16AsmReg() const {
1130 if (!(isRegIdx() && RegIdx.Kind))
1131 return false;
1132 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1133 || RegIdx.Index == 16 || RegIdx.Index == 17);
1134 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001135 bool isMM16AsmRegZero() const {
1136 if (!(isRegIdx() && RegIdx.Kind))
1137 return false;
1138 return (RegIdx.Index == 0 ||
1139 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1140 RegIdx.Index == 17);
1141 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001142 bool isMM16AsmRegMoveP() const {
1143 if (!(isRegIdx() && RegIdx.Kind))
1144 return false;
1145 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1146 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1147 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001148 bool isFGRAsmReg() const {
1149 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1150 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001151 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001152 bool isHWRegsAsmReg() const {
1153 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001154 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001155 bool isCCRAsmReg() const {
1156 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001157 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001158 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001159 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1160 return false;
1161 if (!AsmParser.hasEightFccRegisters())
1162 return RegIdx.Index == 0;
1163 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001164 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001165 bool isACCAsmReg() const {
1166 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001167 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001168 bool isCOP2AsmReg() const {
1169 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001170 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001171 bool isCOP3AsmReg() const {
1172 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1173 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001174 bool isMSA128AsmReg() const {
1175 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001176 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001177 bool isMSACtrlAsmReg() const {
1178 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001179 }
1180
Jack Carterb4dbc172012-09-05 23:34:03 +00001181 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001182 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001183 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001184 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001185
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001186 virtual ~MipsOperand() {
1187 switch (Kind) {
1188 case k_Immediate:
1189 break;
1190 case k_Memory:
1191 delete Mem.Base;
1192 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001193 case k_RegList:
1194 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001195 case k_PhysRegister:
1196 case k_RegisterIndex:
1197 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001198 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001199 break;
1200 }
1201 }
1202
Craig Topper56c590a2014-04-29 07:58:02 +00001203 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001204 switch (Kind) {
1205 case k_Immediate:
1206 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001207 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001208 OS << ">";
1209 break;
1210 case k_Memory:
1211 OS << "Mem<";
1212 Mem.Base->print(OS);
1213 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001214 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001215 OS << ">";
1216 break;
1217 case k_PhysRegister:
1218 OS << "PhysReg<" << PhysReg.Num << ">";
1219 break;
1220 case k_RegisterIndex:
1221 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1222 break;
1223 case k_Token:
1224 OS << Tok.Data;
1225 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001226 case k_RegList:
1227 OS << "RegList< ";
1228 for (auto Reg : (*RegList.List))
1229 OS << Reg << " ";
1230 OS << ">";
1231 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001232 case k_RegPair:
1233 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1234 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001235 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001236 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001237}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001238} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001239
Jack Carter9e65aa32013-03-22 00:05:30 +00001240namespace llvm {
1241extern const MCInstrDesc MipsInsts[];
1242}
1243static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1244 return MipsInsts[Opcode];
1245}
1246
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001247static bool hasShortDelaySlot(unsigned Opcode) {
1248 switch (Opcode) {
1249 case Mips::JALS_MM:
1250 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001251 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001252 case Mips::BGEZALS_MM:
1253 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001254 return true;
1255 default:
1256 return false;
1257 }
1258}
1259
Jack Carter9e65aa32013-03-22 00:05:30 +00001260bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001261 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001262 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001263
Jack Carter9e65aa32013-03-22 00:05:30 +00001264 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001265
1266 if (MCID.isBranch() || MCID.isCall()) {
1267 const unsigned Opcode = Inst.getOpcode();
1268 MCOperand Offset;
1269
1270 switch (Opcode) {
1271 default:
1272 break;
Kai Nackee0245392015-01-27 19:11:28 +00001273 case Mips::BBIT0:
1274 case Mips::BBIT032:
1275 case Mips::BBIT1:
1276 case Mips::BBIT132:
1277 assert(hasCnMips() && "instruction only valid for octeon cpus");
1278 // Fall through
1279
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001280 case Mips::BEQ:
1281 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001282 case Mips::BEQ_MM:
1283 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001284 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001285 Offset = Inst.getOperand(2);
1286 if (!Offset.isImm())
1287 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001288 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001289 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001290 if (OffsetToAlignment(Offset.getImm(),
1291 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001292 return Error(IDLoc, "branch to misaligned address");
1293 break;
1294 case Mips::BGEZ:
1295 case Mips::BGTZ:
1296 case Mips::BLEZ:
1297 case Mips::BLTZ:
1298 case Mips::BGEZAL:
1299 case Mips::BLTZAL:
1300 case Mips::BC1F:
1301 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001302 case Mips::BGEZ_MM:
1303 case Mips::BGTZ_MM:
1304 case Mips::BLEZ_MM:
1305 case Mips::BLTZ_MM:
1306 case Mips::BGEZAL_MM:
1307 case Mips::BLTZAL_MM:
1308 case Mips::BC1F_MM:
1309 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001310 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001311 Offset = Inst.getOperand(1);
1312 if (!Offset.isImm())
1313 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001314 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001315 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001316 if (OffsetToAlignment(Offset.getImm(),
1317 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001318 return Error(IDLoc, "branch to misaligned address");
1319 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001320 case Mips::BEQZ16_MM:
1321 case Mips::BNEZ16_MM:
1322 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1323 Offset = Inst.getOperand(1);
1324 if (!Offset.isImm())
1325 break; // We'll deal with this situation later on when applying fixups.
1326 if (!isIntN(8, Offset.getImm()))
1327 return Error(IDLoc, "branch target out of range");
1328 if (OffsetToAlignment(Offset.getImm(), 2LL))
1329 return Error(IDLoc, "branch to misaligned address");
1330 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001331 }
1332 }
1333
Daniel Sandersa84989a2014-06-16 13:25:35 +00001334 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1335 // We still accept it but it is a normal nop.
1336 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1337 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1338 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1339 "nop instruction");
1340 }
1341
Kai Nackee0245392015-01-27 19:11:28 +00001342 if (hasCnMips()) {
1343 const unsigned Opcode = Inst.getOpcode();
1344 MCOperand Opnd;
1345 int Imm;
1346
1347 switch (Opcode) {
1348 default:
1349 break;
1350
1351 case Mips::BBIT0:
1352 case Mips::BBIT032:
1353 case Mips::BBIT1:
1354 case Mips::BBIT132:
1355 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1356 // The offset is handled above
1357 Opnd = Inst.getOperand(1);
1358 if (!Opnd.isImm())
1359 return Error(IDLoc, "expected immediate operand kind");
1360 Imm = Opnd.getImm();
1361 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1362 Opcode == Mips::BBIT1 ? 63 : 31))
1363 return Error(IDLoc, "immediate operand value out of range");
1364 if (Imm > 31) {
1365 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1366 : Mips::BBIT132);
1367 Inst.getOperand(1).setImm(Imm - 32);
1368 }
1369 break;
1370
1371 case Mips::CINS:
1372 case Mips::CINS32:
1373 case Mips::EXTS:
1374 case Mips::EXTS32:
1375 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1376 // Check length
1377 Opnd = Inst.getOperand(3);
1378 if (!Opnd.isImm())
1379 return Error(IDLoc, "expected immediate operand kind");
1380 Imm = Opnd.getImm();
1381 if (Imm < 0 || Imm > 31)
1382 return Error(IDLoc, "immediate operand value out of range");
1383 // Check position
1384 Opnd = Inst.getOperand(2);
1385 if (!Opnd.isImm())
1386 return Error(IDLoc, "expected immediate operand kind");
1387 Imm = Opnd.getImm();
1388 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1389 Opcode == Mips::EXTS ? 63 : 31))
1390 return Error(IDLoc, "immediate operand value out of range");
1391 if (Imm > 31) {
1392 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1393 Inst.getOperand(2).setImm(Imm - 32);
1394 }
1395 break;
1396
1397 case Mips::SEQi:
1398 case Mips::SNEi:
1399 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1400 Opnd = Inst.getOperand(2);
1401 if (!Opnd.isImm())
1402 return Error(IDLoc, "expected immediate operand kind");
1403 Imm = Opnd.getImm();
1404 if (!isInt<10>(Imm))
1405 return Error(IDLoc, "immediate operand value out of range");
1406 break;
1407 }
1408 }
1409
Jack Carter9e65aa32013-03-22 00:05:30 +00001410 if (MCID.mayLoad() || MCID.mayStore()) {
1411 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001412 // reference or immediate we may have to expand instructions.
1413 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001414 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001415 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1416 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001417 MCOperand &Op = Inst.getOperand(i);
1418 if (Op.isImm()) {
1419 int MemOffset = Op.getImm();
1420 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001421 // Offset can't exceed 16bit value.
1422 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001423 return false;
1424 }
1425 } else if (Op.isExpr()) {
1426 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001427 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001428 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001429 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001430 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001431 // Expand symbol.
1432 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001433 return false;
1434 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001435 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001436 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001437 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001438 }
1439 }
1440 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001441 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001442 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001443
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001444 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001445 if (MCID.mayLoad()) {
1446 // Try to create 16-bit GP relative load instruction.
1447 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1448 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1449 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1450 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1451 MCOperand &Op = Inst.getOperand(i);
1452 if (Op.isImm()) {
1453 int MemOffset = Op.getImm();
1454 MCOperand &DstReg = Inst.getOperand(0);
1455 MCOperand &BaseReg = Inst.getOperand(1);
1456 if (isIntN(9, MemOffset) && (MemOffset % 4 == 0) &&
1457 getContext().getRegisterInfo()->getRegClass(
1458 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
1459 BaseReg.getReg() == Mips::GP) {
1460 MCInst TmpInst;
1461 TmpInst.setLoc(IDLoc);
1462 TmpInst.setOpcode(Mips::LWGP_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00001463 TmpInst.addOperand(MCOperand::createReg(DstReg.getReg()));
1464 TmpInst.addOperand(MCOperand::createReg(Mips::GP));
1465 TmpInst.addOperand(MCOperand::createImm(MemOffset));
Jozef Koleke10a02e2015-01-28 17:27:26 +00001466 Instructions.push_back(TmpInst);
1467 return false;
1468 }
1469 }
1470 }
1471 } // for
1472 } // if load
1473
1474 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1475
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001476 MCOperand Opnd;
1477 int Imm;
1478
1479 switch (Inst.getOpcode()) {
1480 default:
1481 break;
1482 case Mips::ADDIUS5_MM:
1483 Opnd = Inst.getOperand(2);
1484 if (!Opnd.isImm())
1485 return Error(IDLoc, "expected immediate operand kind");
1486 Imm = Opnd.getImm();
1487 if (Imm < -8 || Imm > 7)
1488 return Error(IDLoc, "immediate operand value out of range");
1489 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001490 case Mips::ADDIUSP_MM:
1491 Opnd = Inst.getOperand(0);
1492 if (!Opnd.isImm())
1493 return Error(IDLoc, "expected immediate operand kind");
1494 Imm = Opnd.getImm();
1495 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1496 Imm % 4 != 0)
1497 return Error(IDLoc, "immediate operand value out of range");
1498 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001499 case Mips::SLL16_MM:
1500 case Mips::SRL16_MM:
1501 Opnd = Inst.getOperand(2);
1502 if (!Opnd.isImm())
1503 return Error(IDLoc, "expected immediate operand kind");
1504 Imm = Opnd.getImm();
1505 if (Imm < 1 || Imm > 8)
1506 return Error(IDLoc, "immediate operand value out of range");
1507 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001508 case Mips::LI16_MM:
1509 Opnd = Inst.getOperand(1);
1510 if (!Opnd.isImm())
1511 return Error(IDLoc, "expected immediate operand kind");
1512 Imm = Opnd.getImm();
1513 if (Imm < -1 || Imm > 126)
1514 return Error(IDLoc, "immediate operand value out of range");
1515 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001516 case Mips::ADDIUR2_MM:
1517 Opnd = Inst.getOperand(2);
1518 if (!Opnd.isImm())
1519 return Error(IDLoc, "expected immediate operand kind");
1520 Imm = Opnd.getImm();
1521 if (!(Imm == 1 || Imm == -1 ||
1522 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1523 return Error(IDLoc, "immediate operand value out of range");
1524 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001525 case Mips::ADDIUR1SP_MM:
1526 Opnd = Inst.getOperand(1);
1527 if (!Opnd.isImm())
1528 return Error(IDLoc, "expected immediate operand kind");
1529 Imm = Opnd.getImm();
1530 if (OffsetToAlignment(Imm, 4LL))
1531 return Error(IDLoc, "misaligned immediate operand value");
1532 if (Imm < 0 || Imm > 255)
1533 return Error(IDLoc, "immediate operand value out of range");
1534 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001535 case Mips::ANDI16_MM:
1536 Opnd = Inst.getOperand(2);
1537 if (!Opnd.isImm())
1538 return Error(IDLoc, "expected immediate operand kind");
1539 Imm = Opnd.getImm();
1540 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1541 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1542 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1543 return Error(IDLoc, "immediate operand value out of range");
1544 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001545 case Mips::LBU16_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 < -1 || Imm > 14)
1551 return Error(IDLoc, "immediate operand value out of range");
1552 break;
1553 case Mips::SB16_MM:
1554 Opnd = Inst.getOperand(2);
1555 if (!Opnd.isImm())
1556 return Error(IDLoc, "expected immediate operand kind");
1557 Imm = Opnd.getImm();
1558 if (Imm < 0 || Imm > 15)
1559 return Error(IDLoc, "immediate operand value out of range");
1560 break;
1561 case Mips::LHU16_MM:
1562 case Mips::SH16_MM:
1563 Opnd = Inst.getOperand(2);
1564 if (!Opnd.isImm())
1565 return Error(IDLoc, "expected immediate operand kind");
1566 Imm = Opnd.getImm();
1567 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1568 return Error(IDLoc, "immediate operand value out of range");
1569 break;
1570 case Mips::LW16_MM:
1571 case Mips::SW16_MM:
1572 Opnd = Inst.getOperand(2);
1573 if (!Opnd.isImm())
1574 return Error(IDLoc, "expected immediate operand kind");
1575 Imm = Opnd.getImm();
1576 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1577 return Error(IDLoc, "immediate operand value out of range");
1578 break;
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001579 case Mips::CACHE:
1580 case Mips::PREF:
1581 Opnd = Inst.getOperand(2);
1582 if (!Opnd.isImm())
1583 return Error(IDLoc, "expected immediate operand kind");
1584 Imm = Opnd.getImm();
1585 if (!isUInt<5>(Imm))
1586 return Error(IDLoc, "immediate operand value out of range");
1587 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001588 case Mips::ADDIUPC_MM:
1589 MCOperand Opnd = Inst.getOperand(1);
1590 if (!Opnd.isImm())
1591 return Error(IDLoc, "expected immediate operand kind");
1592 int Imm = Opnd.getImm();
1593 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1594 return Error(IDLoc, "immediate operand value out of range");
1595 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001596 }
1597 }
1598
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001599 if (needsExpansion(Inst)) {
1600 if (expandInstruction(Inst, IDLoc, Instructions))
1601 return true;
1602 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001603 Instructions.push_back(Inst);
1604
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001605 // If this instruction has a delay slot and .set reorder is active,
1606 // emit a NOP after it.
1607 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1608 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1609
Jack Carter9e65aa32013-03-22 00:05:30 +00001610 return false;
1611}
1612
Jack Carter30a59822012-10-04 04:03:53 +00001613bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1614
Jack Carterd0bd6422013-04-18 00:41:53 +00001615 switch (Inst.getOpcode()) {
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001616 case Mips::LoadImm32:
1617 case Mips::LoadImm64:
1618 case Mips::LoadAddrImm32:
1619 case Mips::LoadAddrReg32:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001620 case Mips::B_MM_Pseudo:
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001621 case Mips::LWM_MM:
1622 case Mips::SWM_MM:
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001623 case Mips::JalOneReg:
1624 case Mips::JalTwoReg:
Toma Tabacue1e460d2015-06-11 10:36:10 +00001625 case Mips::BneImm:
1626 case Mips::BeqImm:
Jack Carterd0bd6422013-04-18 00:41:53 +00001627 return true;
1628 default:
1629 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001630 }
1631}
Jack Carter92995f12012-10-06 00:53:28 +00001632
Matheus Almeida3813d572014-06-19 14:39:14 +00001633bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001634 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001635 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001636 default: llvm_unreachable("unimplemented expansion");
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001637 case Mips::LoadImm32:
Toma Tabacu00e98672015-05-01 12:19:27 +00001638 return expandLoadImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001639 case Mips::LoadImm64:
Toma Tabacu00e98672015-05-01 12:19:27 +00001640 return expandLoadImm(Inst, false, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001641 case Mips::LoadAddrImm32:
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001642 return expandLoadAddressImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001643 case Mips::LoadAddrReg32:
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001644 return expandLoadAddressReg(Inst, true, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001645 case Mips::B_MM_Pseudo:
1646 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001647 case Mips::SWM_MM:
1648 case Mips::LWM_MM:
1649 return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001650 case Mips::JalOneReg:
1651 case Mips::JalTwoReg:
1652 return expandJalWithRegs(Inst, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00001653 case Mips::BneImm:
1654 case Mips::BeqImm:
1655 return expandBranchImm(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001656 }
Jack Carter30a59822012-10-04 04:03:53 +00001657}
Jack Carter92995f12012-10-06 00:53:28 +00001658
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001659namespace {
Toma Tabacua2861db2015-05-01 10:26:47 +00001660template <unsigned ShiftAmount>
Toma Tabacu61145652015-04-28 13:16:06 +00001661void createLShiftOri(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001662 SmallVectorImpl<MCInst> &Instructions) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001663 MCInst tmpInst;
Toma Tabacua2861db2015-05-01 10:26:47 +00001664 if (ShiftAmount >= 32) {
1665 tmpInst.setOpcode(Mips::DSLL32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001666 tmpInst.addOperand(MCOperand::createReg(RegNo));
1667 tmpInst.addOperand(MCOperand::createReg(RegNo));
1668 tmpInst.addOperand(MCOperand::createImm(ShiftAmount - 32));
Toma Tabacua2861db2015-05-01 10:26:47 +00001669 tmpInst.setLoc(IDLoc);
1670 Instructions.push_back(tmpInst);
1671 tmpInst.clear();
1672 } else if (ShiftAmount > 0) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001673 tmpInst.setOpcode(Mips::DSLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00001674 tmpInst.addOperand(MCOperand::createReg(RegNo));
1675 tmpInst.addOperand(MCOperand::createReg(RegNo));
1676 tmpInst.addOperand(MCOperand::createImm(ShiftAmount));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001677 tmpInst.setLoc(IDLoc);
1678 Instructions.push_back(tmpInst);
1679 tmpInst.clear();
1680 }
Toma Tabacu7dea2e32015-04-28 14:06:35 +00001681 // There's no need for an ORi if the immediate is 0.
1682 if (Operand.isImm() && Operand.getImm() == 0)
1683 return;
1684
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001685 tmpInst.setOpcode(Mips::ORi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001686 tmpInst.addOperand(MCOperand::createReg(RegNo));
1687 tmpInst.addOperand(MCOperand::createReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001688 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001689 tmpInst.setLoc(IDLoc);
1690 Instructions.push_back(tmpInst);
1691}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001692
Toma Tabacua2861db2015-05-01 10:26:47 +00001693template <unsigned ShiftAmount>
Toma Tabacu61145652015-04-28 13:16:06 +00001694void createLShiftOri(int64_t Value, unsigned RegNo, SMLoc IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001695 SmallVectorImpl<MCInst> &Instructions) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001696 createLShiftOri<ShiftAmount>(MCOperand::createImm(Value), RegNo, IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001697 Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001698}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001699}
1700
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001701bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
1702 SmallVectorImpl<MCInst> &Instructions) {
1703 // Create a JALR instruction which is going to replace the pseudo-JAL.
1704 MCInst JalrInst;
1705 JalrInst.setLoc(IDLoc);
1706 const MCOperand FirstRegOp = Inst.getOperand(0);
1707 const unsigned Opcode = Inst.getOpcode();
1708
1709 if (Opcode == Mips::JalOneReg) {
1710 // jal $rs => jalr $rs
1711 if (inMicroMipsMode()) {
1712 JalrInst.setOpcode(Mips::JALR16_MM);
1713 JalrInst.addOperand(FirstRegOp);
1714 } else {
1715 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00001716 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001717 JalrInst.addOperand(FirstRegOp);
1718 }
1719 } else if (Opcode == Mips::JalTwoReg) {
1720 // jal $rd, $rs => jalr $rd, $rs
1721 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
1722 JalrInst.addOperand(FirstRegOp);
1723 const MCOperand SecondRegOp = Inst.getOperand(1);
1724 JalrInst.addOperand(SecondRegOp);
1725 }
1726 Instructions.push_back(JalrInst);
1727
1728 // If .set reorder is active, emit a NOP after it.
1729 if (AssemblerOptions.back()->isReorder()) {
1730 // This is a 32-bit NOP because these 2 pseudo-instructions
1731 // do not have a short delay slot.
1732 MCInst NopInst;
1733 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00001734 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
1735 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
1736 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001737 Instructions.push_back(NopInst);
1738 }
1739
1740 return false;
1741}
1742
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001743bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
1744 unsigned SrcReg, bool Is32BitImm, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001745 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00001746 if (!Is32BitImm && !isGP64bit()) {
1747 Error(IDLoc, "instruction requires a 64-bit architecture");
1748 return true;
1749 }
1750
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001751 bool UseSrcReg = false;
1752 if (SrcReg != Mips::NoRegister)
1753 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00001754
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001755 MCInst tmpInst;
1756
Jack Carter92995f12012-10-06 00:53:28 +00001757 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001758 // FIXME: gas has a special case for values that are 000...1111, which
1759 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001760 if (0 <= ImmValue && ImmValue <= 65535) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001761 // For unsigned and positive signed 16-bit values (0 <= j <= 65535):
Jack Carter30a59822012-10-04 04:03:53 +00001762 // li d,j => ori d,$zero,j
Toma Tabacudf7fd462015-05-13 16:02:41 +00001763 if (!UseSrcReg)
1764 SrcReg = isGP64bit() ? Mips::ZERO_64 : Mips::ZERO;
Jack Carter873c7242013-01-12 01:03:14 +00001765 tmpInst.setOpcode(Mips::ORi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001766 tmpInst.addOperand(MCOperand::createReg(DstReg));
1767 tmpInst.addOperand(MCOperand::createReg(SrcReg));
1768 tmpInst.addOperand(MCOperand::createImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001769 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001770 } else if (ImmValue < 0 && ImmValue >= -32768) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001771 // For negative signed 16-bit values (-32768 <= j < 0):
Jack Carter30a59822012-10-04 04:03:53 +00001772 // li d,j => addiu d,$zero,j
Toma Tabacudf7fd462015-05-13 16:02:41 +00001773 if (!UseSrcReg)
1774 SrcReg = Mips::ZERO;
Jack Carter873c7242013-01-12 01:03:14 +00001775 tmpInst.setOpcode(Mips::ADDiu);
Jim Grosbache9119e42015-05-13 18:37:00 +00001776 tmpInst.addOperand(MCOperand::createReg(DstReg));
1777 tmpInst.addOperand(MCOperand::createReg(SrcReg));
1778 tmpInst.addOperand(MCOperand::createImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001779 Instructions.push_back(tmpInst);
Toma Tabacua3d056f2015-05-15 09:42:11 +00001780 } else if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00001781 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00001782
Toma Tabacuae47f932015-04-10 13:28:16 +00001783 // For all other values which are representable as a 32-bit integer:
Jack Carter30a59822012-10-04 04:03:53 +00001784 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001785 // ori d,d,lo16(j)
Toma Tabacu79588102015-04-29 10:19:56 +00001786 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1787 uint16_t Bits15To0 = ImmValue & 0xffff;
1788
Toma Tabacua3d056f2015-05-15 09:42:11 +00001789 if (!Is32BitImm && !isInt<32>(ImmValue)) {
1790 // For DLI, expand to an ORi instead of a LUi to avoid sign-extending the
1791 // upper 32 bits.
1792 tmpInst.setOpcode(Mips::ORi);
1793 tmpInst.addOperand(MCOperand::createReg(DstReg));
1794 tmpInst.addOperand(MCOperand::createReg(Mips::ZERO));
1795 tmpInst.addOperand(MCOperand::createImm(Bits31To16));
1796 tmpInst.setLoc(IDLoc);
1797 Instructions.push_back(tmpInst);
1798 // Move the value to the upper 16 bits by doing a 16-bit left shift.
1799 createLShiftOri<16>(0, DstReg, IDLoc, Instructions);
1800 } else {
1801 tmpInst.setOpcode(Mips::LUi);
1802 tmpInst.addOperand(MCOperand::createReg(DstReg));
1803 tmpInst.addOperand(MCOperand::createImm(Bits31To16));
1804 Instructions.push_back(tmpInst);
1805 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001806 createLShiftOri<0>(Bits15To0, DstReg, IDLoc, Instructions);
1807
1808 if (UseSrcReg)
1809 createAddu(DstReg, DstReg, SrcReg, Instructions);
1810
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001811 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Toma Tabacu00e98672015-05-01 12:19:27 +00001812 if (Is32BitImm) {
1813 Error(IDLoc, "instruction requires a 32-bit immediate");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001814 return true;
1815 }
Toma Tabacu81496c12015-05-20 08:54:45 +00001816 warnIfNoMacro(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001817
1818 // <------- lo32 ------>
1819 // <------- hi32 ------>
1820 // <- hi16 -> <- lo16 ->
1821 // _________________________________
1822 // | | | |
Toma Tabacubda745f2015-04-27 15:21:38 +00001823 // | 16-bits | 16-bits | 16-bits |
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001824 // |__________|__________|__________|
1825 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001826 // For any 64-bit value that is representable as a 48-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001827 // li d,j => lui d,hi16(j)
1828 // ori d,d,hi16(lo32(j))
1829 // dsll d,d,16
1830 // ori d,d,lo16(lo32(j))
Toma Tabacu79588102015-04-29 10:19:56 +00001831 uint16_t Bits47To32 = (ImmValue >> 32) & 0xffff;
1832 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1833 uint16_t Bits15To0 = ImmValue & 0xffff;
1834
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001835 tmpInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001836 tmpInst.addOperand(MCOperand::createReg(DstReg));
1837 tmpInst.addOperand(MCOperand::createImm(Bits47To32));
Jack Carter30a59822012-10-04 04:03:53 +00001838 Instructions.push_back(tmpInst);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001839 createLShiftOri<0>(Bits31To16, DstReg, IDLoc, Instructions);
1840 createLShiftOri<16>(Bits15To0, DstReg, IDLoc, Instructions);
1841
1842 if (UseSrcReg)
1843 createAddu(DstReg, DstReg, SrcReg, Instructions);
1844
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001845 } else {
Toma Tabacu00e98672015-05-01 12:19:27 +00001846 if (Is32BitImm) {
1847 Error(IDLoc, "instruction requires a 32-bit immediate");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001848 return true;
1849 }
Toma Tabacu81496c12015-05-20 08:54:45 +00001850 warnIfNoMacro(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001851
1852 // <------- hi32 ------> <------- lo32 ------>
1853 // <- hi16 -> <- lo16 ->
1854 // ___________________________________________
1855 // | | | | |
Toma Tabacubda745f2015-04-27 15:21:38 +00001856 // | 16-bits | 16-bits | 16-bits | 16-bits |
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001857 // |__________|__________|__________|__________|
1858 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001859 // For all other values which are representable as a 64-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001860 // li d,j => lui d,hi16(j)
1861 // ori d,d,lo16(hi32(j))
1862 // dsll d,d,16
1863 // ori d,d,hi16(lo32(j))
1864 // dsll d,d,16
1865 // ori d,d,lo16(lo32(j))
Toma Tabacu79588102015-04-29 10:19:56 +00001866 uint16_t Bits63To48 = (ImmValue >> 48) & 0xffff;
1867 uint16_t Bits47To32 = (ImmValue >> 32) & 0xffff;
1868 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1869 uint16_t Bits15To0 = ImmValue & 0xffff;
1870
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001871 tmpInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001872 tmpInst.addOperand(MCOperand::createReg(DstReg));
1873 tmpInst.addOperand(MCOperand::createImm(Bits63To48));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001874 Instructions.push_back(tmpInst);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001875 createLShiftOri<0>(Bits47To32, DstReg, IDLoc, Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001876
1877 // When Bits31To16 is 0, do a left shift of 32 bits instead of doing
1878 // two left shifts of 16 bits.
1879 if (Bits31To16 == 0) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001880 createLShiftOri<32>(Bits15To0, DstReg, IDLoc, Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001881 } else {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001882 createLShiftOri<16>(Bits31To16, DstReg, IDLoc, Instructions);
1883 createLShiftOri<16>(Bits15To0, DstReg, IDLoc, Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001884 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001885
1886 if (UseSrcReg)
1887 createAddu(DstReg, DstReg, SrcReg, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001888 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001889 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001890}
Jack Carter92995f12012-10-06 00:53:28 +00001891
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001892bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
1893 SmallVectorImpl<MCInst> &Instructions) {
1894 const MCOperand &ImmOp = Inst.getOperand(1);
1895 assert(ImmOp.isImm() && "expected immediate operand kind");
1896 const MCOperand &DstRegOp = Inst.getOperand(0);
1897 assert(DstRegOp.isReg() && "expected register operand kind");
1898
1899 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
1900 Is32BitImm, IDLoc, Instructions))
1901 return true;
1902
1903 return false;
1904}
1905
Matheus Almeida3813d572014-06-19 14:39:14 +00001906bool
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001907MipsAsmParser::expandLoadAddressReg(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001908 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacub5592ee2015-05-14 10:02:58 +00001909 const MCOperand &DstRegOp = Inst.getOperand(0);
1910 assert(DstRegOp.isReg() && "expected register operand kind");
1911
Jack Carter543fdf82012-10-09 23:29:45 +00001912 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001913 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1914 "expected immediate operand kind");
1915 if (!ImmOp.isImm()) {
Toma Tabacu674825c2015-06-16 12:16:24 +00001916 if (loadSymbolAddress(ImmOp.getExpr(), DstRegOp.getReg(), Is32BitImm, IDLoc,
1917 Instructions))
1918 return true;
1919
Toma Tabacu0d64b202014-08-14 10:29:17 +00001920 return false;
1921 }
Jack Carter543fdf82012-10-09 23:29:45 +00001922 const MCOperand &SrcRegOp = Inst.getOperand(1);
1923 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001924
1925 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), SrcRegOp.getReg(),
1926 Is32BitImm, IDLoc, Instructions))
1927 return true;
1928
Matheus Almeida3813d572014-06-19 14:39:14 +00001929 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001930}
1931
Matheus Almeida3813d572014-06-19 14:39:14 +00001932bool
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001933MipsAsmParser::expandLoadAddressImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001934 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacub5592ee2015-05-14 10:02:58 +00001935 const MCOperand &DstRegOp = Inst.getOperand(0);
1936 assert(DstRegOp.isReg() && "expected register operand kind");
1937
Jack Carter543fdf82012-10-09 23:29:45 +00001938 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001939 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1940 "expected immediate operand kind");
1941 if (!ImmOp.isImm()) {
Toma Tabacu674825c2015-06-16 12:16:24 +00001942 if (loadSymbolAddress(ImmOp.getExpr(), DstRegOp.getReg(), Is32BitImm, IDLoc,
1943 Instructions))
1944 return true;
1945
Toma Tabacu0d64b202014-08-14 10:29:17 +00001946 return false;
1947 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001948
1949 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
1950 Is32BitImm, IDLoc, Instructions))
1951 return true;
1952
Matheus Almeida3813d572014-06-19 14:39:14 +00001953 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001954}
1955
Toma Tabacu674825c2015-06-16 12:16:24 +00001956bool MipsAsmParser::loadSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
1957 bool Is32BitSym, SMLoc IDLoc,
1958 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00001959 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00001960
Toma Tabacuec1de822015-05-14 10:53:40 +00001961 if (Is32BitSym && isABI_N64())
1962 Warning(IDLoc, "instruction loads the 32-bit address of a 64-bit symbol");
1963
Toma Tabacu0d64b202014-08-14 10:29:17 +00001964 MCInst tmpInst;
Toma Tabacu674825c2015-06-16 12:16:24 +00001965 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymExpr);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001966 const MCSymbolRefExpr *HiExpr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00001967 MCSymbolRefExpr::create(Symbol->getSymbol().getName(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00001968 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1969 const MCSymbolRefExpr *LoExpr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00001970 MCSymbolRefExpr::create(Symbol->getSymbol().getName(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00001971 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
Toma Tabacuec1de822015-05-14 10:53:40 +00001972 if (!Is32BitSym) {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001973 // If it's a 64-bit architecture, expand to:
1974 // la d,sym => lui d,highest(sym)
1975 // ori d,d,higher(sym)
1976 // dsll d,d,16
1977 // ori d,d,hi16(sym)
1978 // dsll d,d,16
1979 // ori d,d,lo16(sym)
1980 const MCSymbolRefExpr *HighestExpr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00001981 MCSymbolRefExpr::create(Symbol->getSymbol().getName(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00001982 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1983 const MCSymbolRefExpr *HigherExpr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00001984 MCSymbolRefExpr::create(Symbol->getSymbol().getName(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00001985 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1986
1987 tmpInst.setOpcode(Mips::LUi);
Toma Tabacu674825c2015-06-16 12:16:24 +00001988 tmpInst.addOperand(MCOperand::createReg(DstReg));
Jim Grosbache9119e42015-05-13 18:37:00 +00001989 tmpInst.addOperand(MCOperand::createExpr(HighestExpr));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001990 Instructions.push_back(tmpInst);
1991
Toma Tabacu674825c2015-06-16 12:16:24 +00001992 createLShiftOri<0>(MCOperand::createExpr(HigherExpr), DstReg, SMLoc(),
Toma Tabacua2861db2015-05-01 10:26:47 +00001993 Instructions);
Toma Tabacu674825c2015-06-16 12:16:24 +00001994 createLShiftOri<16>(MCOperand::createExpr(HiExpr), DstReg, SMLoc(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00001995 Instructions);
Toma Tabacu674825c2015-06-16 12:16:24 +00001996 createLShiftOri<16>(MCOperand::createExpr(LoExpr), DstReg, SMLoc(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00001997 Instructions);
1998 } else {
1999 // Otherwise, expand to:
2000 // la d,sym => lui d,hi16(sym)
2001 // ori d,d,lo16(sym)
2002 tmpInst.setOpcode(Mips::LUi);
Toma Tabacu674825c2015-06-16 12:16:24 +00002003 tmpInst.addOperand(MCOperand::createReg(DstReg));
Jim Grosbache9119e42015-05-13 18:37:00 +00002004 tmpInst.addOperand(MCOperand::createExpr(HiExpr));
Toma Tabacu0d64b202014-08-14 10:29:17 +00002005 Instructions.push_back(tmpInst);
2006
Toma Tabacu674825c2015-06-16 12:16:24 +00002007 createLShiftOri<0>(MCOperand::createExpr(LoExpr), DstReg, SMLoc(),
Toma Tabacua2861db2015-05-01 10:26:47 +00002008 Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00002009 }
Toma Tabacu674825c2015-06-16 12:16:24 +00002010 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002011}
2012
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002013bool MipsAsmParser::expandUncondBranchMMPseudo(
2014 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002015 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2016 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002017
2018 MCOperand Offset = Inst.getOperand(0);
2019 if (Offset.isExpr()) {
2020 Inst.clear();
2021 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002022 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2023 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2024 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002025 } else {
2026 assert(Offset.isImm() && "expected immediate operand kind");
2027 if (isIntN(11, Offset.getImm())) {
2028 // If offset fits into 11 bits then this instruction becomes microMIPS
2029 // 16-bit unconditional branch instruction.
2030 Inst.setOpcode(Mips::B16_MM);
2031 } else {
2032 if (!isIntN(17, Offset.getImm()))
2033 Error(IDLoc, "branch target out of range");
2034 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2035 Error(IDLoc, "branch to misaligned address");
2036 Inst.clear();
2037 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002038 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2039 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2040 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002041 }
2042 }
2043 Instructions.push_back(Inst);
2044
Toma Tabacu234482a2015-03-16 12:03:39 +00002045 // If .set reorder is active, emit a NOP after the branch instruction.
2046 if (AssemblerOptions.back()->isReorder())
2047 createNop(true, IDLoc, Instructions);
2048
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002049 return false;
2050}
2051
Toma Tabacue1e460d2015-06-11 10:36:10 +00002052bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2053 SmallVectorImpl<MCInst> &Instructions) {
2054 const MCOperand &DstRegOp = Inst.getOperand(0);
2055 assert(DstRegOp.isReg() && "expected register operand kind");
2056
2057 const MCOperand &ImmOp = Inst.getOperand(1);
2058 assert(ImmOp.isImm() && "expected immediate operand kind");
2059
2060 const MCOperand &MemOffsetOp = Inst.getOperand(2);
2061 assert(MemOffsetOp.isImm() && "expected immediate operand kind");
2062
2063 unsigned OpCode = 0;
2064 switch(Inst.getOpcode()) {
2065 case Mips::BneImm:
2066 OpCode = Mips::BNE;
2067 break;
2068 case Mips::BeqImm:
2069 OpCode = Mips::BEQ;
2070 break;
2071 default:
2072 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2073 break;
2074 }
2075
2076 int64_t ImmValue = ImmOp.getImm();
2077 if (ImmValue == 0) {
2078 MCInst BranchInst;
2079 BranchInst.setOpcode(OpCode);
2080 BranchInst.addOperand(DstRegOp);
2081 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2082 BranchInst.addOperand(MemOffsetOp);
2083 Instructions.push_back(BranchInst);
2084 } else {
2085 warnIfNoMacro(IDLoc);
2086
2087 unsigned ATReg = getATReg(IDLoc);
2088 if (!ATReg)
2089 return true;
2090
2091 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), IDLoc,
2092 Instructions))
2093 return true;
2094
2095 MCInst BranchInst;
2096 BranchInst.setOpcode(OpCode);
2097 BranchInst.addOperand(DstRegOp);
2098 BranchInst.addOperand(MCOperand::createReg(ATReg));
2099 BranchInst.addOperand(MemOffsetOp);
2100 Instructions.push_back(BranchInst);
2101 }
2102 return false;
2103}
2104
Jack Carter9e65aa32013-03-22 00:05:30 +00002105void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002106 SmallVectorImpl<MCInst> &Instructions,
2107 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002108 const MCSymbolRefExpr *SR;
2109 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00002110 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002111 const MCExpr *ExprOffset;
2112 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002113 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002114 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2115 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002116 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002117 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2118 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002119 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002120 if (isImmOpnd) {
2121 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2122 ImmOffset = Inst.getOperand(2).getImm();
2123 LoOffset = ImmOffset & 0x0000ffff;
2124 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002125 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002126 if (LoOffset & 0x8000)
2127 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002128 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002129 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002130 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002131 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002132 // These are some of the types of expansions we perform here:
2133 // 1) lw $8, sym => lui $8, %hi(sym)
2134 // lw $8, %lo(sym)($8)
2135 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2136 // add $8, $8, $9
2137 // lw $8, %lo(offset)($9)
2138 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2139 // add $at, $at, $8
2140 // lw $8, %lo(offset)($at)
2141 // 4) sw $8, sym => lui $at, %hi(sym)
2142 // sw $8, %lo(sym)($at)
2143 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2144 // add $at, $at, $8
2145 // sw $8, %lo(offset)($at)
2146 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2147 // ldc1 $f0, %lo(sym)($at)
2148 //
2149 // For load instructions we can use the destination register as a temporary
2150 // if base and dst are different (examples 1 and 2) and if the base register
2151 // is general purpose otherwise we must use $at (example 6) and error if it's
2152 // not available. For stores we must use $at (examples 4 and 5) because we
2153 // must not clobber the source register setting up the offset.
2154 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2155 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2156 unsigned RegClassIDOp0 =
2157 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2158 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2159 (RegClassIDOp0 == Mips::GPR64RegClassID);
2160 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002161 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002162 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002163 // At this point we need AT to perform the expansions and we exit if it is
2164 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002165 TmpRegNum = getATReg(IDLoc);
2166 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002167 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002168 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002169
Jack Carter9e65aa32013-03-22 00:05:30 +00002170 TempInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00002171 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002172 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002173 TempInst.addOperand(MCOperand::createImm(HiOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002174 else {
2175 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002176 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jim Grosbach13760bd2015-05-30 01:25:56 +00002177 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::create(
Jack Carterd0bd6422013-04-18 00:41:53 +00002178 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
2179 getContext());
Jim Grosbache9119e42015-05-13 18:37:00 +00002180 TempInst.addOperand(MCOperand::createExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002181 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002182 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jim Grosbache9119e42015-05-13 18:37:00 +00002183 TempInst.addOperand(MCOperand::createExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002184 }
2185 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002186 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002187 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002188 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002189 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002190 // Add temp register to base.
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002191 if (BaseRegNum != Mips::ZERO) {
2192 TempInst.setOpcode(Mips::ADDu);
Jim Grosbache9119e42015-05-13 18:37:00 +00002193 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2194 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2195 TempInst.addOperand(MCOperand::createReg(BaseRegNum));
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002196 Instructions.push_back(TempInst);
2197 TempInst.clear();
2198 }
Alp Tokercb402912014-01-24 17:20:08 +00002199 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002200 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002201 TempInst.setOpcode(Inst.getOpcode());
Jim Grosbache9119e42015-05-13 18:37:00 +00002202 TempInst.addOperand(MCOperand::createReg(RegOpNum));
2203 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002204 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002205 TempInst.addOperand(MCOperand::createImm(LoOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002206 else {
2207 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002208 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::create(
Jack Carterd0bd6422013-04-18 00:41:53 +00002209 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
2210 getContext());
Jim Grosbache9119e42015-05-13 18:37:00 +00002211 TempInst.addOperand(MCOperand::createExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002212 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002213 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jim Grosbache9119e42015-05-13 18:37:00 +00002214 TempInst.addOperand(MCOperand::createExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002215 }
2216 }
2217 Instructions.push_back(TempInst);
2218 TempInst.clear();
2219}
2220
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002221bool
2222MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2223 SmallVectorImpl<MCInst> &Instructions) {
2224 unsigned OpNum = Inst.getNumOperands();
2225 unsigned Opcode = Inst.getOpcode();
2226 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2227
2228 assert (Inst.getOperand(OpNum - 1).isImm() &&
2229 Inst.getOperand(OpNum - 2).isReg() &&
2230 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2231
2232 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2233 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2234 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2235 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2236 // It can be implemented as SWM16 or LWM16 instruction.
2237 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2238
2239 Inst.setOpcode(NewOpcode);
2240 Instructions.push_back(Inst);
2241 return false;
2242}
2243
Toma Tabacu234482a2015-03-16 12:03:39 +00002244void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
2245 SmallVectorImpl<MCInst> &Instructions) {
2246 MCInst NopInst;
2247 if (hasShortDelaySlot) {
2248 NopInst.setOpcode(Mips::MOVE16_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002249 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2250 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
Toma Tabacu234482a2015-03-16 12:03:39 +00002251 } else {
2252 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00002253 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2254 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2255 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu234482a2015-03-16 12:03:39 +00002256 }
2257 Instructions.push_back(NopInst);
2258}
2259
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002260void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
2261 unsigned TrgReg,
2262 SmallVectorImpl<MCInst> &Instructions) {
2263 MCInst AdduInst;
2264 AdduInst.setOpcode(Mips::ADDu);
Jim Grosbache9119e42015-05-13 18:37:00 +00002265 AdduInst.addOperand(MCOperand::createReg(DstReg));
2266 AdduInst.addOperand(MCOperand::createReg(SrcReg));
2267 AdduInst.addOperand(MCOperand::createReg(TrgReg));
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002268 Instructions.push_back(AdduInst);
2269}
2270
Matheus Almeida595fcab2014-06-11 15:05:56 +00002271unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
2272 // As described by the Mips32r2 spec, the registers Rd and Rs for
2273 // jalr.hb must be different.
2274 unsigned Opcode = Inst.getOpcode();
2275
2276 if (Opcode == Mips::JALR_HB &&
2277 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
2278 return Match_RequiresDifferentSrcAndDst;
2279
2280 return Match_Success;
2281}
2282
David Blaikie960ea3f2014-06-08 16:18:35 +00002283bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
2284 OperandVector &Operands,
2285 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00002286 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00002287 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00002288
Jack Carterb4dbc172012-09-05 23:34:03 +00002289 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00002290 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00002291 unsigned MatchResult =
2292 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00002293
2294 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002295 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002296 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00002297 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00002298 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00002299 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00002300 return false;
2301 }
2302 case Match_MissingFeature:
2303 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
2304 return true;
2305 case Match_InvalidOperand: {
2306 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00002307 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002308 if (ErrorInfo >= Operands.size())
2309 return Error(IDLoc, "too few operands for instruction");
2310
David Blaikie960ea3f2014-06-08 16:18:35 +00002311 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00002312 if (ErrorLoc == SMLoc())
2313 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00002314 }
2315
2316 return Error(ErrorLoc, "invalid operand for instruction");
2317 }
2318 case Match_MnemonicFail:
2319 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00002320 case Match_RequiresDifferentSrcAndDst:
2321 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00002322 }
Craig Topper589ceee2015-01-03 08:16:34 +00002323
2324 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00002325}
2326
Toma Tabacud9d344b2015-04-27 14:05:04 +00002327void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
2328 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
2329 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
2330 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002331}
2332
Toma Tabacu81496c12015-05-20 08:54:45 +00002333void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
2334 if (!AssemblerOptions.back()->isMacro())
2335 Warning(Loc, "macro instruction expanded into multiple instructions");
2336}
2337
Daniel Sandersef638fe2014-10-03 15:37:37 +00002338void
2339MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
2340 SMRange Range, bool ShowColors) {
2341 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00002342 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00002343 ShowColors);
2344}
2345
Jack Carter1ac53222013-02-20 23:11:17 +00002346int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002347 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002348
Vladimir Medic4c299852013-11-06 11:27:05 +00002349 CC = StringSwitch<unsigned>(Name)
2350 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002351 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00002352 .Case("a0", 4)
2353 .Case("a1", 5)
2354 .Case("a2", 6)
2355 .Case("a3", 7)
2356 .Case("v0", 2)
2357 .Case("v1", 3)
2358 .Case("s0", 16)
2359 .Case("s1", 17)
2360 .Case("s2", 18)
2361 .Case("s3", 19)
2362 .Case("s4", 20)
2363 .Case("s5", 21)
2364 .Case("s6", 22)
2365 .Case("s7", 23)
2366 .Case("k0", 26)
2367 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002368 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00002369 .Case("sp", 29)
2370 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002371 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00002372 .Case("ra", 31)
2373 .Case("t0", 8)
2374 .Case("t1", 9)
2375 .Case("t2", 10)
2376 .Case("t3", 11)
2377 .Case("t4", 12)
2378 .Case("t5", 13)
2379 .Case("t6", 14)
2380 .Case("t7", 15)
2381 .Case("t8", 24)
2382 .Case("t9", 25)
2383 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002384
Toma Tabacufda445c2014-09-15 15:33:01 +00002385 if (!(isABI_N32() || isABI_N64()))
2386 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002387
Daniel Sandersef638fe2014-10-03 15:37:37 +00002388 if (12 <= CC && CC <= 15) {
2389 // Name is one of t4-t7
2390 AsmToken RegTok = getLexer().peekTok();
2391 SMRange RegRange = RegTok.getLocRange();
2392
2393 StringRef FixedName = StringSwitch<StringRef>(Name)
2394 .Case("t4", "t0")
2395 .Case("t5", "t1")
2396 .Case("t6", "t2")
2397 .Case("t7", "t3")
2398 .Default("");
2399 assert(FixedName != "" && "Register name is not one of t4-t7.");
2400
2401 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
2402 "Did you mean $" + FixedName + "?", RegRange);
2403 }
2404
Toma Tabacufda445c2014-09-15 15:33:01 +00002405 // Although SGI documentation just cuts out t0-t3 for n32/n64,
2406 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
2407 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
2408 if (8 <= CC && CC <= 11)
2409 CC += 4;
2410
2411 if (CC == -1)
2412 CC = StringSwitch<unsigned>(Name)
2413 .Case("a4", 8)
2414 .Case("a5", 9)
2415 .Case("a6", 10)
2416 .Case("a7", 11)
2417 .Case("kt0", 26)
2418 .Case("kt1", 27)
2419 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002420
2421 return CC;
2422}
Jack Carterd0bd6422013-04-18 00:41:53 +00002423
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002424int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
2425 int CC;
2426
2427 CC = StringSwitch<unsigned>(Name)
2428 .Case("hwr_cpunum", 0)
2429 .Case("hwr_synci_step", 1)
2430 .Case("hwr_cc", 2)
2431 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00002432 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002433 .Default(-1);
2434
2435 return CC;
2436}
2437
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002438int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002439
Jack Cartera63b16a2012-09-07 00:23:42 +00002440 if (Name[0] == 'f') {
2441 StringRef NumString = Name.substr(1);
2442 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002443 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002444 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002445 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00002446 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002447 return IntVal;
2448 }
2449 return -1;
2450}
Jack Cartera63b16a2012-09-07 00:23:42 +00002451
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002452int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
2453
2454 if (Name.startswith("fcc")) {
2455 StringRef NumString = Name.substr(3);
2456 unsigned IntVal;
2457 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002458 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002459 if (IntVal > 7) // There are only 8 fcc registers.
2460 return -1;
2461 return IntVal;
2462 }
2463 return -1;
2464}
2465
2466int MipsAsmParser::matchACRegisterName(StringRef Name) {
2467
Akira Hatanaka274d24c2013-08-14 01:15:52 +00002468 if (Name.startswith("ac")) {
2469 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002470 unsigned IntVal;
2471 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002472 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002473 if (IntVal > 3) // There are only 3 acc registers.
2474 return -1;
2475 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00002476 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002477 return -1;
2478}
Jack Carterd0bd6422013-04-18 00:41:53 +00002479
Jack Carter5dc8ac92013-09-25 23:50:44 +00002480int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
2481 unsigned IntVal;
2482
2483 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2484 return -1;
2485
2486 if (IntVal > 31)
2487 return -1;
2488
2489 return IntVal;
2490}
2491
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002492int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
2493 int CC;
2494
2495 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00002496 .Case("msair", 0)
2497 .Case("msacsr", 1)
2498 .Case("msaaccess", 2)
2499 .Case("msasave", 3)
2500 .Case("msamodify", 4)
2501 .Case("msarequest", 5)
2502 .Case("msamap", 6)
2503 .Case("msaunmap", 7)
2504 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002505
2506 return CC;
2507}
2508
Toma Tabacu89a712b2015-04-15 10:48:56 +00002509unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00002510 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00002511 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002512 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00002513 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00002514 return 0;
2515 }
2516 unsigned AT = getReg(
2517 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00002518 return AT;
2519}
Jack Carter0b744b32012-10-04 02:29:46 +00002520
Jack Carterd0bd6422013-04-18 00:41:53 +00002521unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00002522 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00002523}
2524
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002525unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002526 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00002527 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002528}
2529
Jack Carter873c7242013-01-12 01:03:14 +00002530int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002531 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00002532 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00002533 return -1;
2534
Jack Carter873c7242013-01-12 01:03:14 +00002535 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00002536}
2537
Toma Tabacu13964452014-09-04 13:23:44 +00002538bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002539 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002540 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002541
Jack Carter30a59822012-10-04 04:03:53 +00002542 // Check if the current operand has a custom associated parser, if so, try to
2543 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00002544 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2545 if (ResTy == MatchOperand_Success)
2546 return false;
2547 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2548 // there was a match, but an error occurred, in which case, just return that
2549 // the operand parsing failed.
2550 if (ResTy == MatchOperand_ParseFail)
2551 return true;
2552
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002553 DEBUG(dbgs() << ".. Generic Parser\n");
2554
Jack Carterb4dbc172012-09-05 23:34:03 +00002555 switch (getLexer().getKind()) {
2556 default:
2557 Error(Parser.getTok().getLoc(), "unexpected token in operand");
2558 return true;
2559 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002560 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00002561 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00002562
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002563 // Almost all registers have been parsed by custom parsers. There is only
2564 // one exception to this. $zero (and it's alias $0) will reach this point
2565 // for div, divu, and similar instructions because it is not an operand
2566 // to the instruction definition but an explicit register. Special case
2567 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00002568 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00002569 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002570
Jack Carterd0bd6422013-04-18 00:41:53 +00002571 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00002572 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002573 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00002574 return true;
2575
Jack Carter873c7242013-01-12 01:03:14 +00002576 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00002577 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00002578 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00002579 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002580 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00002581
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002582 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002583 return false;
2584 }
Vladimir Medic4c299852013-11-06 11:27:05 +00002585 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00002586 case AsmToken::LParen:
2587 case AsmToken::Minus:
2588 case AsmToken::Plus:
2589 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002590 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00002591 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002592 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002593 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002594 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00002595 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00002596 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002597 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002598 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002599 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00002600 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00002601 return true;
2602
Jack Carter873c7242013-01-12 01:03:14 +00002603 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2604
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002605 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00002606 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002607 } // case AsmToken::Percent
2608 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00002609 return true;
2610}
2611
Vladimir Medic4c299852013-11-06 11:27:05 +00002612const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00002613 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00002614 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00002615 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002616 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00002617 // It's a constant, evaluate reloc value.
2618 int16_t Val;
2619 switch (getVariantKind(RelocStr)) {
2620 case MCSymbolRefExpr::VK_Mips_ABS_LO:
2621 // Get the 1st 16-bits.
2622 Val = MCE->getValue() & 0xffff;
2623 break;
2624 case MCSymbolRefExpr::VK_Mips_ABS_HI:
2625 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2626 // 16 bits being negative.
2627 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2628 break;
2629 case MCSymbolRefExpr::VK_Mips_HIGHER:
2630 // Get the 3rd 16-bits.
2631 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2632 break;
2633 case MCSymbolRefExpr::VK_Mips_HIGHEST:
2634 // Get the 4th 16-bits.
2635 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2636 break;
2637 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00002638 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00002639 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00002640 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002641 }
2642
Jack Carterb5cf5902013-04-17 00:18:04 +00002643 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002644 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00002645 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00002646 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00002647 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002648 return Res;
2649 }
2650
2651 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00002652 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2653
Sasa Stankovic06c47802014-04-03 10:37:45 +00002654 // Try to create target expression.
2655 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00002656 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002657
Jack Carterd0bd6422013-04-18 00:41:53 +00002658 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2659 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00002660 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002661 return Res;
2662 }
2663
2664 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002665 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00002666 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00002667 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002668 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002669 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002670 return Expr;
2671}
2672
2673bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2674
2675 switch (Expr->getKind()) {
2676 case MCExpr::Constant:
2677 return true;
2678 case MCExpr::SymbolRef:
2679 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2680 case MCExpr::Binary:
2681 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2682 if (!isEvaluated(BE->getLHS()))
2683 return false;
2684 return isEvaluated(BE->getRHS());
2685 }
2686 case MCExpr::Unary:
2687 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002688 case MCExpr::Target:
2689 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002690 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002691 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002692}
Jack Carterd0bd6422013-04-18 00:41:53 +00002693
Jack Carterb5cf5902013-04-17 00:18:04 +00002694bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002695 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00002696 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002697 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002698 if (Tok.isNot(AsmToken::Identifier))
2699 return true;
2700
Yaron Keren075759a2015-03-30 15:42:36 +00002701 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00002702
Jack Carterd0bd6422013-04-18 00:41:53 +00002703 Parser.Lex(); // Eat the identifier.
2704 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002705 const MCExpr *IdVal;
2706 SMLoc EndLoc;
2707
2708 if (getLexer().getKind() == AsmToken::LParen) {
2709 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002710 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002711 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002712 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002713 const AsmToken &nextTok = Parser.getTok();
2714 if (nextTok.isNot(AsmToken::Identifier))
2715 return true;
2716 Str += "(%";
2717 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002718 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002719 if (getLexer().getKind() != AsmToken::LParen)
2720 return true;
2721 } else
2722 break;
2723 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002724 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002725 return true;
2726
2727 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002728 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002729
2730 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002731 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002732
Jack Carterd0bd6422013-04-18 00:41:53 +00002733 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002734 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002735}
2736
Jack Carterb4dbc172012-09-05 23:34:03 +00002737bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2738 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002739 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002740 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002741 if (ResTy == MatchOperand_Success) {
2742 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002743 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002744 StartLoc = Operand.getStartLoc();
2745 EndLoc = Operand.getEndLoc();
2746
2747 // AFAIK, we only support numeric registers and named GPR's in CFI
2748 // directives.
2749 // Don't worry about eating tokens before failing. Using an unrecognised
2750 // register is a parse error.
2751 if (Operand.isGPRAsmReg()) {
2752 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002753 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002754 }
2755
2756 return (RegNo == (unsigned)-1);
2757 }
2758
2759 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002760 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002761}
2762
Jack Carterb5cf5902013-04-17 00:18:04 +00002763bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002764 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00002765 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002766 bool Result = true;
2767
2768 while (getLexer().getKind() == AsmToken::LParen)
2769 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002770
Jack Carterd0bd6422013-04-18 00:41:53 +00002771 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002772 default:
2773 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002774 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002775 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002776 case AsmToken::Integer:
2777 case AsmToken::Minus:
2778 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002779 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002780 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002781 else
2782 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002783 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002784 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002785 break;
Jack Carter873c7242013-01-12 01:03:14 +00002786 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002787 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002788 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002789 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002790}
2791
David Blaikie960ea3f2014-06-08 16:18:35 +00002792MipsAsmParser::OperandMatchResultTy
2793MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002794 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002795 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002796 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002797 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002798 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002799 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002800 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002801 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002802
Jack Carterb5cf5902013-04-17 00:18:04 +00002803 if (getLexer().getKind() == AsmToken::LParen) {
2804 Parser.Lex();
2805 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002806 }
2807
Jack Carterb5cf5902013-04-17 00:18:04 +00002808 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002809 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002810 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002811
Jack Carterd0bd6422013-04-18 00:41:53 +00002812 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002813 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002814 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2815 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002816 SMLoc E =
2817 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002818 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002819 return MatchOperand_Success;
2820 }
2821 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002822 SMLoc E =
2823 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002824
Jack Carterd0bd6422013-04-18 00:41:53 +00002825 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002826 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002827 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002828 S, E, *this);
2829 Operands.push_back(
2830 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002831 return MatchOperand_Success;
2832 }
2833 Error(Parser.getTok().getLoc(), "'(' expected");
2834 return MatchOperand_ParseFail;
2835 }
2836
Jack Carterd0bd6422013-04-18 00:41:53 +00002837 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002838 }
2839
Toma Tabacu13964452014-09-04 13:23:44 +00002840 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002841 if (Res != MatchOperand_Success)
2842 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002843
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002844 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002845 Error(Parser.getTok().getLoc(), "')' expected");
2846 return MatchOperand_ParseFail;
2847 }
2848
Jack Carter873c7242013-01-12 01:03:14 +00002849 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2850
Jack Carterd0bd6422013-04-18 00:41:53 +00002851 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002852
Craig Topper062a2ba2014-04-25 05:30:21 +00002853 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002854 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002855
Jack Carterd0bd6422013-04-18 00:41:53 +00002856 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002857 std::unique_ptr<MipsOperand> op(
2858 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002859 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002860 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002861 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002862 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002863 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2864 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00002865 if (IdVal->evaluateAsAbsolute(Imm))
2866 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002867 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002868 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00002869 getContext());
2870 }
2871
David Blaikie960ea3f2014-06-08 16:18:35 +00002872 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002873 return MatchOperand_Success;
2874}
2875
David Blaikie960ea3f2014-06-08 16:18:35 +00002876bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002877 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00002878 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00002879 if (Sym) {
2880 SMLoc S = Parser.getTok().getLoc();
2881 const MCExpr *Expr;
2882 if (Sym->isVariable())
2883 Expr = Sym->getVariableValue();
2884 else
2885 return false;
2886 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002887 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002888 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002889 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002890 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002891 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002892 if (ResTy == MatchOperand_Success) {
2893 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002894 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002895 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002896 llvm_unreachable("Should never ParseFail");
2897 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002898 }
2899 } else if (Expr->getKind() == MCExpr::Constant) {
2900 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002901 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002902 Operands.push_back(
2903 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002904 return true;
2905 }
2906 }
2907 return false;
2908}
Jack Carterd0bd6422013-04-18 00:41:53 +00002909
Jack Carter873c7242013-01-12 01:03:14 +00002910MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002911MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002912 StringRef Identifier,
2913 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002914 int Index = matchCPURegisterName(Identifier);
2915 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002916 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002917 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2918 return MatchOperand_Success;
2919 }
2920
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002921 Index = matchHWRegsRegisterName(Identifier);
2922 if (Index != -1) {
2923 Operands.push_back(MipsOperand::createHWRegsReg(
2924 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2925 return MatchOperand_Success;
2926 }
2927
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002928 Index = matchFPURegisterName(Identifier);
2929 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002930 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002931 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2932 return MatchOperand_Success;
2933 }
2934
2935 Index = matchFCCRegisterName(Identifier);
2936 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002937 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002938 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2939 return MatchOperand_Success;
2940 }
2941
2942 Index = matchACRegisterName(Identifier);
2943 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002944 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002945 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2946 return MatchOperand_Success;
2947 }
2948
2949 Index = matchMSA128RegisterName(Identifier);
2950 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002951 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002952 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2953 return MatchOperand_Success;
2954 }
2955
2956 Index = matchMSA128CtrlRegisterName(Identifier);
2957 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002958 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002959 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2960 return MatchOperand_Success;
2961 }
2962
2963 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002964}
2965
2966MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002967MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002968 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00002969 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002970
2971 if (Token.is(AsmToken::Identifier)) {
2972 DEBUG(dbgs() << ".. identifier\n");
2973 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002974 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002975 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002976 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002977 } else if (Token.is(AsmToken::Integer)) {
2978 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002979 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002980 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2981 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002982 return MatchOperand_Success;
2983 }
2984
2985 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2986
2987 return MatchOperand_NoMatch;
2988}
2989
David Blaikie960ea3f2014-06-08 16:18:35 +00002990MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002991MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002992 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002993 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002994
2995 auto Token = Parser.getTok();
2996
2997 SMLoc S = Token.getLoc();
2998
2999 if (Token.isNot(AsmToken::Dollar)) {
3000 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
3001 if (Token.is(AsmToken::Identifier)) {
3002 if (searchSymbolAlias(Operands))
3003 return MatchOperand_Success;
3004 }
3005 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
3006 return MatchOperand_NoMatch;
3007 }
3008 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003009
Toma Tabacu13964452014-09-04 13:23:44 +00003010 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00003011 if (ResTy == MatchOperand_Success) {
3012 Parser.Lex(); // $
3013 Parser.Lex(); // identifier
3014 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003015 return ResTy;
3016}
3017
3018MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003019MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003020 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003021 switch (getLexer().getKind()) {
3022 default:
3023 return MatchOperand_NoMatch;
3024 case AsmToken::LParen:
3025 case AsmToken::Minus:
3026 case AsmToken::Plus:
3027 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003028 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003029 case AsmToken::String:
3030 break;
3031 }
3032
3033 const MCExpr *IdVal;
3034 SMLoc S = Parser.getTok().getLoc();
3035 if (getParser().parseExpression(IdVal))
3036 return MatchOperand_ParseFail;
3037
3038 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3039 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
3040 return MatchOperand_Success;
3041}
3042
David Blaikie960ea3f2014-06-08 16:18:35 +00003043MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003044MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003045 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003046 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003047
3048 SMLoc S = getLexer().getLoc();
3049
3050 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00003051 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003052 if (ResTy != MatchOperand_NoMatch)
3053 return ResTy;
3054
Daniel Sanders315386c2014-04-01 10:40:14 +00003055 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00003056 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00003057 if (ResTy != MatchOperand_NoMatch)
3058 return ResTy;
3059
Daniel Sandersffd84362014-04-01 10:41:48 +00003060 const MCExpr *Expr = nullptr;
3061 if (Parser.parseExpression(Expr)) {
3062 // We have no way of knowing if a symbol was consumed so we must ParseFail
3063 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003064 }
Daniel Sandersffd84362014-04-01 10:41:48 +00003065 Operands.push_back(
3066 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003067 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00003068}
3069
Vladimir Medic2b953d02013-10-01 09:48:56 +00003070MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00003071MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003072 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00003073 const MCExpr *IdVal;
3074 // If the first token is '$' we may have register operand.
3075 if (Parser.getTok().is(AsmToken::Dollar))
3076 return MatchOperand_NoMatch;
3077 SMLoc S = Parser.getTok().getLoc();
3078 if (getParser().parseExpression(IdVal))
3079 return MatchOperand_ParseFail;
3080 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00003081 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00003082 int64_t Val = MCE->getValue();
3083 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3084 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003085 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00003086 return MatchOperand_Success;
3087}
3088
Matheus Almeida779c5932013-11-18 12:32:49 +00003089MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003090MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003091 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00003092 switch (getLexer().getKind()) {
3093 default:
3094 return MatchOperand_NoMatch;
3095 case AsmToken::LParen:
3096 case AsmToken::Plus:
3097 case AsmToken::Minus:
3098 case AsmToken::Integer:
3099 break;
3100 }
3101
3102 const MCExpr *Expr;
3103 SMLoc S = Parser.getTok().getLoc();
3104
3105 if (getParser().parseExpression(Expr))
3106 return MatchOperand_ParseFail;
3107
3108 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003109 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00003110 Error(S, "expected immediate value");
3111 return MatchOperand_ParseFail;
3112 }
3113
3114 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
3115 // and because the CPU always adds one to the immediate field, the allowed
3116 // range becomes 1..4. We'll only check the range here and will deal
3117 // with the addition/subtraction when actually decoding/encoding
3118 // the instruction.
3119 if (Val < 1 || Val > 4) {
3120 Error(S, "immediate not in range (1..4)");
3121 return MatchOperand_ParseFail;
3122 }
3123
Jack Carter3b2c96e2014-01-22 23:31:38 +00003124 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003125 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00003126 return MatchOperand_Success;
3127}
3128
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00003129MipsAsmParser::OperandMatchResultTy
3130MipsAsmParser::parseRegisterList(OperandVector &Operands) {
3131 MCAsmParser &Parser = getParser();
3132 SmallVector<unsigned, 10> Regs;
3133 unsigned RegNo;
3134 unsigned PrevReg = Mips::NoRegister;
3135 bool RegRange = false;
3136 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3137
3138 if (Parser.getTok().isNot(AsmToken::Dollar))
3139 return MatchOperand_ParseFail;
3140
3141 SMLoc S = Parser.getTok().getLoc();
3142 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
3143 SMLoc E = getLexer().getLoc();
3144 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
3145 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
3146 if (RegRange) {
3147 // Remove last register operand because registers from register range
3148 // should be inserted first.
3149 if (RegNo == Mips::RA) {
3150 Regs.push_back(RegNo);
3151 } else {
3152 unsigned TmpReg = PrevReg + 1;
3153 while (TmpReg <= RegNo) {
3154 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
3155 Error(E, "invalid register operand");
3156 return MatchOperand_ParseFail;
3157 }
3158
3159 PrevReg = TmpReg;
3160 Regs.push_back(TmpReg++);
3161 }
3162 }
3163
3164 RegRange = false;
3165 } else {
3166 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
3167 (RegNo != Mips::RA)) {
3168 Error(E, "$16 or $31 expected");
3169 return MatchOperand_ParseFail;
3170 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
3171 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3172 Error(E, "invalid register operand");
3173 return MatchOperand_ParseFail;
3174 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
3175 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3176 Error(E, "consecutive register numbers expected");
3177 return MatchOperand_ParseFail;
3178 }
3179
3180 Regs.push_back(RegNo);
3181 }
3182
3183 if (Parser.getTok().is(AsmToken::Minus))
3184 RegRange = true;
3185
3186 if (!Parser.getTok().isNot(AsmToken::Minus) &&
3187 !Parser.getTok().isNot(AsmToken::Comma)) {
3188 Error(E, "',' or '-' expected");
3189 return MatchOperand_ParseFail;
3190 }
3191
3192 Lex(); // Consume comma or minus
3193 if (Parser.getTok().isNot(AsmToken::Dollar))
3194 break;
3195
3196 PrevReg = RegNo;
3197 }
3198
3199 SMLoc E = Parser.getTok().getLoc();
3200 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3201 parseMemOperand(Operands);
3202 return MatchOperand_Success;
3203}
3204
Zoran Jovanovic2deca342014-12-16 14:59:10 +00003205MipsAsmParser::OperandMatchResultTy
3206MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
3207 MCAsmParser &Parser = getParser();
3208
3209 SMLoc S = Parser.getTok().getLoc();
3210 if (parseAnyRegister(Operands) != MatchOperand_Success)
3211 return MatchOperand_ParseFail;
3212
3213 SMLoc E = Parser.getTok().getLoc();
3214 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
3215 unsigned Reg = Op.getGPR32Reg();
3216 Operands.pop_back();
3217 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
3218 return MatchOperand_Success;
3219}
3220
Zoran Jovanovic41688672015-02-10 16:36:20 +00003221MipsAsmParser::OperandMatchResultTy
3222MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
3223 MCAsmParser &Parser = getParser();
3224 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3225 SmallVector<unsigned, 10> Regs;
3226
3227 if (Parser.getTok().isNot(AsmToken::Dollar))
3228 return MatchOperand_ParseFail;
3229
3230 SMLoc S = Parser.getTok().getLoc();
3231
3232 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3233 return MatchOperand_ParseFail;
3234
3235 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3236 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3237 Regs.push_back(RegNo);
3238
3239 SMLoc E = Parser.getTok().getLoc();
3240 if (Parser.getTok().isNot(AsmToken::Comma)) {
3241 Error(E, "',' expected");
3242 return MatchOperand_ParseFail;
3243 }
3244
3245 // Remove comma.
3246 Parser.Lex();
3247
3248 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3249 return MatchOperand_ParseFail;
3250
3251 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3252 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3253 Regs.push_back(RegNo);
3254
3255 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3256
3257 return MatchOperand_Success;
3258}
3259
Jack Carterdc1e35d2012-09-06 20:00:02 +00003260MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
3261
Vladimir Medic4c299852013-11-06 11:27:05 +00003262 MCSymbolRefExpr::VariantKind VK =
3263 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
3264 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
3265 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
3266 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
3267 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
3268 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
3269 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
3270 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
3271 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
3272 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
3273 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
3274 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
3275 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
3276 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
3277 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
3278 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
3279 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
3280 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00003281 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
3282 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
3283 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
3284 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
3285 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
3286 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00003287 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
3288 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00003289 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003290
Matheus Almeida2852af82014-04-22 10:15:54 +00003291 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00003292
Jack Carterdc1e35d2012-09-06 20:00:02 +00003293 return VK;
3294}
Jack Cartera63b16a2012-09-07 00:23:42 +00003295
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003296/// Sometimes (i.e. load/stores) the operand may be followed immediately by
3297/// either this.
3298/// ::= '(', register, ')'
3299/// handle it before we iterate so we don't get tripped up by the lack of
3300/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003301bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003302 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003303 if (getLexer().is(AsmToken::LParen)) {
3304 Operands.push_back(
3305 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
3306 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003307 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003308 SMLoc Loc = getLexer().getLoc();
3309 Parser.eatToEndOfStatement();
3310 return Error(Loc, "unexpected token in argument list");
3311 }
3312 if (Parser.getTok().isNot(AsmToken::RParen)) {
3313 SMLoc Loc = getLexer().getLoc();
3314 Parser.eatToEndOfStatement();
3315 return Error(Loc, "unexpected token, expected ')'");
3316 }
3317 Operands.push_back(
3318 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
3319 Parser.Lex();
3320 }
3321 return false;
3322}
3323
3324/// Sometimes (i.e. in MSA) the operand may be followed immediately by
3325/// either one of these.
3326/// ::= '[', register, ']'
3327/// ::= '[', integer, ']'
3328/// handle it before we iterate so we don't get tripped up by the lack of
3329/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003330bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00003331 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003332 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003333 if (getLexer().is(AsmToken::LBrac)) {
3334 Operands.push_back(
3335 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
3336 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003337 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003338 SMLoc Loc = getLexer().getLoc();
3339 Parser.eatToEndOfStatement();
3340 return Error(Loc, "unexpected token in argument list");
3341 }
3342 if (Parser.getTok().isNot(AsmToken::RBrac)) {
3343 SMLoc Loc = getLexer().getLoc();
3344 Parser.eatToEndOfStatement();
3345 return Error(Loc, "unexpected token, expected ']'");
3346 }
3347 Operands.push_back(
3348 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
3349 Parser.Lex();
3350 }
3351 return false;
3352}
3353
David Blaikie960ea3f2014-06-08 16:18:35 +00003354bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
3355 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003356 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003357 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003358
3359 // We have reached first instruction, module directive are now forbidden.
3360 getTargetStreamer().forbidModuleDirective();
3361
Vladimir Medic74593e62013-07-17 15:00:42 +00003362 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00003363 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00003364 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00003365 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00003366 }
Vladimir Medic64828a12013-07-16 10:07:14 +00003367 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003368 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003369
3370 // Read the remaining operands.
3371 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3372 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003373 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003374 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003375 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003376 return Error(Loc, "unexpected token in argument list");
3377 }
Toma Tabacu13964452014-09-04 13:23:44 +00003378 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003379 return true;
3380 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00003381
Jack Carterd0bd6422013-04-18 00:41:53 +00003382 while (getLexer().is(AsmToken::Comma)) {
3383 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00003384 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003385 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003386 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003387 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003388 return Error(Loc, "unexpected token in argument list");
3389 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003390 // Parse bracket and parenthesis suffixes before we iterate
3391 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00003392 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003393 return true;
3394 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00003395 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003396 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003397 }
3398 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003399 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3400 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003401 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003402 return Error(Loc, "unexpected token in argument list");
3403 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003404 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00003405 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00003406}
3407
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003408bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003409 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003410 SMLoc Loc = getLexer().getLoc();
3411 Parser.eatToEndOfStatement();
3412 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00003413}
3414
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003415bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003416 return Error(Loc, ErrorMsg);
3417}
3418
Jack Carter0b744b32012-10-04 02:29:46 +00003419bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003420 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003421 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00003422
3423 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00003424 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00003425
3426 Parser.Lex(); // Eat "noat".
3427
Jack Carterd0bd6422013-04-18 00:41:53 +00003428 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003429 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003430 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003431 return false;
3432 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003433
3434 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003435 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003436 return false;
3437}
Jack Carterd0bd6422013-04-18 00:41:53 +00003438
Jack Carter0b744b32012-10-04 02:29:46 +00003439bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00003440 // Line can be: ".set at", which sets $at to $1
3441 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00003442 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00003443 Parser.Lex(); // Eat "at".
3444
Jack Carter0b744b32012-10-04 02:29:46 +00003445 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003446 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00003447 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00003448
3449 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003450 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003451 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00003452 }
3453
3454 if (getLexer().isNot(AsmToken::Equal)) {
3455 reportParseError("unexpected token, expected equals sign");
3456 return false;
3457 }
3458 Parser.Lex(); // Eat "=".
3459
3460 if (getLexer().isNot(AsmToken::Dollar)) {
3461 if (getLexer().is(AsmToken::EndOfStatement)) {
3462 reportParseError("no register specified");
3463 return false;
3464 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00003465 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00003466 return false;
3467 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003468 }
3469 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00003470
Toma Tabacu16a74492015-02-13 10:30:57 +00003471 // Find out what "reg" is.
3472 unsigned AtRegNo;
3473 const AsmToken &Reg = Parser.getTok();
3474 if (Reg.is(AsmToken::Identifier)) {
3475 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
3476 } else if (Reg.is(AsmToken::Integer)) {
3477 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00003478 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00003479 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00003480 return false;
3481 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003482
3483 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00003484 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003485 reportParseError("invalid register");
3486 return false;
3487 }
3488 Parser.Lex(); // Eat "reg".
3489
3490 // If this is not the end of the statement, report an error.
3491 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3492 reportParseError("unexpected token, expected end of statement");
3493 return false;
3494 }
3495
3496 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
3497
3498 Parser.Lex(); // Consume the EndOfStatement.
3499 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003500}
3501
3502bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003503 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003504 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003505 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003506 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003507 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003508 return false;
3509 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003510 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00003511 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003512 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003513 return false;
3514}
3515
3516bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003517 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003518 Parser.Lex();
3519 // If this is not the end of the statement, report an error.
3520 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003521 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003522 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003523 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003524 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00003525 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003526 Parser.Lex(); // Consume the EndOfStatement.
3527 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003528}
3529
3530bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003531 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003532 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003533 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003534 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003535 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003536 return false;
3537 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003538 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00003539 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003540 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003541 return false;
3542}
3543
3544bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003545 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003546 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003547 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003548 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003549 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003550 return false;
3551 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003552 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00003553 reportParseError("`noreorder' must be set before `nomacro'");
3554 return false;
3555 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003556 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00003557 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003558 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003559 return false;
3560}
Jack Carterd76b2372013-03-21 21:44:16 +00003561
Daniel Sanders44934432014-08-07 12:03:36 +00003562bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003563 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003564 Parser.Lex();
3565
3566 // If this is not the end of the statement, report an error.
3567 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003568 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003569
3570 setFeatureBits(Mips::FeatureMSA, "msa");
3571 getTargetStreamer().emitDirectiveSetMsa();
3572 return false;
3573}
3574
3575bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003576 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003577 Parser.Lex();
3578
3579 // If this is not the end of the statement, report an error.
3580 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003581 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003582
3583 clearFeatureBits(Mips::FeatureMSA, "msa");
3584 getTargetStreamer().emitDirectiveSetNoMsa();
3585 return false;
3586}
3587
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003588bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003589 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003590 Parser.Lex(); // Eat "nodsp".
3591
3592 // If this is not the end of the statement, report an error.
3593 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3594 reportParseError("unexpected token, expected end of statement");
3595 return false;
3596 }
3597
3598 clearFeatureBits(Mips::FeatureDSP, "dsp");
3599 getTargetStreamer().emitDirectiveSetNoDsp();
3600 return false;
3601}
3602
Toma Tabacucc2502d2014-11-04 17:18:07 +00003603bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003604 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003605 Parser.Lex(); // Eat "mips16".
3606
Jack Carter39536722014-01-22 23:08:42 +00003607 // If this is not the end of the statement, report an error.
3608 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003609 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00003610 return false;
3611 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00003612
3613 setFeatureBits(Mips::FeatureMips16, "mips16");
3614 getTargetStreamer().emitDirectiveSetMips16();
3615 Parser.Lex(); // Consume the EndOfStatement.
3616 return false;
3617}
3618
3619bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003620 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003621 Parser.Lex(); // Eat "nomips16".
3622
3623 // If this is not the end of the statement, report an error.
3624 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3625 reportParseError("unexpected token, expected end of statement");
3626 return false;
3627 }
3628
3629 clearFeatureBits(Mips::FeatureMips16, "mips16");
3630 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00003631 Parser.Lex(); // Consume the EndOfStatement.
3632 return false;
3633}
3634
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003635bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003636 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003637 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003638 // Line can be: .set fp=32
3639 // .set fp=xx
3640 // .set fp=64
3641 Parser.Lex(); // Eat fp token
3642 AsmToken Tok = Parser.getTok();
3643 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003644 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003645 return false;
3646 }
3647 Parser.Lex(); // Eat '=' token.
3648 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003649
3650 if (!parseFpABIValue(FpAbiVal, ".set"))
3651 return false;
3652
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003653 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003654 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003655 return false;
3656 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003657 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003658 Parser.Lex(); // Consume the EndOfStatement.
3659 return false;
3660}
3661
Toma Tabacu9db22db2014-09-09 10:15:38 +00003662bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003663 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003664 SMLoc Loc = getLexer().getLoc();
3665
3666 Parser.Lex();
3667 if (getLexer().isNot(AsmToken::EndOfStatement))
3668 return reportParseError("unexpected token, expected end of statement");
3669
3670 // Always keep an element on the options "stack" to prevent the user
3671 // from changing the initial options. This is how we remember them.
3672 if (AssemblerOptions.size() == 2)
3673 return reportParseError(Loc, ".set pop with no .set push");
3674
3675 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00003676 setAvailableFeatures(
3677 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
3678 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00003679
3680 getTargetStreamer().emitDirectiveSetPop();
3681 return false;
3682}
3683
3684bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003685 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003686 Parser.Lex();
3687 if (getLexer().isNot(AsmToken::EndOfStatement))
3688 return reportParseError("unexpected token, expected end of statement");
3689
3690 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00003691 AssemblerOptions.push_back(
3692 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00003693
3694 getTargetStreamer().emitDirectiveSetPush();
3695 return false;
3696}
3697
Toma Tabacu29696502015-06-02 09:48:04 +00003698bool MipsAsmParser::parseSetSoftFloatDirective() {
3699 MCAsmParser &Parser = getParser();
3700 Parser.Lex();
3701 if (getLexer().isNot(AsmToken::EndOfStatement))
3702 return reportParseError("unexpected token, expected end of statement");
3703
3704 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
3705 getTargetStreamer().emitDirectiveSetSoftFloat();
3706 return false;
3707}
3708
3709bool MipsAsmParser::parseSetHardFloatDirective() {
3710 MCAsmParser &Parser = getParser();
3711 Parser.Lex();
3712 if (getLexer().isNot(AsmToken::EndOfStatement))
3713 return reportParseError("unexpected token, expected end of statement");
3714
3715 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
3716 getTargetStreamer().emitDirectiveSetHardFloat();
3717 return false;
3718}
3719
Jack Carterd76b2372013-03-21 21:44:16 +00003720bool MipsAsmParser::parseSetAssignment() {
3721 StringRef Name;
3722 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00003723 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00003724
3725 if (Parser.parseIdentifier(Name))
3726 reportParseError("expected identifier after .set");
3727
3728 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003729 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00003730 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00003731
Jack Carter3b2c96e2014-01-22 23:31:38 +00003732 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00003733 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00003734
Jim Grosbach6f482002015-05-18 18:43:14 +00003735 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00003736 Sym->setVariableValue(Value);
3737
3738 return false;
3739}
Jack Carterd0bd6422013-04-18 00:41:53 +00003740
Toma Tabacu26647792014-09-09 12:52:14 +00003741bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003742 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00003743 Parser.Lex();
3744 if (getLexer().isNot(AsmToken::EndOfStatement))
3745 return reportParseError("unexpected token, expected end of statement");
3746
3747 // Reset assembler options to their initial values.
Toma Tabacu465acfd2015-06-09 13:33:26 +00003748 setAvailableFeatures(
3749 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
3750 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00003751 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
3752
3753 getTargetStreamer().emitDirectiveSetMips0();
3754 return false;
3755}
3756
Toma Tabacu85618b32014-08-19 14:22:52 +00003757bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003758 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00003759 Parser.Lex();
3760 if (getLexer().isNot(AsmToken::Equal))
3761 return reportParseError("unexpected token, expected equals sign");
3762
3763 Parser.Lex();
3764 StringRef Arch;
3765 if (Parser.parseIdentifier(Arch))
3766 return reportParseError("expected arch identifier");
3767
3768 StringRef ArchFeatureName =
3769 StringSwitch<StringRef>(Arch)
3770 .Case("mips1", "mips1")
3771 .Case("mips2", "mips2")
3772 .Case("mips3", "mips3")
3773 .Case("mips4", "mips4")
3774 .Case("mips5", "mips5")
3775 .Case("mips32", "mips32")
3776 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003777 .Case("mips32r3", "mips32r3")
3778 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003779 .Case("mips32r6", "mips32r6")
3780 .Case("mips64", "mips64")
3781 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003782 .Case("mips64r3", "mips64r3")
3783 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003784 .Case("mips64r6", "mips64r6")
3785 .Case("cnmips", "cnmips")
3786 .Case("r4000", "mips3") // This is an implementation of Mips3.
3787 .Default("");
3788
3789 if (ArchFeatureName.empty())
3790 return reportParseError("unsupported architecture");
3791
3792 selectArch(ArchFeatureName);
3793 getTargetStreamer().emitDirectiveSetArch(Arch);
3794 return false;
3795}
3796
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003797bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003798 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003799 Parser.Lex();
3800 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003801 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003802
Matheus Almeida2852af82014-04-22 10:15:54 +00003803 switch (Feature) {
3804 default:
3805 llvm_unreachable("Unimplemented feature");
3806 case Mips::FeatureDSP:
3807 setFeatureBits(Mips::FeatureDSP, "dsp");
3808 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003809 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003810 case Mips::FeatureMicroMips:
3811 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003812 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003813 case Mips::FeatureMips1:
3814 selectArch("mips1");
3815 getTargetStreamer().emitDirectiveSetMips1();
3816 break;
3817 case Mips::FeatureMips2:
3818 selectArch("mips2");
3819 getTargetStreamer().emitDirectiveSetMips2();
3820 break;
3821 case Mips::FeatureMips3:
3822 selectArch("mips3");
3823 getTargetStreamer().emitDirectiveSetMips3();
3824 break;
3825 case Mips::FeatureMips4:
3826 selectArch("mips4");
3827 getTargetStreamer().emitDirectiveSetMips4();
3828 break;
3829 case Mips::FeatureMips5:
3830 selectArch("mips5");
3831 getTargetStreamer().emitDirectiveSetMips5();
3832 break;
3833 case Mips::FeatureMips32:
3834 selectArch("mips32");
3835 getTargetStreamer().emitDirectiveSetMips32();
3836 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003837 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003838 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003839 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003840 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003841 case Mips::FeatureMips32r3:
3842 selectArch("mips32r3");
3843 getTargetStreamer().emitDirectiveSetMips32R3();
3844 break;
3845 case Mips::FeatureMips32r5:
3846 selectArch("mips32r5");
3847 getTargetStreamer().emitDirectiveSetMips32R5();
3848 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003849 case Mips::FeatureMips32r6:
3850 selectArch("mips32r6");
3851 getTargetStreamer().emitDirectiveSetMips32R6();
3852 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003853 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003854 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00003855 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003856 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003857 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003858 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003859 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003860 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003861 case Mips::FeatureMips64r3:
3862 selectArch("mips64r3");
3863 getTargetStreamer().emitDirectiveSetMips64R3();
3864 break;
3865 case Mips::FeatureMips64r5:
3866 selectArch("mips64r5");
3867 getTargetStreamer().emitDirectiveSetMips64R5();
3868 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003869 case Mips::FeatureMips64r6:
3870 selectArch("mips64r6");
3871 getTargetStreamer().emitDirectiveSetMips64R6();
3872 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003873 }
3874 return false;
3875}
3876
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003877bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003878 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003879 if (getLexer().isNot(AsmToken::Comma)) {
3880 SMLoc Loc = getLexer().getLoc();
3881 Parser.eatToEndOfStatement();
3882 return Error(Loc, ErrorStr);
3883 }
3884
Matheus Almeida2852af82014-04-22 10:15:54 +00003885 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003886 return true;
3887}
3888
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003889bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003890 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00003891 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003892
Toma Tabacudde4c462014-11-06 10:02:45 +00003893 if (inMips16Mode()) {
3894 reportParseError(".cpload is not supported in Mips16 mode");
3895 return false;
3896 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003897
David Blaikie960ea3f2014-06-08 16:18:35 +00003898 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00003899 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003900 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3901 reportParseError("expected register containing function address");
3902 return false;
3903 }
3904
David Blaikie960ea3f2014-06-08 16:18:35 +00003905 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
3906 if (!RegOpnd.isGPRAsmReg()) {
3907 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003908 return false;
3909 }
3910
Toma Tabacudde4c462014-11-06 10:02:45 +00003911 // If this is not the end of the statement, report an error.
3912 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3913 reportParseError("unexpected token, expected end of statement");
3914 return false;
3915 }
3916
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003917 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003918 return false;
3919}
3920
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003921bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003922 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003923 unsigned FuncReg;
3924 unsigned Save;
3925 bool SaveIsReg = true;
3926
Matheus Almeida7e815762014-06-18 13:08:59 +00003927 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003928 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003929 if (ResTy == MatchOperand_NoMatch) {
3930 reportParseError("expected register containing function address");
3931 Parser.eatToEndOfStatement();
3932 return false;
3933 }
3934
3935 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3936 if (!FuncRegOpnd.isGPRAsmReg()) {
3937 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3938 Parser.eatToEndOfStatement();
3939 return false;
3940 }
3941
3942 FuncReg = FuncRegOpnd.getGPR32Reg();
3943 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003944
Toma Tabacu65f10572014-09-16 15:00:52 +00003945 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003946 return true;
3947
Toma Tabacu13964452014-09-04 13:23:44 +00003948 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003949 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003950 const AsmToken &Tok = Parser.getTok();
3951 if (Tok.is(AsmToken::Integer)) {
3952 Save = Tok.getIntVal();
3953 SaveIsReg = false;
3954 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003955 } else {
3956 reportParseError("expected save register or stack offset");
3957 Parser.eatToEndOfStatement();
3958 return false;
3959 }
3960 } else {
3961 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3962 if (!SaveOpnd.isGPRAsmReg()) {
3963 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3964 Parser.eatToEndOfStatement();
3965 return false;
3966 }
3967 Save = SaveOpnd.getGPR32Reg();
3968 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003969
Toma Tabacu65f10572014-09-16 15:00:52 +00003970 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003971 return true;
3972
Toma Tabacu8874eac2015-02-18 13:46:53 +00003973 const MCExpr *Expr;
3974 if (Parser.parseExpression(Expr)) {
3975 reportParseError("expected expression");
3976 return false;
3977 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003978
Toma Tabacu8874eac2015-02-18 13:46:53 +00003979 if (Expr->getKind() != MCExpr::SymbolRef) {
3980 reportParseError("expected symbol");
3981 return false;
3982 }
3983 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
3984
3985 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
3986 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003987 return false;
3988}
3989
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003990bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003991 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003992 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3993 const AsmToken &Tok = Parser.getTok();
3994
3995 if (Tok.getString() == "2008") {
3996 Parser.Lex();
3997 getTargetStreamer().emitDirectiveNaN2008();
3998 return false;
3999 } else if (Tok.getString() == "legacy") {
4000 Parser.Lex();
4001 getTargetStreamer().emitDirectiveNaNLegacy();
4002 return false;
4003 }
4004 }
4005 // If we don't recognize the option passed to the .nan
4006 // directive (e.g. no option or unknown option), emit an error.
4007 reportParseError("invalid option in .nan directive");
4008 return false;
4009}
4010
Jack Carter0b744b32012-10-04 02:29:46 +00004011bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004012 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004013 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00004014 const AsmToken &Tok = Parser.getTok();
4015
4016 if (Tok.getString() == "noat") {
4017 return parseSetNoAtDirective();
4018 } else if (Tok.getString() == "at") {
4019 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00004020 } else if (Tok.getString() == "arch") {
4021 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004022 } else if (Tok.getString() == "fp") {
4023 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004024 } else if (Tok.getString() == "pop") {
4025 return parseSetPopDirective();
4026 } else if (Tok.getString() == "push") {
4027 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00004028 } else if (Tok.getString() == "reorder") {
4029 return parseSetReorderDirective();
4030 } else if (Tok.getString() == "noreorder") {
4031 return parseSetNoReorderDirective();
4032 } else if (Tok.getString() == "macro") {
4033 return parseSetMacroDirective();
4034 } else if (Tok.getString() == "nomacro") {
4035 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00004036 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00004037 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00004038 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00004039 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00004040 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00004041 getTargetStreamer().emitDirectiveSetNoMicroMips();
4042 Parser.eatToEndOfStatement();
4043 return false;
4044 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004045 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00004046 } else if (Tok.getString() == "mips0") {
4047 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00004048 } else if (Tok.getString() == "mips1") {
4049 return parseSetFeature(Mips::FeatureMips1);
4050 } else if (Tok.getString() == "mips2") {
4051 return parseSetFeature(Mips::FeatureMips2);
4052 } else if (Tok.getString() == "mips3") {
4053 return parseSetFeature(Mips::FeatureMips3);
4054 } else if (Tok.getString() == "mips4") {
4055 return parseSetFeature(Mips::FeatureMips4);
4056 } else if (Tok.getString() == "mips5") {
4057 return parseSetFeature(Mips::FeatureMips5);
4058 } else if (Tok.getString() == "mips32") {
4059 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00004060 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004061 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00004062 } else if (Tok.getString() == "mips32r3") {
4063 return parseSetFeature(Mips::FeatureMips32r3);
4064 } else if (Tok.getString() == "mips32r5") {
4065 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00004066 } else if (Tok.getString() == "mips32r6") {
4067 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00004068 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004069 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00004070 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004071 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00004072 } else if (Tok.getString() == "mips64r3") {
4073 return parseSetFeature(Mips::FeatureMips64r3);
4074 } else if (Tok.getString() == "mips64r5") {
4075 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00004076 } else if (Tok.getString() == "mips64r6") {
4077 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00004078 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004079 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004080 } else if (Tok.getString() == "nodsp") {
4081 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00004082 } else if (Tok.getString() == "msa") {
4083 return parseSetMsaDirective();
4084 } else if (Tok.getString() == "nomsa") {
4085 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00004086 } else if (Tok.getString() == "softfloat") {
4087 return parseSetSoftFloatDirective();
4088 } else if (Tok.getString() == "hardfloat") {
4089 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00004090 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00004091 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00004092 parseSetAssignment();
4093 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004094 }
Jack Carter07c818d2013-01-25 01:31:34 +00004095
Jack Carter0b744b32012-10-04 02:29:46 +00004096 return true;
4097}
4098
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004099/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00004100/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004101bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004102 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004103 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4104 for (;;) {
4105 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004106 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00004107 return true;
4108
4109 getParser().getStreamer().EmitValue(Value, Size);
4110
4111 if (getLexer().is(AsmToken::EndOfStatement))
4112 break;
4113
Jack Carter07c818d2013-01-25 01:31:34 +00004114 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004115 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00004116 Parser.Lex();
4117 }
4118 }
4119
4120 Parser.Lex();
4121 return false;
4122}
4123
Vladimir Medic4c299852013-11-06 11:27:05 +00004124/// parseDirectiveGpWord
4125/// ::= .gpword local_sym
4126bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004127 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004128 const MCExpr *Value;
4129 // EmitGPRel32Value requires an expression, so we are using base class
4130 // method to evaluate the expression.
4131 if (getParser().parseExpression(Value))
4132 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00004133 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00004134
Vladimir Medice10c1122013-11-13 13:18:04 +00004135 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004136 return Error(getLexer().getLoc(),
4137 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00004138 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00004139 return false;
4140}
4141
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004142/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00004143/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004144bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004145 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004146 const MCExpr *Value;
4147 // EmitGPRel64Value requires an expression, so we are using base class
4148 // method to evaluate the expression.
4149 if (getParser().parseExpression(Value))
4150 return true;
4151 getParser().getStreamer().EmitGPRel64Value(Value);
4152
4153 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004154 return Error(getLexer().getLoc(),
4155 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00004156 Parser.Lex(); // Eat EndOfStatement token.
4157 return false;
4158}
4159
Jack Carter0cd3c192014-01-06 23:27:31 +00004160bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004161 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00004162 // Get the option token.
4163 AsmToken Tok = Parser.getTok();
4164 // At the moment only identifiers are supported.
4165 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004166 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00004167 Parser.eatToEndOfStatement();
4168 return false;
4169 }
4170
4171 StringRef Option = Tok.getIdentifier();
4172
4173 if (Option == "pic0") {
4174 getTargetStreamer().emitDirectiveOptionPic0();
4175 Parser.Lex();
4176 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4177 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004178 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004179 Parser.eatToEndOfStatement();
4180 }
4181 return false;
4182 }
4183
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004184 if (Option == "pic2") {
4185 getTargetStreamer().emitDirectiveOptionPic2();
4186 Parser.Lex();
4187 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4188 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004189 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004190 Parser.eatToEndOfStatement();
4191 }
4192 return false;
4193 }
4194
Jack Carter0cd3c192014-01-06 23:27:31 +00004195 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00004196 Warning(Parser.getTok().getLoc(),
4197 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00004198 Parser.eatToEndOfStatement();
4199 return false;
4200}
4201
Toma Tabacu9ca50962015-04-16 09:53:47 +00004202/// parseInsnDirective
4203/// ::= .insn
4204bool MipsAsmParser::parseInsnDirective() {
4205 // If this is not the end of the statement, report an error.
4206 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4207 reportParseError("unexpected token, expected end of statement");
4208 return false;
4209 }
4210
4211 // The actual label marking happens in
4212 // MipsELFStreamer::createPendingLabelRelocs().
4213 getTargetStreamer().emitDirectiveInsn();
4214
4215 getParser().Lex(); // Eat EndOfStatement token.
4216 return false;
4217}
4218
Daniel Sanders7e527422014-07-10 13:38:23 +00004219/// parseDirectiveModule
4220/// ::= .module oddspreg
4221/// ::= .module nooddspreg
4222/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004223bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004224 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004225 MCAsmLexer &Lexer = getLexer();
4226 SMLoc L = Lexer.getLoc();
4227
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004228 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004229 // TODO : get a better message.
4230 reportParseError(".module directive must appear before any code");
4231 return false;
4232 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004233
Toma Tabacuc405c822015-01-23 10:40:19 +00004234 StringRef Option;
4235 if (Parser.parseIdentifier(Option)) {
4236 reportParseError("expected .module option identifier");
4237 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004238 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004239
Toma Tabacuc405c822015-01-23 10:40:19 +00004240 if (Option == "oddspreg") {
4241 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
4242 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4243
4244 // If this is not the end of the statement, report an error.
4245 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4246 reportParseError("unexpected token, expected end of statement");
4247 return false;
4248 }
4249
4250 return false; // parseDirectiveModule has finished successfully.
4251 } else if (Option == "nooddspreg") {
4252 if (!isABI_O32()) {
4253 Error(L, "'.module nooddspreg' requires the O32 ABI");
4254 return false;
4255 }
4256
4257 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
4258 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4259
4260 // If this is not the end of the statement, report an error.
4261 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4262 reportParseError("unexpected token, expected end of statement");
4263 return false;
4264 }
4265
4266 return false; // parseDirectiveModule has finished successfully.
4267 } else if (Option == "fp") {
4268 return parseDirectiveModuleFP();
4269 } else {
4270 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
4271 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004272}
4273
4274/// parseDirectiveModuleFP
4275/// ::= =32
4276/// ::= =xx
4277/// ::= =64
4278bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004279 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004280 MCAsmLexer &Lexer = getLexer();
4281
4282 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004283 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004284 return false;
4285 }
4286 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004287
Daniel Sanders7e527422014-07-10 13:38:23 +00004288 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004289 if (!parseFpABIValue(FpABI, ".module"))
4290 return false;
4291
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004292 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004293 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004294 return false;
4295 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004296
Daniel Sanders7201a3e2014-07-08 10:35:52 +00004297 // Emit appropriate flags.
4298 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00004299 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004300 return false;
4301}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004302
Daniel Sanders7e527422014-07-10 13:38:23 +00004303bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004304 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004305 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004306 MCAsmLexer &Lexer = getLexer();
4307
4308 if (Lexer.is(AsmToken::Identifier)) {
4309 StringRef Value = Parser.getTok().getString();
4310 Parser.Lex();
4311
4312 if (Value != "xx") {
4313 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4314 return false;
4315 }
4316
4317 if (!isABI_O32()) {
4318 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
4319 return false;
4320 }
4321
Daniel Sanders7e527422014-07-10 13:38:23 +00004322 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004323 return true;
4324 }
4325
4326 if (Lexer.is(AsmToken::Integer)) {
4327 unsigned Value = Parser.getTok().getIntVal();
4328 Parser.Lex();
4329
4330 if (Value != 32 && Value != 64) {
4331 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4332 return false;
4333 }
4334
4335 if (Value == 32) {
4336 if (!isABI_O32()) {
4337 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
4338 return false;
4339 }
4340
Daniel Sanders7e527422014-07-10 13:38:23 +00004341 FpABI = MipsABIFlagsSection::FpABIKind::S32;
4342 } else
4343 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004344
Daniel Sanders7e527422014-07-10 13:38:23 +00004345 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004346 }
4347
4348 return false;
4349}
4350
Jack Carter0b744b32012-10-04 02:29:46 +00004351bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004352 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004353 StringRef IDVal = DirectiveID.getString();
4354
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004355 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004356 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00004357 if (IDVal == ".dword") {
4358 parseDataDirective(8, DirectiveID.getLoc());
4359 return false;
4360 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004361 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004362 StringRef SymbolName;
4363
4364 if (Parser.parseIdentifier(SymbolName)) {
4365 reportParseError("expected identifier after .ent");
4366 return false;
4367 }
4368
4369 // There's an undocumented extension that allows an integer to
4370 // follow the name of the procedure which AFAICS is ignored by GAS.
4371 // Example: .ent foo,2
4372 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4373 if (getLexer().isNot(AsmToken::Comma)) {
4374 // Even though we accept this undocumented extension for compatibility
4375 // reasons, the additional integer argument does not actually change
4376 // the behaviour of the '.ent' directive, so we would like to discourage
4377 // its use. We do this by not referring to the extended version in
4378 // error messages which are not directly related to its use.
4379 reportParseError("unexpected token, expected end of statement");
4380 return false;
4381 }
4382 Parser.Lex(); // Eat the comma.
4383 const MCExpr *DummyNumber;
4384 int64_t DummyNumberVal;
4385 // If the user was explicitly trying to use the extended version,
4386 // we still give helpful extension-related error messages.
4387 if (Parser.parseExpression(DummyNumber)) {
4388 reportParseError("expected number after comma");
4389 return false;
4390 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00004391 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004392 reportParseError("expected an absolute expression after comma");
4393 return false;
4394 }
4395 }
4396
4397 // If this is not the end of the statement, report an error.
4398 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4399 reportParseError("unexpected token, expected end of statement");
4400 return false;
4401 }
4402
Jim Grosbach6f482002015-05-18 18:43:14 +00004403 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004404
4405 getTargetStreamer().emitDirectiveEnt(*Sym);
4406 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00004407 return false;
4408 }
4409
Jack Carter07c818d2013-01-25 01:31:34 +00004410 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004411 StringRef SymbolName;
4412
4413 if (Parser.parseIdentifier(SymbolName)) {
4414 reportParseError("expected identifier after .end");
4415 return false;
4416 }
4417
4418 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4419 reportParseError("unexpected token, expected end of statement");
4420 return false;
4421 }
4422
4423 if (CurrentFn == nullptr) {
4424 reportParseError(".end used without .ent");
4425 return false;
4426 }
4427
4428 if ((SymbolName != CurrentFn->getName())) {
4429 reportParseError(".end symbol does not match .ent symbol");
4430 return false;
4431 }
4432
4433 getTargetStreamer().emitDirectiveEnd(SymbolName);
4434 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00004435 return false;
4436 }
4437
Jack Carter07c818d2013-01-25 01:31:34 +00004438 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004439 // .frame $stack_reg, frame_size_in_bytes, $return_reg
4440 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004441 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004442 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4443 reportParseError("expected stack register");
4444 return false;
4445 }
4446
4447 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4448 if (!StackRegOpnd.isGPRAsmReg()) {
4449 reportParseError(StackRegOpnd.getStartLoc(),
4450 "expected general purpose register");
4451 return false;
4452 }
4453 unsigned StackReg = StackRegOpnd.getGPR32Reg();
4454
4455 if (Parser.getTok().is(AsmToken::Comma))
4456 Parser.Lex();
4457 else {
4458 reportParseError("unexpected token, expected comma");
4459 return false;
4460 }
4461
4462 // Parse the frame size.
4463 const MCExpr *FrameSize;
4464 int64_t FrameSizeVal;
4465
4466 if (Parser.parseExpression(FrameSize)) {
4467 reportParseError("expected frame size value");
4468 return false;
4469 }
4470
Jim Grosbach13760bd2015-05-30 01:25:56 +00004471 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004472 reportParseError("frame size not an absolute expression");
4473 return false;
4474 }
4475
4476 if (Parser.getTok().is(AsmToken::Comma))
4477 Parser.Lex();
4478 else {
4479 reportParseError("unexpected token, expected comma");
4480 return false;
4481 }
4482
4483 // Parse the return register.
4484 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00004485 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004486 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4487 reportParseError("expected return register");
4488 return false;
4489 }
4490
4491 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4492 if (!ReturnRegOpnd.isGPRAsmReg()) {
4493 reportParseError(ReturnRegOpnd.getStartLoc(),
4494 "expected general purpose register");
4495 return false;
4496 }
4497
4498 // If this is not the end of the statement, report an error.
4499 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4500 reportParseError("unexpected token, expected end of statement");
4501 return false;
4502 }
4503
4504 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
4505 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00004506 return false;
4507 }
4508
Jack Carter07c818d2013-01-25 01:31:34 +00004509 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00004510 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00004511 }
4512
Daniel Sandersd97a6342014-08-13 10:07:34 +00004513 if (IDVal == ".mask" || IDVal == ".fmask") {
4514 // .mask bitmask, frame_offset
4515 // bitmask: One bit for each register used.
4516 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
4517 // first register is expected to be saved.
4518 // Examples:
4519 // .mask 0x80000000, -4
4520 // .fmask 0x80000000, -4
4521 //
Jack Carterbe332172012-09-07 00:48:02 +00004522
Daniel Sandersd97a6342014-08-13 10:07:34 +00004523 // Parse the bitmask
4524 const MCExpr *BitMask;
4525 int64_t BitMaskVal;
4526
4527 if (Parser.parseExpression(BitMask)) {
4528 reportParseError("expected bitmask value");
4529 return false;
4530 }
4531
Jim Grosbach13760bd2015-05-30 01:25:56 +00004532 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004533 reportParseError("bitmask not an absolute expression");
4534 return false;
4535 }
4536
4537 if (Parser.getTok().is(AsmToken::Comma))
4538 Parser.Lex();
4539 else {
4540 reportParseError("unexpected token, expected comma");
4541 return false;
4542 }
4543
4544 // Parse the frame_offset
4545 const MCExpr *FrameOffset;
4546 int64_t FrameOffsetVal;
4547
4548 if (Parser.parseExpression(FrameOffset)) {
4549 reportParseError("expected frame offset value");
4550 return false;
4551 }
4552
Jim Grosbach13760bd2015-05-30 01:25:56 +00004553 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004554 reportParseError("frame offset not an absolute expression");
4555 return false;
4556 }
4557
4558 // If this is not the end of the statement, report an error.
4559 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4560 reportParseError("unexpected token, expected end of statement");
4561 return false;
4562 }
4563
4564 if (IDVal == ".mask")
4565 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
4566 else
4567 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00004568 return false;
4569 }
4570
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004571 if (IDVal == ".nan")
4572 return parseDirectiveNaN();
4573
Jack Carter07c818d2013-01-25 01:31:34 +00004574 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004575 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00004576 return false;
4577 }
4578
Rafael Espindolab59fb732014-03-28 18:50:26 +00004579 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004580 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004581 return false;
4582 }
4583
Jack Carter07c818d2013-01-25 01:31:34 +00004584 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004585 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00004586 return false;
4587 }
4588
Jack Carter0cd3c192014-01-06 23:27:31 +00004589 if (IDVal == ".option")
4590 return parseDirectiveOption();
4591
4592 if (IDVal == ".abicalls") {
4593 getTargetStreamer().emitDirectiveAbiCalls();
4594 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004595 Error(Parser.getTok().getLoc(),
4596 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004597 // Clear line
4598 Parser.eatToEndOfStatement();
4599 }
4600 return false;
4601 }
4602
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004603 if (IDVal == ".cpsetup")
4604 return parseDirectiveCPSetup();
4605
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004606 if (IDVal == ".module")
4607 return parseDirectiveModule();
4608
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004609 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
4610 return parseInternalDirectiveReallowModule();
4611
Toma Tabacu9ca50962015-04-16 09:53:47 +00004612 if (IDVal == ".insn")
4613 return parseInsnDirective();
4614
Rafael Espindola870c4e92012-01-11 03:56:41 +00004615 return true;
4616}
4617
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004618bool MipsAsmParser::parseInternalDirectiveReallowModule() {
4619 // If this is not the end of the statement, report an error.
4620 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4621 reportParseError("unexpected token, expected end of statement");
4622 return false;
4623 }
4624
4625 getTargetStreamer().reallowModuleDirective();
4626
4627 getParser().Lex(); // Eat EndOfStatement token.
4628 return false;
4629}
4630
Rafael Espindola870c4e92012-01-11 03:56:41 +00004631extern "C" void LLVMInitializeMipsAsmParser() {
4632 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
4633 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
4634 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
4635 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
4636}
Jack Carterb4dbc172012-09-05 23:34:03 +00004637
4638#define GET_REGISTER_MATCHER
4639#define GET_MATCHER_IMPLEMENTATION
4640#include "MipsGenAsmMatcher.inc"