blob: 46c73c7be600a42fb8f8ecc6ca960ae561246891 [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Eric Christophera5762812015-01-26 17:33:46 +000010#include "MCTargetDesc/MipsABIInfo.h"
Petar Jovanovica5da5882014-02-04 18:41:57 +000011#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000012#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000013#include "MipsRegisterInfo.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000014#include "MipsTargetStreamer.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000015#include "llvm/ADT/APInt.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000016#include "llvm/ADT/SmallVector.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000017#include "llvm/ADT/StringSwitch.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000018#include "llvm/MC/MCContext.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000021#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000022#include "llvm/MC/MCParser/MCAsmLexer.h"
23#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000024#include "llvm/MC/MCStreamer.h"
25#include "llvm/MC/MCSubtargetInfo.h"
26#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000027#include "llvm/MC/MCTargetAsmParser.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000028#include "llvm/Support/Debug.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000029#include "llvm/Support/MathExtras.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000030#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000031#include "llvm/Support/TargetRegistry.h"
Benjamin Kramer799003b2015-03-23 19:32:43 +000032#include "llvm/Support/raw_ostream.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000033#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000034
35using namespace llvm;
36
Chandler Carruthe96dd892014-04-21 22:55:11 +000037#define DEBUG_TYPE "mips-asm-parser"
38
Joey Gouly0e76fa72013-09-12 10:28:05 +000039namespace llvm {
40class MCInstrInfo;
41}
42
Rafael Espindola870c4e92012-01-11 03:56:41 +000043namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000044class MipsAssemblerOptions {
45public:
Toma Tabacu9db22db2014-09-09 10:15:38 +000046 MipsAssemblerOptions(uint64_t Features_) :
47 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000048
Toma Tabacu9db22db2014-09-09 10:15:38 +000049 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000050 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000051 Reorder = Opts->isReorder();
52 Macro = Opts->isMacro();
53 Features = Opts->getFeatures();
54 }
55
Toma Tabacub19cf202015-04-27 13:12:59 +000056 unsigned getATRegIndex() const { return ATReg; }
57 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000058 if (Reg > 31)
59 return false;
60
61 ATReg = Reg;
62 return true;
63 }
Jack Carter0b744b32012-10-04 02:29:46 +000064
Toma Tabacu9db22db2014-09-09 10:15:38 +000065 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000066 void setReorder() { Reorder = true; }
67 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000068
Toma Tabacu9db22db2014-09-09 10:15:38 +000069 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000070 void setMacro() { Macro = true; }
71 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000072
Toma Tabacu9db22db2014-09-09 10:15:38 +000073 uint64_t getFeatures() const { return Features; }
74 void setFeatures(uint64_t Features_) { Features = Features_; }
75
Daniel Sandersf0df2212014-08-04 12:20:00 +000076 // Set of features that are either architecture features or referenced
77 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
78 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
79 // The reason we need this mask is explained in the selectArch function.
80 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteinaba4a342015-05-13 08:27:08 +000081 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +000082
Jack Carter0b744b32012-10-04 02:29:46 +000083private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000084 unsigned ATReg;
85 bool Reorder;
86 bool Macro;
Toma Tabacu9db22db2014-09-09 10:15:38 +000087 uint64_t Features;
Jack Carter0b744b32012-10-04 02:29:46 +000088};
89}
90
Michael Kupersteinaba4a342015-05-13 08:27:08 +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 Tabacu00e98672015-05-01 12:19:27 +0000185 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000186 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000187
188 bool expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000189 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000190
191 bool expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000192 SmallVectorImpl<MCInst> &Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000193 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
194 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000195
Toma Tabacu0d64b202014-08-14 10:29:17 +0000196 void expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
197 SmallVectorImpl<MCInst> &Instructions);
198
Jack Carter9e65aa32013-03-22 00:05:30 +0000199 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000200 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
201 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000202
203 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
204 SmallVectorImpl<MCInst> &Instructions);
205
Toma Tabacu234482a2015-03-16 12:03:39 +0000206 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
207 SmallVectorImpl<MCInst> &Instructions);
208
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000209 bool reportParseError(Twine ErrorMsg);
210 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000211
Jack Carterb5cf5902013-04-17 00:18:04 +0000212 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000213 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000214
Vladimir Medic4c299852013-11-06 11:27:05 +0000215 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000216
217 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000218 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000219 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000220 bool parseSetFeature(uint64_t Feature);
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000221 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000222 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000223 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000224 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000225 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000226 bool parseInsnDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000227
228 bool parseSetAtDirective();
229 bool parseSetNoAtDirective();
230 bool parseSetMacroDirective();
231 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000232 bool parseSetMsaDirective();
233 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000234 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000235 bool parseSetReorderDirective();
236 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000237 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000238 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000239 bool parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000240 bool parseSetPopDirective();
241 bool parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000242
Jack Carterd76b2372013-03-21 21:44:16 +0000243 bool parseSetAssignment();
244
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000245 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000246 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000247 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000248 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000249 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000250 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
251 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000252
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000253 bool parseInternalDirectiveReallowModule();
254
Jack Carterdc1e35d2012-09-06 20:00:02 +0000255 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000256
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000257 bool eatComma(StringRef ErrorStr);
258
Jack Carter1ac53222013-02-20 23:11:17 +0000259 int matchCPURegisterName(StringRef Symbol);
260
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000261 int matchHWRegsRegisterName(StringRef Symbol);
262
Jack Carter873c7242013-01-12 01:03:14 +0000263 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000264
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000265 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000266
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000267 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000268
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000269 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000270
Jack Carter5dc8ac92013-09-25 23:50:44 +0000271 int matchMSA128RegisterName(StringRef Name);
272
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000273 int matchMSA128CtrlRegisterName(StringRef Name);
274
Jack Carterd0bd6422013-04-18 00:41:53 +0000275 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000276
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000277 unsigned getGPR(int RegNo);
278
Toma Tabacu89a712b2015-04-15 10:48:56 +0000279 /// Returns the internal register number for the current AT. Also checks if
280 /// the current AT is unavailable (set to $0) and gives an error if it is.
281 /// This should be used in pseudo-instruction expansions which need AT.
282 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000283
284 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000285 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000286
287 // Helper function that checks if the value of a vector index is within the
288 // boundaries of accepted values for each RegisterKind
289 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
290 bool validateMSAIndex(int Val, int RegKind);
291
Daniel Sandersf0df2212014-08-04 12:20:00 +0000292 // Selects a new architecture by updating the FeatureBits with the necessary
293 // info including implied dependencies.
294 // Internally, it clears all the feature bits related to *any* architecture
295 // and selects the new one using the ToggleFeature functionality of the
296 // MCSubtargetInfo object that handles implied dependencies. The reason we
297 // clear all the arch related bits manually is because ToggleFeature only
298 // clears the features that imply the feature being cleared and not the
299 // features implied by the feature being cleared. This is easier to see
300 // with an example:
301 // --------------------------------------------------
302 // | Feature | Implies |
303 // | -------------------------------------------------|
304 // | FeatureMips1 | None |
305 // | FeatureMips2 | FeatureMips1 |
306 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
307 // | FeatureMips4 | FeatureMips3 |
308 // | ... | |
309 // --------------------------------------------------
310 //
311 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
312 // FeatureMipsGP64 | FeatureMips1)
313 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
314 void selectArch(StringRef ArchFeature) {
Michael Kupersteinaba4a342015-05-13 08:27:08 +0000315 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000316 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
317 STI.setFeatureBits(FeatureBits);
318 setAvailableFeatures(
319 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000320 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000321 }
322
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000323 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteinaba4a342015-05-13 08:27:08 +0000324 if (!(STI.getFeatureBits()[Feature])) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000325 setAvailableFeatures(
326 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000327 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000328 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000329 }
330
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000331 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteinaba4a342015-05-13 08:27:08 +0000332 if (STI.getFeatureBits()[Feature]) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000333 setAvailableFeatures(
334 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000335 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000336 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000337 }
338
Rafael Espindola870c4e92012-01-11 03:56:41 +0000339public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000340 enum MipsMatchResultTy {
341 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
342#define GET_OPERAND_DIAGNOSTIC_TYPES
343#include "MipsGenAsmMatcher.inc"
344#undef GET_OPERAND_DIAGNOSTIC_TYPES
345
346 };
347
Joey Gouly0e76fa72013-09-12 10:28:05 +0000348 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000349 const MCInstrInfo &MII, const MCTargetOptions &Options)
Eric Christophera5762812015-01-26 17:33:46 +0000350 : MCTargetAsmParser(), STI(sti),
351 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
352 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000353 MCAsmParserExtension::Initialize(parser);
354
Toma Tabacu11e14a92015-04-21 11:50:52 +0000355 parser.addAliasForDirective(".asciiz", ".asciz");
356
Jack Carterb4dbc172012-09-05 23:34:03 +0000357 // Initialize the set of available features.
358 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000359
360 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000361 AssemblerOptions.push_back(
362 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000363
364 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000365 AssemblerOptions.push_back(
366 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000367
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000368 getTargetStreamer().updateABIInfo(*this);
369
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000370 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000371 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000372
373 CurrentFn = nullptr;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000374 }
375
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000376 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
377 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
378
Michael Kupersteinaba4a342015-05-13 08:27:08 +0000379 bool isGP64bit() const { return STI.getFeatureBits()[Mips::FeatureGP64Bit]; }
380 bool isFP64bit() const { return STI.getFeatureBits()[Mips::FeatureFP64Bit]; }
Eric Christophera5762812015-01-26 17:33:46 +0000381 const MipsABIInfo &getABI() const { return ABI; }
382 bool isABI_N32() const { return ABI.IsN32(); }
383 bool isABI_N64() const { return ABI.IsN64(); }
384 bool isABI_O32() const { return ABI.IsO32(); }
Michael Kupersteinaba4a342015-05-13 08:27:08 +0000385 bool isABI_FPXX() const { return STI.getFeatureBits()[Mips::FeatureFPXX]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000386
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000387 bool useOddSPReg() const {
Michael Kupersteinaba4a342015-05-13 08:27:08 +0000388 return !(STI.getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000389 }
390
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000391 bool inMicroMipsMode() const {
Michael Kupersteinaba4a342015-05-13 08:27:08 +0000392 return STI.getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000393 }
Michael Kupersteinaba4a342015-05-13 08:27:08 +0000394 bool hasMips1() const { return STI.getFeatureBits()[Mips::FeatureMips1]; }
395 bool hasMips2() const { return STI.getFeatureBits()[Mips::FeatureMips2]; }
396 bool hasMips3() const { return STI.getFeatureBits()[Mips::FeatureMips3]; }
397 bool hasMips4() const { return STI.getFeatureBits()[Mips::FeatureMips4]; }
398 bool hasMips5() const { return STI.getFeatureBits()[Mips::FeatureMips5]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000399 bool hasMips32() const {
Michael Kupersteinaba4a342015-05-13 08:27:08 +0000400 return STI.getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000401 }
402 bool hasMips64() const {
Michael Kupersteinaba4a342015-05-13 08:27:08 +0000403 return STI.getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000404 }
405 bool hasMips32r2() const {
Michael Kupersteinaba4a342015-05-13 08:27:08 +0000406 return STI.getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000407 }
408 bool hasMips64r2() const {
Michael Kupersteinaba4a342015-05-13 08:27:08 +0000409 return STI.getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000410 }
Daniel Sanders17793142015-02-18 16:24:50 +0000411 bool hasMips32r3() const {
Michael Kupersteinaba4a342015-05-13 08:27:08 +0000412 return (STI.getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000413 }
414 bool hasMips64r3() const {
Michael Kupersteinaba4a342015-05-13 08:27:08 +0000415 return (STI.getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000416 }
417 bool hasMips32r5() const {
Michael Kupersteinaba4a342015-05-13 08:27:08 +0000418 return (STI.getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000419 }
420 bool hasMips64r5() const {
Michael Kupersteinaba4a342015-05-13 08:27:08 +0000421 return (STI.getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000422 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000423 bool hasMips32r6() const {
Michael Kupersteinaba4a342015-05-13 08:27:08 +0000424 return STI.getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000425 }
426 bool hasMips64r6() const {
Michael Kupersteinaba4a342015-05-13 08:27:08 +0000427 return STI.getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000428 }
Michael Kupersteinaba4a342015-05-13 08:27:08 +0000429
430 bool hasDSP() const { return STI.getFeatureBits()[Mips::FeatureDSP]; }
431 bool hasDSPR2() const { return STI.getFeatureBits()[Mips::FeatureDSPR2]; }
432 bool hasMSA() const { return STI.getFeatureBits()[Mips::FeatureMSA]; }
Kai Nackee0245392015-01-27 19:11:28 +0000433 bool hasCnMips() const {
Michael Kupersteinaba4a342015-05-13 08:27:08 +0000434 return (STI.getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000435 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000436
437 bool inMips16Mode() const {
Michael Kupersteinaba4a342015-05-13 08:27:08 +0000438 return STI.getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000439 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000440
Eric Christophere8ae3e32015-05-07 23:10:21 +0000441 bool useSoftFloat() const {
Michael Kupersteinaba4a342015-05-13 08:27:08 +0000442 return STI.getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000443 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000444
Toma Tabacud9d344b2015-04-27 14:05:04 +0000445 /// Warn if RegIndex is the same as the current AT.
446 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000447};
448}
449
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000450namespace {
451
452/// MipsOperand - Instances of this class represent a parsed Mips machine
453/// instruction.
454class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000455public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000456 /// Broad categories of register classes
457 /// The exact class is finalized by the render method.
458 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000459 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000460 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000461 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000462 RegKind_FCC = 4, /// FCC
463 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
464 RegKind_MSACtrl = 16, /// MSA control registers
465 RegKind_COP2 = 32, /// COP2
466 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
467 /// context).
468 RegKind_CCR = 128, /// CCR
469 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000470 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000471
472 /// Potentially any (e.g. $1)
473 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
474 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000475 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000476 };
477
478private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000479 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000480 k_Immediate, /// An immediate (possibly involving symbol references)
481 k_Memory, /// Base + Offset Memory Address
482 k_PhysRegister, /// A physical register from the Mips namespace
483 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000484 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000485 k_RegList, /// A physical register list
486 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000487 } Kind;
488
David Blaikie960ea3f2014-06-08 16:18:35 +0000489public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000490 MipsOperand(KindTy K, MipsAsmParser &Parser)
491 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
492
David Blaikie960ea3f2014-06-08 16:18:35 +0000493private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000494 /// For diagnostics, and checking the assembler temporary
495 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000496
Eric Christopher8996c5d2013-03-15 00:42:55 +0000497 struct Token {
498 const char *Data;
499 unsigned Length;
500 };
501
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000502 struct PhysRegOp {
503 unsigned Num; /// Register Number
504 };
505
506 struct RegIdxOp {
507 unsigned Index; /// Index into the register class
508 RegKind Kind; /// Bitfield of the kinds it could possibly be
509 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000510 };
511
512 struct ImmOp {
513 const MCExpr *Val;
514 };
515
516 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000517 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000518 const MCExpr *Off;
519 };
520
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000521 struct RegListOp {
522 SmallVector<unsigned, 10> *List;
523 };
524
Jack Carterb4dbc172012-09-05 23:34:03 +0000525 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000526 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000527 struct PhysRegOp PhysReg;
528 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000529 struct ImmOp Imm;
530 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000531 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000532 };
533
534 SMLoc StartLoc, EndLoc;
535
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000536 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000537 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
538 const MCRegisterInfo *RegInfo,
539 SMLoc S, SMLoc E,
540 MipsAsmParser &Parser) {
541 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000542 Op->RegIdx.Index = Index;
543 Op->RegIdx.RegInfo = RegInfo;
544 Op->RegIdx.Kind = RegKind;
545 Op->StartLoc = S;
546 Op->EndLoc = E;
547 return Op;
548 }
549
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000550public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000551 /// Coerce the register to GPR32 and return the real register for the current
552 /// target.
553 unsigned getGPR32Reg() const {
554 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000555 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000556 unsigned ClassID = Mips::GPR32RegClassID;
557 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000558 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000559
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000560 /// Coerce the register to GPR32 and return the real register for the current
561 /// target.
562 unsigned getGPRMM16Reg() const {
563 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
564 unsigned ClassID = Mips::GPR32RegClassID;
565 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
566 }
567
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000568 /// Coerce the register to GPR64 and return the real register for the current
569 /// target.
570 unsigned getGPR64Reg() const {
571 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
572 unsigned ClassID = Mips::GPR64RegClassID;
573 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000574 }
575
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000576private:
577 /// Coerce the register to AFGR64 and return the real register for the current
578 /// target.
579 unsigned getAFGR64Reg() const {
580 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
581 if (RegIdx.Index % 2 != 0)
582 AsmParser.Warning(StartLoc, "Float register should be even.");
583 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
584 .getRegister(RegIdx.Index / 2);
585 }
586
587 /// Coerce the register to FGR64 and return the real register for the current
588 /// target.
589 unsigned getFGR64Reg() const {
590 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
591 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
592 .getRegister(RegIdx.Index);
593 }
594
595 /// Coerce the register to FGR32 and return the real register for the current
596 /// target.
597 unsigned getFGR32Reg() const {
598 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
599 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
600 .getRegister(RegIdx.Index);
601 }
602
603 /// Coerce the register to FGRH32 and return the real register for the current
604 /// target.
605 unsigned getFGRH32Reg() const {
606 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
607 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
608 .getRegister(RegIdx.Index);
609 }
610
611 /// Coerce the register to FCC and return the real register for the current
612 /// target.
613 unsigned getFCCReg() const {
614 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
615 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
616 .getRegister(RegIdx.Index);
617 }
618
619 /// Coerce the register to MSA128 and return the real register for the current
620 /// target.
621 unsigned getMSA128Reg() const {
622 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
623 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
624 // identical
625 unsigned ClassID = Mips::MSA128BRegClassID;
626 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
627 }
628
629 /// Coerce the register to MSACtrl and return the real register for the
630 /// current target.
631 unsigned getMSACtrlReg() const {
632 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
633 unsigned ClassID = Mips::MSACtrlRegClassID;
634 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
635 }
636
637 /// Coerce the register to COP2 and return the real register for the
638 /// current target.
639 unsigned getCOP2Reg() const {
640 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
641 unsigned ClassID = Mips::COP2RegClassID;
642 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
643 }
644
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000645 /// Coerce the register to COP3 and return the real register for the
646 /// current target.
647 unsigned getCOP3Reg() const {
648 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
649 unsigned ClassID = Mips::COP3RegClassID;
650 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
651 }
652
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000653 /// Coerce the register to ACC64DSP and return the real register for the
654 /// current target.
655 unsigned getACC64DSPReg() const {
656 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
657 unsigned ClassID = Mips::ACC64DSPRegClassID;
658 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
659 }
660
661 /// Coerce the register to HI32DSP and return the real register for the
662 /// current target.
663 unsigned getHI32DSPReg() const {
664 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
665 unsigned ClassID = Mips::HI32DSPRegClassID;
666 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
667 }
668
669 /// Coerce the register to LO32DSP and return the real register for the
670 /// current target.
671 unsigned getLO32DSPReg() const {
672 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
673 unsigned ClassID = Mips::LO32DSPRegClassID;
674 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
675 }
676
677 /// Coerce the register to CCR and return the real register for the
678 /// current target.
679 unsigned getCCRReg() const {
680 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
681 unsigned ClassID = Mips::CCRRegClassID;
682 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
683 }
684
685 /// Coerce the register to HWRegs and return the real register for the
686 /// current target.
687 unsigned getHWRegsReg() const {
688 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
689 unsigned ClassID = Mips::HWRegsRegClassID;
690 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
691 }
692
693public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000694 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000695 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000696 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000697 Inst.addOperand(MCOperand::CreateImm(0));
698 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
699 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
700 else
701 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000702 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000703
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000704 void addRegOperands(MCInst &Inst, unsigned N) const {
705 llvm_unreachable("Use a custom parser instead");
706 }
707
Daniel Sanders21bce302014-04-01 12:35:23 +0000708 /// Render the operand to an MCInst as a GPR32
709 /// Asserts if the wrong number of operands are requested, or the operand
710 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000711 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
712 assert(N == 1 && "Invalid number of operands!");
713 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
714 }
715
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000716 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
717 assert(N == 1 && "Invalid number of operands!");
718 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
719 }
720
Jozef Kolek1904fa22014-11-24 14:25:53 +0000721 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
722 assert(N == 1 && "Invalid number of operands!");
723 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
724 }
725
Zoran Jovanovic41688672015-02-10 16:36:20 +0000726 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
727 assert(N == 1 && "Invalid number of operands!");
728 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
729 }
730
Daniel Sanders21bce302014-04-01 12:35:23 +0000731 /// Render the operand to an MCInst as a GPR64
732 /// Asserts if the wrong number of operands are requested, or the operand
733 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000734 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
735 assert(N == 1 && "Invalid number of operands!");
736 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
737 }
738
739 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
740 assert(N == 1 && "Invalid number of operands!");
741 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
742 }
743
744 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
745 assert(N == 1 && "Invalid number of operands!");
746 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
747 }
748
749 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
750 assert(N == 1 && "Invalid number of operands!");
751 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000752 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000753 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000754 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
755 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000756 }
757
758 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
759 assert(N == 1 && "Invalid number of operands!");
760 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
761 }
762
763 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
764 assert(N == 1 && "Invalid number of operands!");
765 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
766 }
767
768 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
769 assert(N == 1 && "Invalid number of operands!");
770 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
771 }
772
773 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
774 assert(N == 1 && "Invalid number of operands!");
775 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
776 }
777
778 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
779 assert(N == 1 && "Invalid number of operands!");
780 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
781 }
782
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000783 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
784 assert(N == 1 && "Invalid number of operands!");
785 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
786 }
787
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000788 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
789 assert(N == 1 && "Invalid number of operands!");
790 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
791 }
792
793 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
794 assert(N == 1 && "Invalid number of operands!");
795 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
796 }
797
798 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
799 assert(N == 1 && "Invalid number of operands!");
800 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
801 }
802
803 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
804 assert(N == 1 && "Invalid number of operands!");
805 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
806 }
807
808 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
809 assert(N == 1 && "Invalid number of operands!");
810 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
811 }
812
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000813 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000814 assert(N == 1 && "Invalid number of operands!");
815 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000816 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000817 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000818
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000819 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000820 assert(N == 2 && "Invalid number of operands!");
821
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000822 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000823
824 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000825 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000826 }
827
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000828 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
829 assert(N == 2 && "Invalid number of operands!");
830
831 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPRMM16Reg()));
832
833 const MCExpr *Expr = getMemOff();
834 addExpr(Inst, Expr);
835 }
836
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000837 void addRegListOperands(MCInst &Inst, unsigned N) const {
838 assert(N == 1 && "Invalid number of operands!");
839
840 for (auto RegNo : getRegList())
841 Inst.addOperand(MCOperand::CreateReg(RegNo));
842 }
843
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000844 void addRegPairOperands(MCInst &Inst, unsigned N) const {
845 assert(N == 2 && "Invalid number of operands!");
846 unsigned RegNo = getRegPair();
847 Inst.addOperand(MCOperand::CreateReg(RegNo++));
848 Inst.addOperand(MCOperand::CreateReg(RegNo));
849 }
850
Zoran Jovanovic41688672015-02-10 16:36:20 +0000851 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
852 assert(N == 2 && "Invalid number of operands!");
853 for (auto RegNo : getRegList())
854 Inst.addOperand(MCOperand::CreateReg(RegNo));
855 }
856
Craig Topper56c590a2014-04-29 07:58:02 +0000857 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000858 // As a special case until we sort out the definition of div/divu, pretend
859 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
860 if (isGPRAsmReg() && RegIdx.Index == 0)
861 return true;
862
863 return Kind == k_PhysRegister;
864 }
865 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000866 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000867 bool isConstantImm() const {
868 return isImm() && dyn_cast<MCConstantExpr>(getImm());
869 }
Craig Topper56c590a2014-04-29 07:58:02 +0000870 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000871 // Note: It's not possible to pretend that other operand kinds are tokens.
872 // The matcher emitter checks tokens first.
873 return Kind == k_Token;
874 }
Craig Topper56c590a2014-04-29 07:58:02 +0000875 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000876 bool isConstantMemOff() const {
877 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
878 }
879 template <unsigned Bits> bool isMemWithSimmOffset() const {
880 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
881 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000882 bool isMemWithGRPMM16Base() const {
883 return isMem() && getMemBase()->isMM16AsmReg();
884 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000885 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
886 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
887 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
888 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000889 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
890 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
891 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
892 && (getMemBase()->getGPR32Reg() == Mips::SP);
893 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000894 bool isRegList16() const {
895 if (!isRegList())
896 return false;
897
898 int Size = RegList.List->size();
899 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
900 RegList.List->back() != Mips::RA)
901 return false;
902
903 int PrevReg = *RegList.List->begin();
904 for (int i = 1; i < Size - 1; i++) {
905 int Reg = (*(RegList.List))[i];
906 if ( Reg != PrevReg + 1)
907 return false;
908 PrevReg = Reg;
909 }
910
911 return true;
912 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000913 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000914 bool isLSAImm() const {
915 if (!isConstantImm())
916 return false;
917 int64_t Val = getConstantImm();
918 return 1 <= Val && Val <= 4;
919 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000920 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +0000921 bool isMovePRegPair() const {
922 if (Kind != k_RegList || RegList.List->size() != 2)
923 return false;
924
925 unsigned R0 = RegList.List->front();
926 unsigned R1 = RegList.List->back();
927
928 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
929 (R0 == Mips::A1 && R1 == Mips::A3) ||
930 (R0 == Mips::A2 && R1 == Mips::A3) ||
931 (R0 == Mips::A0 && R1 == Mips::S5) ||
932 (R0 == Mips::A0 && R1 == Mips::S6) ||
933 (R0 == Mips::A0 && R1 == Mips::A1) ||
934 (R0 == Mips::A0 && R1 == Mips::A2) ||
935 (R0 == Mips::A0 && R1 == Mips::A3))
936 return true;
937
938 return false;
939 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000940
941 StringRef getToken() const {
942 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000943 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000944 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000945 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000946
Craig Topper56c590a2014-04-29 07:58:02 +0000947 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000948 // As a special case until we sort out the definition of div/divu, pretend
949 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
950 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
951 RegIdx.Kind & RegKind_GPR)
952 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000953
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000954 assert(Kind == k_PhysRegister && "Invalid access!");
955 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000956 }
957
Jack Carterb4dbc172012-09-05 23:34:03 +0000958 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000959 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000960 return Imm.Val;
961 }
962
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000963 int64_t getConstantImm() const {
964 const MCExpr *Val = getImm();
965 return static_cast<const MCConstantExpr *>(Val)->getValue();
966 }
967
968 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000969 assert((Kind == k_Memory) && "Invalid access!");
970 return Mem.Base;
971 }
972
973 const MCExpr *getMemOff() const {
974 assert((Kind == k_Memory) && "Invalid access!");
975 return Mem.Off;
976 }
977
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000978 int64_t getConstantMemOff() const {
979 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
980 }
981
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000982 const SmallVectorImpl<unsigned> &getRegList() const {
983 assert((Kind == k_RegList) && "Invalid access!");
984 return *(RegList.List);
985 }
986
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000987 unsigned getRegPair() const {
988 assert((Kind == k_RegPair) && "Invalid access!");
989 return RegIdx.Index;
990 }
991
David Blaikie960ea3f2014-06-08 16:18:35 +0000992 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
993 MipsAsmParser &Parser) {
994 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000995 Op->Tok.Data = Str.data();
996 Op->Tok.Length = Str.size();
997 Op->StartLoc = S;
998 Op->EndLoc = S;
999 return Op;
1000 }
1001
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001002 /// Create a numeric register (e.g. $1). The exact register remains
1003 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001004 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001005 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001006 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001007 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001008 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001009 }
1010
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001011 /// Create a register that is definitely a GPR.
1012 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001013 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001014 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001015 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001016 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001017 }
1018
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001019 /// Create a register that is definitely a FGR.
1020 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001021 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001022 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001023 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001024 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1025 }
1026
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001027 /// Create a register that is definitely a HWReg.
1028 /// This is typically only used for named registers such as $hwr_cpunum.
1029 static std::unique_ptr<MipsOperand>
1030 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1031 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1032 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1033 }
1034
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001035 /// Create a register that is definitely an FCC.
1036 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001037 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001038 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001039 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001040 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1041 }
1042
1043 /// Create a register that is definitely an ACC.
1044 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001045 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001046 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001047 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001048 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1049 }
1050
1051 /// Create a register that is definitely an MSA128.
1052 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001053 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001054 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001055 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001056 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1057 }
1058
1059 /// Create a register that is definitely an MSACtrl.
1060 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001061 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001062 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001063 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001064 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1065 }
1066
David Blaikie960ea3f2014-06-08 16:18:35 +00001067 static std::unique_ptr<MipsOperand>
1068 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1069 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001070 Op->Imm.Val = Val;
1071 Op->StartLoc = S;
1072 Op->EndLoc = E;
1073 return Op;
1074 }
1075
David Blaikie960ea3f2014-06-08 16:18:35 +00001076 static std::unique_ptr<MipsOperand>
1077 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1078 SMLoc E, MipsAsmParser &Parser) {
1079 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1080 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001081 Op->Mem.Off = Off;
1082 Op->StartLoc = S;
1083 Op->EndLoc = E;
1084 return Op;
1085 }
1086
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001087 static std::unique_ptr<MipsOperand>
1088 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1089 MipsAsmParser &Parser) {
1090 assert (Regs.size() > 0 && "Empty list not allowed");
1091
1092 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001093 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001094 Op->StartLoc = StartLoc;
1095 Op->EndLoc = EndLoc;
1096 return Op;
1097 }
1098
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001099 static std::unique_ptr<MipsOperand>
1100 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1101 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1102 Op->RegIdx.Index = RegNo;
1103 Op->StartLoc = S;
1104 Op->EndLoc = E;
1105 return Op;
1106 }
1107
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001108 bool isGPRAsmReg() const {
1109 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001110 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001111 bool isMM16AsmReg() const {
1112 if (!(isRegIdx() && RegIdx.Kind))
1113 return false;
1114 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1115 || RegIdx.Index == 16 || RegIdx.Index == 17);
1116 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001117 bool isMM16AsmRegZero() const {
1118 if (!(isRegIdx() && RegIdx.Kind))
1119 return false;
1120 return (RegIdx.Index == 0 ||
1121 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1122 RegIdx.Index == 17);
1123 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001124 bool isMM16AsmRegMoveP() const {
1125 if (!(isRegIdx() && RegIdx.Kind))
1126 return false;
1127 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1128 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1129 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001130 bool isFGRAsmReg() const {
1131 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1132 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001133 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001134 bool isHWRegsAsmReg() const {
1135 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001136 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001137 bool isCCRAsmReg() const {
1138 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001139 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001140 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001141 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1142 return false;
1143 if (!AsmParser.hasEightFccRegisters())
1144 return RegIdx.Index == 0;
1145 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001146 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001147 bool isACCAsmReg() const {
1148 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001149 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001150 bool isCOP2AsmReg() const {
1151 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001152 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001153 bool isCOP3AsmReg() const {
1154 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1155 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001156 bool isMSA128AsmReg() const {
1157 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001158 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001159 bool isMSACtrlAsmReg() const {
1160 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001161 }
1162
Jack Carterb4dbc172012-09-05 23:34:03 +00001163 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001164 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001165 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001166 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001167
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001168 virtual ~MipsOperand() {
1169 switch (Kind) {
1170 case k_Immediate:
1171 break;
1172 case k_Memory:
1173 delete Mem.Base;
1174 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001175 case k_RegList:
1176 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001177 case k_PhysRegister:
1178 case k_RegisterIndex:
1179 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001180 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001181 break;
1182 }
1183 }
1184
Craig Topper56c590a2014-04-29 07:58:02 +00001185 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001186 switch (Kind) {
1187 case k_Immediate:
1188 OS << "Imm<";
1189 Imm.Val->print(OS);
1190 OS << ">";
1191 break;
1192 case k_Memory:
1193 OS << "Mem<";
1194 Mem.Base->print(OS);
1195 OS << ", ";
1196 Mem.Off->print(OS);
1197 OS << ">";
1198 break;
1199 case k_PhysRegister:
1200 OS << "PhysReg<" << PhysReg.Num << ">";
1201 break;
1202 case k_RegisterIndex:
1203 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1204 break;
1205 case k_Token:
1206 OS << Tok.Data;
1207 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001208 case k_RegList:
1209 OS << "RegList< ";
1210 for (auto Reg : (*RegList.List))
1211 OS << Reg << " ";
1212 OS << ">";
1213 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001214 case k_RegPair:
1215 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1216 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001217 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001218 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001219}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001220} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001221
Jack Carter9e65aa32013-03-22 00:05:30 +00001222namespace llvm {
1223extern const MCInstrDesc MipsInsts[];
1224}
1225static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1226 return MipsInsts[Opcode];
1227}
1228
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001229static bool hasShortDelaySlot(unsigned Opcode) {
1230 switch (Opcode) {
1231 case Mips::JALS_MM:
1232 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001233 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001234 case Mips::BGEZALS_MM:
1235 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001236 return true;
1237 default:
1238 return false;
1239 }
1240}
1241
Jack Carter9e65aa32013-03-22 00:05:30 +00001242bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001243 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001244 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001245
Jack Carter9e65aa32013-03-22 00:05:30 +00001246 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001247
1248 if (MCID.isBranch() || MCID.isCall()) {
1249 const unsigned Opcode = Inst.getOpcode();
1250 MCOperand Offset;
1251
1252 switch (Opcode) {
1253 default:
1254 break;
Kai Nackee0245392015-01-27 19:11:28 +00001255 case Mips::BBIT0:
1256 case Mips::BBIT032:
1257 case Mips::BBIT1:
1258 case Mips::BBIT132:
1259 assert(hasCnMips() && "instruction only valid for octeon cpus");
1260 // Fall through
1261
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001262 case Mips::BEQ:
1263 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001264 case Mips::BEQ_MM:
1265 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001266 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001267 Offset = Inst.getOperand(2);
1268 if (!Offset.isImm())
1269 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001270 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001271 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001272 if (OffsetToAlignment(Offset.getImm(),
1273 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001274 return Error(IDLoc, "branch to misaligned address");
1275 break;
1276 case Mips::BGEZ:
1277 case Mips::BGTZ:
1278 case Mips::BLEZ:
1279 case Mips::BLTZ:
1280 case Mips::BGEZAL:
1281 case Mips::BLTZAL:
1282 case Mips::BC1F:
1283 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001284 case Mips::BGEZ_MM:
1285 case Mips::BGTZ_MM:
1286 case Mips::BLEZ_MM:
1287 case Mips::BLTZ_MM:
1288 case Mips::BGEZAL_MM:
1289 case Mips::BLTZAL_MM:
1290 case Mips::BC1F_MM:
1291 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001292 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001293 Offset = Inst.getOperand(1);
1294 if (!Offset.isImm())
1295 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001296 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001297 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001298 if (OffsetToAlignment(Offset.getImm(),
1299 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001300 return Error(IDLoc, "branch to misaligned address");
1301 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001302 case Mips::BEQZ16_MM:
1303 case Mips::BNEZ16_MM:
1304 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1305 Offset = Inst.getOperand(1);
1306 if (!Offset.isImm())
1307 break; // We'll deal with this situation later on when applying fixups.
1308 if (!isIntN(8, Offset.getImm()))
1309 return Error(IDLoc, "branch target out of range");
1310 if (OffsetToAlignment(Offset.getImm(), 2LL))
1311 return Error(IDLoc, "branch to misaligned address");
1312 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001313 }
1314 }
1315
Daniel Sandersa84989a2014-06-16 13:25:35 +00001316 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1317 // We still accept it but it is a normal nop.
1318 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1319 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1320 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1321 "nop instruction");
1322 }
1323
Kai Nackee0245392015-01-27 19:11:28 +00001324 if (hasCnMips()) {
1325 const unsigned Opcode = Inst.getOpcode();
1326 MCOperand Opnd;
1327 int Imm;
1328
1329 switch (Opcode) {
1330 default:
1331 break;
1332
1333 case Mips::BBIT0:
1334 case Mips::BBIT032:
1335 case Mips::BBIT1:
1336 case Mips::BBIT132:
1337 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1338 // The offset is handled above
1339 Opnd = Inst.getOperand(1);
1340 if (!Opnd.isImm())
1341 return Error(IDLoc, "expected immediate operand kind");
1342 Imm = Opnd.getImm();
1343 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1344 Opcode == Mips::BBIT1 ? 63 : 31))
1345 return Error(IDLoc, "immediate operand value out of range");
1346 if (Imm > 31) {
1347 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1348 : Mips::BBIT132);
1349 Inst.getOperand(1).setImm(Imm - 32);
1350 }
1351 break;
1352
1353 case Mips::CINS:
1354 case Mips::CINS32:
1355 case Mips::EXTS:
1356 case Mips::EXTS32:
1357 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1358 // Check length
1359 Opnd = Inst.getOperand(3);
1360 if (!Opnd.isImm())
1361 return Error(IDLoc, "expected immediate operand kind");
1362 Imm = Opnd.getImm();
1363 if (Imm < 0 || Imm > 31)
1364 return Error(IDLoc, "immediate operand value out of range");
1365 // Check position
1366 Opnd = Inst.getOperand(2);
1367 if (!Opnd.isImm())
1368 return Error(IDLoc, "expected immediate operand kind");
1369 Imm = Opnd.getImm();
1370 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1371 Opcode == Mips::EXTS ? 63 : 31))
1372 return Error(IDLoc, "immediate operand value out of range");
1373 if (Imm > 31) {
1374 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1375 Inst.getOperand(2).setImm(Imm - 32);
1376 }
1377 break;
1378
1379 case Mips::SEQi:
1380 case Mips::SNEi:
1381 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1382 Opnd = Inst.getOperand(2);
1383 if (!Opnd.isImm())
1384 return Error(IDLoc, "expected immediate operand kind");
1385 Imm = Opnd.getImm();
1386 if (!isInt<10>(Imm))
1387 return Error(IDLoc, "immediate operand value out of range");
1388 break;
1389 }
1390 }
1391
Jack Carter9e65aa32013-03-22 00:05:30 +00001392 if (MCID.mayLoad() || MCID.mayStore()) {
1393 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001394 // reference or immediate we may have to expand instructions.
1395 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001396 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001397 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1398 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001399 MCOperand &Op = Inst.getOperand(i);
1400 if (Op.isImm()) {
1401 int MemOffset = Op.getImm();
1402 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001403 // Offset can't exceed 16bit value.
1404 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001405 return false;
1406 }
1407 } else if (Op.isExpr()) {
1408 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001409 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001410 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001411 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001412 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001413 // Expand symbol.
1414 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001415 return false;
1416 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001417 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001418 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001419 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001420 }
1421 }
1422 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001423 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001424 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001425
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001426 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001427 if (MCID.mayLoad()) {
1428 // Try to create 16-bit GP relative load instruction.
1429 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1430 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1431 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1432 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1433 MCOperand &Op = Inst.getOperand(i);
1434 if (Op.isImm()) {
1435 int MemOffset = Op.getImm();
1436 MCOperand &DstReg = Inst.getOperand(0);
1437 MCOperand &BaseReg = Inst.getOperand(1);
1438 if (isIntN(9, MemOffset) && (MemOffset % 4 == 0) &&
1439 getContext().getRegisterInfo()->getRegClass(
1440 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
1441 BaseReg.getReg() == Mips::GP) {
1442 MCInst TmpInst;
1443 TmpInst.setLoc(IDLoc);
1444 TmpInst.setOpcode(Mips::LWGP_MM);
1445 TmpInst.addOperand(MCOperand::CreateReg(DstReg.getReg()));
1446 TmpInst.addOperand(MCOperand::CreateReg(Mips::GP));
1447 TmpInst.addOperand(MCOperand::CreateImm(MemOffset));
1448 Instructions.push_back(TmpInst);
1449 return false;
1450 }
1451 }
1452 }
1453 } // for
1454 } // if load
1455
1456 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1457
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001458 MCOperand Opnd;
1459 int Imm;
1460
1461 switch (Inst.getOpcode()) {
1462 default:
1463 break;
1464 case Mips::ADDIUS5_MM:
1465 Opnd = Inst.getOperand(2);
1466 if (!Opnd.isImm())
1467 return Error(IDLoc, "expected immediate operand kind");
1468 Imm = Opnd.getImm();
1469 if (Imm < -8 || Imm > 7)
1470 return Error(IDLoc, "immediate operand value out of range");
1471 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001472 case Mips::ADDIUSP_MM:
1473 Opnd = Inst.getOperand(0);
1474 if (!Opnd.isImm())
1475 return Error(IDLoc, "expected immediate operand kind");
1476 Imm = Opnd.getImm();
1477 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1478 Imm % 4 != 0)
1479 return Error(IDLoc, "immediate operand value out of range");
1480 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001481 case Mips::SLL16_MM:
1482 case Mips::SRL16_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 < 1 || Imm > 8)
1488 return Error(IDLoc, "immediate operand value out of range");
1489 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001490 case Mips::LI16_MM:
1491 Opnd = Inst.getOperand(1);
1492 if (!Opnd.isImm())
1493 return Error(IDLoc, "expected immediate operand kind");
1494 Imm = Opnd.getImm();
1495 if (Imm < -1 || Imm > 126)
1496 return Error(IDLoc, "immediate operand value out of range");
1497 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001498 case Mips::ADDIUR2_MM:
1499 Opnd = Inst.getOperand(2);
1500 if (!Opnd.isImm())
1501 return Error(IDLoc, "expected immediate operand kind");
1502 Imm = Opnd.getImm();
1503 if (!(Imm == 1 || Imm == -1 ||
1504 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1505 return Error(IDLoc, "immediate operand value out of range");
1506 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001507 case Mips::ADDIUR1SP_MM:
1508 Opnd = Inst.getOperand(1);
1509 if (!Opnd.isImm())
1510 return Error(IDLoc, "expected immediate operand kind");
1511 Imm = Opnd.getImm();
1512 if (OffsetToAlignment(Imm, 4LL))
1513 return Error(IDLoc, "misaligned immediate operand value");
1514 if (Imm < 0 || Imm > 255)
1515 return Error(IDLoc, "immediate operand value out of range");
1516 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001517 case Mips::ANDI16_MM:
1518 Opnd = Inst.getOperand(2);
1519 if (!Opnd.isImm())
1520 return Error(IDLoc, "expected immediate operand kind");
1521 Imm = Opnd.getImm();
1522 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1523 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1524 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1525 return Error(IDLoc, "immediate operand value out of range");
1526 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001527 case Mips::LBU16_MM:
1528 Opnd = Inst.getOperand(2);
1529 if (!Opnd.isImm())
1530 return Error(IDLoc, "expected immediate operand kind");
1531 Imm = Opnd.getImm();
1532 if (Imm < -1 || Imm > 14)
1533 return Error(IDLoc, "immediate operand value out of range");
1534 break;
1535 case Mips::SB16_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 < 0 || Imm > 15)
1541 return Error(IDLoc, "immediate operand value out of range");
1542 break;
1543 case Mips::LHU16_MM:
1544 case Mips::SH16_MM:
1545 Opnd = Inst.getOperand(2);
1546 if (!Opnd.isImm())
1547 return Error(IDLoc, "expected immediate operand kind");
1548 Imm = Opnd.getImm();
1549 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1550 return Error(IDLoc, "immediate operand value out of range");
1551 break;
1552 case Mips::LW16_MM:
1553 case Mips::SW16_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 > 60 || (Imm % 4 != 0))
1559 return Error(IDLoc, "immediate operand value out of range");
1560 break;
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001561 case Mips::CACHE:
1562 case Mips::PREF:
1563 Opnd = Inst.getOperand(2);
1564 if (!Opnd.isImm())
1565 return Error(IDLoc, "expected immediate operand kind");
1566 Imm = Opnd.getImm();
1567 if (!isUInt<5>(Imm))
1568 return Error(IDLoc, "immediate operand value out of range");
1569 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001570 case Mips::ADDIUPC_MM:
1571 MCOperand Opnd = Inst.getOperand(1);
1572 if (!Opnd.isImm())
1573 return Error(IDLoc, "expected immediate operand kind");
1574 int Imm = Opnd.getImm();
1575 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1576 return Error(IDLoc, "immediate operand value out of range");
1577 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001578 }
1579 }
1580
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001581 if (needsExpansion(Inst)) {
1582 if (expandInstruction(Inst, IDLoc, Instructions))
1583 return true;
1584 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001585 Instructions.push_back(Inst);
1586
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001587 // If this instruction has a delay slot and .set reorder is active,
1588 // emit a NOP after it.
1589 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1590 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1591
Jack Carter9e65aa32013-03-22 00:05:30 +00001592 return false;
1593}
1594
Jack Carter30a59822012-10-04 04:03:53 +00001595bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1596
Jack Carterd0bd6422013-04-18 00:41:53 +00001597 switch (Inst.getOpcode()) {
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001598 case Mips::LoadImm32:
1599 case Mips::LoadImm64:
1600 case Mips::LoadAddrImm32:
1601 case Mips::LoadAddrReg32:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001602 case Mips::B_MM_Pseudo:
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001603 case Mips::LWM_MM:
1604 case Mips::SWM_MM:
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001605 case Mips::JalOneReg:
1606 case Mips::JalTwoReg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001607 return true;
1608 default:
1609 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001610 }
1611}
Jack Carter92995f12012-10-06 00:53:28 +00001612
Matheus Almeida3813d572014-06-19 14:39:14 +00001613bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001614 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001615 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001616 default: llvm_unreachable("unimplemented expansion");
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001617 case Mips::LoadImm32:
Toma Tabacu00e98672015-05-01 12:19:27 +00001618 return expandLoadImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001619 case Mips::LoadImm64:
Toma Tabacu00e98672015-05-01 12:19:27 +00001620 return expandLoadImm(Inst, false, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001621 case Mips::LoadAddrImm32:
Jack Carterd0bd6422013-04-18 00:41:53 +00001622 return expandLoadAddressImm(Inst, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001623 case Mips::LoadAddrReg32:
Jack Carterd0bd6422013-04-18 00:41:53 +00001624 return expandLoadAddressReg(Inst, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001625 case Mips::B_MM_Pseudo:
1626 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001627 case Mips::SWM_MM:
1628 case Mips::LWM_MM:
1629 return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001630 case Mips::JalOneReg:
1631 case Mips::JalTwoReg:
1632 return expandJalWithRegs(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001633 }
Jack Carter30a59822012-10-04 04:03:53 +00001634}
Jack Carter92995f12012-10-06 00:53:28 +00001635
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001636namespace {
Toma Tabacua2861db2015-05-01 10:26:47 +00001637template <unsigned ShiftAmount>
Toma Tabacu61145652015-04-28 13:16:06 +00001638void createLShiftOri(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001639 SmallVectorImpl<MCInst> &Instructions) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001640 MCInst tmpInst;
Toma Tabacua2861db2015-05-01 10:26:47 +00001641 if (ShiftAmount >= 32) {
1642 tmpInst.setOpcode(Mips::DSLL32);
1643 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1644 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1645 tmpInst.addOperand(MCOperand::CreateImm(ShiftAmount - 32));
1646 tmpInst.setLoc(IDLoc);
1647 Instructions.push_back(tmpInst);
1648 tmpInst.clear();
1649 } else if (ShiftAmount > 0) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001650 tmpInst.setOpcode(Mips::DSLL);
1651 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1652 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacua2861db2015-05-01 10:26:47 +00001653 tmpInst.addOperand(MCOperand::CreateImm(ShiftAmount));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001654 tmpInst.setLoc(IDLoc);
1655 Instructions.push_back(tmpInst);
1656 tmpInst.clear();
1657 }
Toma Tabacu7dea2e32015-04-28 14:06:35 +00001658 // There's no need for an ORi if the immediate is 0.
1659 if (Operand.isImm() && Operand.getImm() == 0)
1660 return;
1661
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001662 tmpInst.setOpcode(Mips::ORi);
1663 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1664 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001665 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001666 tmpInst.setLoc(IDLoc);
1667 Instructions.push_back(tmpInst);
1668}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001669
Toma Tabacua2861db2015-05-01 10:26:47 +00001670template <unsigned ShiftAmount>
Toma Tabacu61145652015-04-28 13:16:06 +00001671void createLShiftOri(int64_t Value, unsigned RegNo, SMLoc IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001672 SmallVectorImpl<MCInst> &Instructions) {
1673 createLShiftOri<ShiftAmount>(MCOperand::CreateImm(Value), RegNo, IDLoc,
1674 Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001675}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001676}
1677
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001678bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
1679 SmallVectorImpl<MCInst> &Instructions) {
1680 // Create a JALR instruction which is going to replace the pseudo-JAL.
1681 MCInst JalrInst;
1682 JalrInst.setLoc(IDLoc);
1683 const MCOperand FirstRegOp = Inst.getOperand(0);
1684 const unsigned Opcode = Inst.getOpcode();
1685
1686 if (Opcode == Mips::JalOneReg) {
1687 // jal $rs => jalr $rs
1688 if (inMicroMipsMode()) {
1689 JalrInst.setOpcode(Mips::JALR16_MM);
1690 JalrInst.addOperand(FirstRegOp);
1691 } else {
1692 JalrInst.setOpcode(Mips::JALR);
1693 JalrInst.addOperand(MCOperand::CreateReg(Mips::RA));
1694 JalrInst.addOperand(FirstRegOp);
1695 }
1696 } else if (Opcode == Mips::JalTwoReg) {
1697 // jal $rd, $rs => jalr $rd, $rs
1698 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
1699 JalrInst.addOperand(FirstRegOp);
1700 const MCOperand SecondRegOp = Inst.getOperand(1);
1701 JalrInst.addOperand(SecondRegOp);
1702 }
1703 Instructions.push_back(JalrInst);
1704
1705 // If .set reorder is active, emit a NOP after it.
1706 if (AssemblerOptions.back()->isReorder()) {
1707 // This is a 32-bit NOP because these 2 pseudo-instructions
1708 // do not have a short delay slot.
1709 MCInst NopInst;
1710 NopInst.setOpcode(Mips::SLL);
1711 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1712 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1713 NopInst.addOperand(MCOperand::CreateImm(0));
1714 Instructions.push_back(NopInst);
1715 }
1716
1717 return false;
1718}
1719
Toma Tabacu00e98672015-05-01 12:19:27 +00001720bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001721 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00001722 if (!Is32BitImm && !isGP64bit()) {
1723 Error(IDLoc, "instruction requires a 64-bit architecture");
1724 return true;
1725 }
1726
Jack Carter92995f12012-10-06 00:53:28 +00001727 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001728 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001729 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001730 const MCOperand &RegOp = Inst.getOperand(0);
1731 assert(RegOp.isReg() && "expected register operand kind");
1732
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001733 int64_t ImmValue = ImmOp.getImm();
Toma Tabacu137d90a2015-04-28 12:04:53 +00001734 unsigned Reg = RegOp.getReg();
Jack Carter92995f12012-10-06 00:53:28 +00001735 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001736 // FIXME: gas has a special case for values that are 000...1111, which
1737 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001738 if (0 <= ImmValue && ImmValue <= 65535) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001739 // For unsigned and positive signed 16-bit values (0 <= j <= 65535):
Jack Carter30a59822012-10-04 04:03:53 +00001740 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001741 tmpInst.setOpcode(Mips::ORi);
Toma Tabacu137d90a2015-04-28 12:04:53 +00001742 tmpInst.addOperand(MCOperand::CreateReg(Reg));
Jack Carterd0bd6422013-04-18 00:41:53 +00001743 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001744 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001745 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001746 } else if (ImmValue < 0 && ImmValue >= -32768) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001747 // For negative signed 16-bit values (-32768 <= j < 0):
Jack Carter30a59822012-10-04 04:03:53 +00001748 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001749 tmpInst.setOpcode(Mips::ADDiu);
Toma Tabacu137d90a2015-04-28 12:04:53 +00001750 tmpInst.addOperand(MCOperand::CreateReg(Reg));
Jack Carterd0bd6422013-04-18 00:41:53 +00001751 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001752 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001753 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001754 } else if ((ImmValue & 0xffffffff) == ImmValue) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001755 // For all other values which are representable as a 32-bit integer:
Jack Carter30a59822012-10-04 04:03:53 +00001756 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001757 // ori d,d,lo16(j)
Toma Tabacu79588102015-04-29 10:19:56 +00001758 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1759 uint16_t Bits15To0 = ImmValue & 0xffff;
1760
Jack Carter873c7242013-01-12 01:03:14 +00001761 tmpInst.setOpcode(Mips::LUi);
Toma Tabacu137d90a2015-04-28 12:04:53 +00001762 tmpInst.addOperand(MCOperand::CreateReg(Reg));
Toma Tabacu79588102015-04-29 10:19:56 +00001763 tmpInst.addOperand(MCOperand::CreateImm(Bits31To16));
Jack Carter30a59822012-10-04 04:03:53 +00001764 Instructions.push_back(tmpInst);
Toma Tabacua2861db2015-05-01 10:26:47 +00001765 createLShiftOri<0>(Bits15To0, Reg, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001766 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Toma Tabacu00e98672015-05-01 12:19:27 +00001767 if (Is32BitImm) {
1768 Error(IDLoc, "instruction requires a 32-bit immediate");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001769 return true;
1770 }
1771
1772 // <------- lo32 ------>
1773 // <------- hi32 ------>
1774 // <- hi16 -> <- lo16 ->
1775 // _________________________________
1776 // | | | |
Toma Tabacubda745f2015-04-27 15:21:38 +00001777 // | 16-bits | 16-bits | 16-bits |
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001778 // |__________|__________|__________|
1779 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001780 // For any 64-bit value that is representable as a 48-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001781 // li d,j => lui d,hi16(j)
1782 // ori d,d,hi16(lo32(j))
1783 // dsll d,d,16
1784 // ori d,d,lo16(lo32(j))
Toma Tabacu79588102015-04-29 10:19:56 +00001785 uint16_t Bits47To32 = (ImmValue >> 32) & 0xffff;
1786 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1787 uint16_t Bits15To0 = ImmValue & 0xffff;
1788
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001789 tmpInst.setOpcode(Mips::LUi);
Toma Tabacu137d90a2015-04-28 12:04:53 +00001790 tmpInst.addOperand(MCOperand::CreateReg(Reg));
Toma Tabacu79588102015-04-29 10:19:56 +00001791 tmpInst.addOperand(MCOperand::CreateImm(Bits47To32));
Jack Carter30a59822012-10-04 04:03:53 +00001792 Instructions.push_back(tmpInst);
Toma Tabacua2861db2015-05-01 10:26:47 +00001793 createLShiftOri<0>(Bits31To16, Reg, IDLoc, Instructions);
1794 createLShiftOri<16>(Bits15To0, Reg, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001795 } else {
Toma Tabacu00e98672015-05-01 12:19:27 +00001796 if (Is32BitImm) {
1797 Error(IDLoc, "instruction requires a 32-bit immediate");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001798 return true;
1799 }
1800
1801 // <------- hi32 ------> <------- lo32 ------>
1802 // <- hi16 -> <- lo16 ->
1803 // ___________________________________________
1804 // | | | | |
Toma Tabacubda745f2015-04-27 15:21:38 +00001805 // | 16-bits | 16-bits | 16-bits | 16-bits |
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001806 // |__________|__________|__________|__________|
1807 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001808 // For all other values which are representable as a 64-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001809 // li d,j => lui d,hi16(j)
1810 // ori d,d,lo16(hi32(j))
1811 // dsll d,d,16
1812 // ori d,d,hi16(lo32(j))
1813 // dsll d,d,16
1814 // ori d,d,lo16(lo32(j))
Toma Tabacu79588102015-04-29 10:19:56 +00001815 uint16_t Bits63To48 = (ImmValue >> 48) & 0xffff;
1816 uint16_t Bits47To32 = (ImmValue >> 32) & 0xffff;
1817 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1818 uint16_t Bits15To0 = ImmValue & 0xffff;
1819
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001820 tmpInst.setOpcode(Mips::LUi);
Toma Tabacu137d90a2015-04-28 12:04:53 +00001821 tmpInst.addOperand(MCOperand::CreateReg(Reg));
Toma Tabacu79588102015-04-29 10:19:56 +00001822 tmpInst.addOperand(MCOperand::CreateImm(Bits63To48));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001823 Instructions.push_back(tmpInst);
Toma Tabacua2861db2015-05-01 10:26:47 +00001824 createLShiftOri<0>(Bits47To32, Reg, IDLoc, Instructions);
1825
1826 // When Bits31To16 is 0, do a left shift of 32 bits instead of doing
1827 // two left shifts of 16 bits.
1828 if (Bits31To16 == 0) {
1829 createLShiftOri<32>(Bits15To0, Reg, IDLoc, Instructions);
1830 } else {
1831 createLShiftOri<16>(Bits31To16, Reg, IDLoc, Instructions);
1832 createLShiftOri<16>(Bits15To0, Reg, IDLoc, Instructions);
1833 }
Jack Carter30a59822012-10-04 04:03:53 +00001834 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001835 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001836}
Jack Carter92995f12012-10-06 00:53:28 +00001837
Matheus Almeida3813d572014-06-19 14:39:14 +00001838bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001839MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1840 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001841 MCInst tmpInst;
1842 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001843 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1844 "expected immediate operand kind");
1845 if (!ImmOp.isImm()) {
1846 expandLoadAddressSym(Inst, IDLoc, Instructions);
1847 return false;
1848 }
Jack Carter543fdf82012-10-09 23:29:45 +00001849 const MCOperand &SrcRegOp = Inst.getOperand(1);
1850 assert(SrcRegOp.isReg() && "expected register operand kind");
1851 const MCOperand &DstRegOp = Inst.getOperand(0);
1852 assert(DstRegOp.isReg() && "expected register operand kind");
1853 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001854 if (-32768 <= ImmValue && ImmValue <= 65535) {
1855 // For -32768 <= j <= 65535.
1856 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001857 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001858 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1859 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1860 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1861 Instructions.push_back(tmpInst);
1862 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001863 // For any other value of j that is representable as a 32-bit integer.
1864 // la d,j(s) => lui d,hi16(j)
1865 // ori d,d,lo16(j)
1866 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001867 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001868 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1869 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1870 Instructions.push_back(tmpInst);
1871 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001872 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001873 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1874 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1875 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1876 Instructions.push_back(tmpInst);
1877 tmpInst.clear();
1878 tmpInst.setOpcode(Mips::ADDu);
1879 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1880 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1881 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1882 Instructions.push_back(tmpInst);
1883 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001884 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001885}
1886
Matheus Almeida3813d572014-06-19 14:39:14 +00001887bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001888MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1889 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001890 MCInst tmpInst;
1891 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001892 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1893 "expected immediate operand kind");
1894 if (!ImmOp.isImm()) {
1895 expandLoadAddressSym(Inst, IDLoc, Instructions);
1896 return false;
1897 }
Jack Carter543fdf82012-10-09 23:29:45 +00001898 const MCOperand &RegOp = Inst.getOperand(0);
1899 assert(RegOp.isReg() && "expected register operand kind");
1900 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001901 if (-32768 <= ImmValue && ImmValue <= 65535) {
1902 // For -32768 <= j <= 65535.
1903 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001904 tmpInst.setOpcode(Mips::ADDiu);
1905 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001906 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001907 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1908 Instructions.push_back(tmpInst);
1909 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001910 // For any other value of j that is representable as a 32-bit integer.
1911 // la d,j => lui d,hi16(j)
1912 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001913 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001914 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1915 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1916 Instructions.push_back(tmpInst);
1917 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001918 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001919 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1920 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1921 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1922 Instructions.push_back(tmpInst);
1923 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001924 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001925}
1926
Toma Tabacu0d64b202014-08-14 10:29:17 +00001927void
1928MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1929 SmallVectorImpl<MCInst> &Instructions) {
1930 // FIXME: If we do have a valid at register to use, we should generate a
1931 // slightly shorter sequence here.
1932 MCInst tmpInst;
1933 int ExprOperandNo = 1;
1934 // Sometimes the assembly parser will get the immediate expression as
1935 // a $zero + an immediate.
1936 if (Inst.getNumOperands() == 3) {
1937 assert(Inst.getOperand(1).getReg() ==
1938 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1939 ExprOperandNo = 2;
1940 }
1941 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1942 assert(SymOp.isExpr() && "expected symbol operand kind");
1943 const MCOperand &RegOp = Inst.getOperand(0);
1944 unsigned RegNo = RegOp.getReg();
1945 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1946 const MCSymbolRefExpr *HiExpr =
1947 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1948 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1949 const MCSymbolRefExpr *LoExpr =
1950 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1951 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1952 if (isGP64bit()) {
1953 // If it's a 64-bit architecture, expand to:
1954 // la d,sym => lui d,highest(sym)
1955 // ori d,d,higher(sym)
1956 // dsll d,d,16
1957 // ori d,d,hi16(sym)
1958 // dsll d,d,16
1959 // ori d,d,lo16(sym)
1960 const MCSymbolRefExpr *HighestExpr =
1961 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1962 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1963 const MCSymbolRefExpr *HigherExpr =
1964 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1965 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1966
1967 tmpInst.setOpcode(Mips::LUi);
1968 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1969 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1970 Instructions.push_back(tmpInst);
1971
Toma Tabacua2861db2015-05-01 10:26:47 +00001972 createLShiftOri<0>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1973 Instructions);
1974 createLShiftOri<16>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00001975 Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001976 createLShiftOri<16>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00001977 Instructions);
1978 } else {
1979 // Otherwise, expand to:
1980 // la d,sym => lui d,hi16(sym)
1981 // ori d,d,lo16(sym)
1982 tmpInst.setOpcode(Mips::LUi);
1983 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1984 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1985 Instructions.push_back(tmpInst);
1986
Toma Tabacua2861db2015-05-01 10:26:47 +00001987 createLShiftOri<0>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1988 Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001989 }
1990}
1991
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00001992bool MipsAsmParser::expandUncondBranchMMPseudo(
1993 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00001994 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
1995 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001996
1997 MCOperand Offset = Inst.getOperand(0);
1998 if (Offset.isExpr()) {
1999 Inst.clear();
2000 Inst.setOpcode(Mips::BEQ_MM);
2001 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2002 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2003 Inst.addOperand(MCOperand::CreateExpr(Offset.getExpr()));
2004 } else {
2005 assert(Offset.isImm() && "expected immediate operand kind");
2006 if (isIntN(11, Offset.getImm())) {
2007 // If offset fits into 11 bits then this instruction becomes microMIPS
2008 // 16-bit unconditional branch instruction.
2009 Inst.setOpcode(Mips::B16_MM);
2010 } else {
2011 if (!isIntN(17, Offset.getImm()))
2012 Error(IDLoc, "branch target out of range");
2013 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2014 Error(IDLoc, "branch to misaligned address");
2015 Inst.clear();
2016 Inst.setOpcode(Mips::BEQ_MM);
2017 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2018 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2019 Inst.addOperand(MCOperand::CreateImm(Offset.getImm()));
2020 }
2021 }
2022 Instructions.push_back(Inst);
2023
Toma Tabacu234482a2015-03-16 12:03:39 +00002024 // If .set reorder is active, emit a NOP after the branch instruction.
2025 if (AssemblerOptions.back()->isReorder())
2026 createNop(true, IDLoc, Instructions);
2027
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002028 return false;
2029}
2030
Jack Carter9e65aa32013-03-22 00:05:30 +00002031void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002032 SmallVectorImpl<MCInst> &Instructions,
2033 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002034 const MCSymbolRefExpr *SR;
2035 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00002036 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002037 const MCExpr *ExprOffset;
2038 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002039 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002040 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2041 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002042 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002043 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2044 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002045 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002046 if (isImmOpnd) {
2047 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2048 ImmOffset = Inst.getOperand(2).getImm();
2049 LoOffset = ImmOffset & 0x0000ffff;
2050 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002051 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002052 if (LoOffset & 0x8000)
2053 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002054 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002055 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002056 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002057 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002058 // These are some of the types of expansions we perform here:
2059 // 1) lw $8, sym => lui $8, %hi(sym)
2060 // lw $8, %lo(sym)($8)
2061 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2062 // add $8, $8, $9
2063 // lw $8, %lo(offset)($9)
2064 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2065 // add $at, $at, $8
2066 // lw $8, %lo(offset)($at)
2067 // 4) sw $8, sym => lui $at, %hi(sym)
2068 // sw $8, %lo(sym)($at)
2069 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2070 // add $at, $at, $8
2071 // sw $8, %lo(offset)($at)
2072 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2073 // ldc1 $f0, %lo(sym)($at)
2074 //
2075 // For load instructions we can use the destination register as a temporary
2076 // if base and dst are different (examples 1 and 2) and if the base register
2077 // is general purpose otherwise we must use $at (example 6) and error if it's
2078 // not available. For stores we must use $at (examples 4 and 5) because we
2079 // must not clobber the source register setting up the offset.
2080 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2081 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2082 unsigned RegClassIDOp0 =
2083 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2084 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2085 (RegClassIDOp0 == Mips::GPR64RegClassID);
2086 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002087 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002088 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002089 // At this point we need AT to perform the expansions and we exit if it is
2090 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002091 TmpRegNum = getATReg(IDLoc);
2092 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002093 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002094 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002095
Jack Carter9e65aa32013-03-22 00:05:30 +00002096 TempInst.setOpcode(Mips::LUi);
2097 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2098 if (isImmOpnd)
2099 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
2100 else {
2101 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002102 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00002103 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
2104 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
2105 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00002106 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002107 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002108 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00002109 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002110 }
2111 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002112 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002113 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002114 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002115 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002116 // Add temp register to base.
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002117 if (BaseRegNum != Mips::ZERO) {
2118 TempInst.setOpcode(Mips::ADDu);
2119 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2120 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2121 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
2122 Instructions.push_back(TempInst);
2123 TempInst.clear();
2124 }
Alp Tokercb402912014-01-24 17:20:08 +00002125 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002126 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002127 TempInst.setOpcode(Inst.getOpcode());
2128 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
2129 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2130 if (isImmOpnd)
2131 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
2132 else {
2133 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002134 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
2135 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
2136 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00002137 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002138 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002139 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00002140 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002141 }
2142 }
2143 Instructions.push_back(TempInst);
2144 TempInst.clear();
2145}
2146
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002147bool
2148MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2149 SmallVectorImpl<MCInst> &Instructions) {
2150 unsigned OpNum = Inst.getNumOperands();
2151 unsigned Opcode = Inst.getOpcode();
2152 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2153
2154 assert (Inst.getOperand(OpNum - 1).isImm() &&
2155 Inst.getOperand(OpNum - 2).isReg() &&
2156 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2157
2158 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2159 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2160 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2161 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2162 // It can be implemented as SWM16 or LWM16 instruction.
2163 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2164
2165 Inst.setOpcode(NewOpcode);
2166 Instructions.push_back(Inst);
2167 return false;
2168}
2169
Toma Tabacu234482a2015-03-16 12:03:39 +00002170void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
2171 SmallVectorImpl<MCInst> &Instructions) {
2172 MCInst NopInst;
2173 if (hasShortDelaySlot) {
2174 NopInst.setOpcode(Mips::MOVE16_MM);
2175 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2176 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2177 } else {
2178 NopInst.setOpcode(Mips::SLL);
2179 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2180 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2181 NopInst.addOperand(MCOperand::CreateImm(0));
2182 }
2183 Instructions.push_back(NopInst);
2184}
2185
Matheus Almeida595fcab2014-06-11 15:05:56 +00002186unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
2187 // As described by the Mips32r2 spec, the registers Rd and Rs for
2188 // jalr.hb must be different.
2189 unsigned Opcode = Inst.getOpcode();
2190
2191 if (Opcode == Mips::JALR_HB &&
2192 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
2193 return Match_RequiresDifferentSrcAndDst;
2194
2195 return Match_Success;
2196}
2197
David Blaikie960ea3f2014-06-08 16:18:35 +00002198bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
2199 OperandVector &Operands,
2200 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00002201 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00002202 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00002203
Jack Carterb4dbc172012-09-05 23:34:03 +00002204 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00002205 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00002206 unsigned MatchResult =
2207 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00002208
2209 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002210 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002211 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00002212 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00002213 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00002214 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00002215 return false;
2216 }
2217 case Match_MissingFeature:
2218 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
2219 return true;
2220 case Match_InvalidOperand: {
2221 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00002222 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002223 if (ErrorInfo >= Operands.size())
2224 return Error(IDLoc, "too few operands for instruction");
2225
David Blaikie960ea3f2014-06-08 16:18:35 +00002226 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00002227 if (ErrorLoc == SMLoc())
2228 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00002229 }
2230
2231 return Error(ErrorLoc, "invalid operand for instruction");
2232 }
2233 case Match_MnemonicFail:
2234 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00002235 case Match_RequiresDifferentSrcAndDst:
2236 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00002237 }
Craig Topper589ceee2015-01-03 08:16:34 +00002238
2239 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00002240}
2241
Toma Tabacud9d344b2015-04-27 14:05:04 +00002242void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
2243 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
2244 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
2245 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002246}
2247
Daniel Sandersef638fe2014-10-03 15:37:37 +00002248void
2249MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
2250 SMRange Range, bool ShowColors) {
2251 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00002252 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00002253 ShowColors);
2254}
2255
Jack Carter1ac53222013-02-20 23:11:17 +00002256int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002257 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002258
Vladimir Medic4c299852013-11-06 11:27:05 +00002259 CC = StringSwitch<unsigned>(Name)
2260 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002261 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00002262 .Case("a0", 4)
2263 .Case("a1", 5)
2264 .Case("a2", 6)
2265 .Case("a3", 7)
2266 .Case("v0", 2)
2267 .Case("v1", 3)
2268 .Case("s0", 16)
2269 .Case("s1", 17)
2270 .Case("s2", 18)
2271 .Case("s3", 19)
2272 .Case("s4", 20)
2273 .Case("s5", 21)
2274 .Case("s6", 22)
2275 .Case("s7", 23)
2276 .Case("k0", 26)
2277 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002278 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00002279 .Case("sp", 29)
2280 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002281 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00002282 .Case("ra", 31)
2283 .Case("t0", 8)
2284 .Case("t1", 9)
2285 .Case("t2", 10)
2286 .Case("t3", 11)
2287 .Case("t4", 12)
2288 .Case("t5", 13)
2289 .Case("t6", 14)
2290 .Case("t7", 15)
2291 .Case("t8", 24)
2292 .Case("t9", 25)
2293 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002294
Toma Tabacufda445c2014-09-15 15:33:01 +00002295 if (!(isABI_N32() || isABI_N64()))
2296 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002297
Daniel Sandersef638fe2014-10-03 15:37:37 +00002298 if (12 <= CC && CC <= 15) {
2299 // Name is one of t4-t7
2300 AsmToken RegTok = getLexer().peekTok();
2301 SMRange RegRange = RegTok.getLocRange();
2302
2303 StringRef FixedName = StringSwitch<StringRef>(Name)
2304 .Case("t4", "t0")
2305 .Case("t5", "t1")
2306 .Case("t6", "t2")
2307 .Case("t7", "t3")
2308 .Default("");
2309 assert(FixedName != "" && "Register name is not one of t4-t7.");
2310
2311 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
2312 "Did you mean $" + FixedName + "?", RegRange);
2313 }
2314
Toma Tabacufda445c2014-09-15 15:33:01 +00002315 // Although SGI documentation just cuts out t0-t3 for n32/n64,
2316 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
2317 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
2318 if (8 <= CC && CC <= 11)
2319 CC += 4;
2320
2321 if (CC == -1)
2322 CC = StringSwitch<unsigned>(Name)
2323 .Case("a4", 8)
2324 .Case("a5", 9)
2325 .Case("a6", 10)
2326 .Case("a7", 11)
2327 .Case("kt0", 26)
2328 .Case("kt1", 27)
2329 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002330
2331 return CC;
2332}
Jack Carterd0bd6422013-04-18 00:41:53 +00002333
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002334int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
2335 int CC;
2336
2337 CC = StringSwitch<unsigned>(Name)
2338 .Case("hwr_cpunum", 0)
2339 .Case("hwr_synci_step", 1)
2340 .Case("hwr_cc", 2)
2341 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00002342 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002343 .Default(-1);
2344
2345 return CC;
2346}
2347
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002348int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002349
Jack Cartera63b16a2012-09-07 00:23:42 +00002350 if (Name[0] == 'f') {
2351 StringRef NumString = Name.substr(1);
2352 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002353 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002354 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002355 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00002356 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002357 return IntVal;
2358 }
2359 return -1;
2360}
Jack Cartera63b16a2012-09-07 00:23:42 +00002361
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002362int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
2363
2364 if (Name.startswith("fcc")) {
2365 StringRef NumString = Name.substr(3);
2366 unsigned IntVal;
2367 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002368 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002369 if (IntVal > 7) // There are only 8 fcc registers.
2370 return -1;
2371 return IntVal;
2372 }
2373 return -1;
2374}
2375
2376int MipsAsmParser::matchACRegisterName(StringRef Name) {
2377
Akira Hatanaka274d24c2013-08-14 01:15:52 +00002378 if (Name.startswith("ac")) {
2379 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002380 unsigned IntVal;
2381 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002382 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002383 if (IntVal > 3) // There are only 3 acc registers.
2384 return -1;
2385 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00002386 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002387 return -1;
2388}
Jack Carterd0bd6422013-04-18 00:41:53 +00002389
Jack Carter5dc8ac92013-09-25 23:50:44 +00002390int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
2391 unsigned IntVal;
2392
2393 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2394 return -1;
2395
2396 if (IntVal > 31)
2397 return -1;
2398
2399 return IntVal;
2400}
2401
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002402int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
2403 int CC;
2404
2405 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00002406 .Case("msair", 0)
2407 .Case("msacsr", 1)
2408 .Case("msaaccess", 2)
2409 .Case("msasave", 3)
2410 .Case("msamodify", 4)
2411 .Case("msarequest", 5)
2412 .Case("msamap", 6)
2413 .Case("msaunmap", 7)
2414 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002415
2416 return CC;
2417}
2418
Toma Tabacu89a712b2015-04-15 10:48:56 +00002419unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00002420 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00002421 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002422 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00002423 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00002424 return 0;
2425 }
2426 unsigned AT = getReg(
2427 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00002428 return AT;
2429}
Jack Carter0b744b32012-10-04 02:29:46 +00002430
Jack Carterd0bd6422013-04-18 00:41:53 +00002431unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00002432 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00002433}
2434
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002435unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002436 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00002437 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002438}
2439
Jack Carter873c7242013-01-12 01:03:14 +00002440int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002441 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00002442 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00002443 return -1;
2444
Jack Carter873c7242013-01-12 01:03:14 +00002445 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00002446}
2447
Toma Tabacu13964452014-09-04 13:23:44 +00002448bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002449 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002450 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002451
Jack Carter30a59822012-10-04 04:03:53 +00002452 // Check if the current operand has a custom associated parser, if so, try to
2453 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00002454 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2455 if (ResTy == MatchOperand_Success)
2456 return false;
2457 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2458 // there was a match, but an error occurred, in which case, just return that
2459 // the operand parsing failed.
2460 if (ResTy == MatchOperand_ParseFail)
2461 return true;
2462
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002463 DEBUG(dbgs() << ".. Generic Parser\n");
2464
Jack Carterb4dbc172012-09-05 23:34:03 +00002465 switch (getLexer().getKind()) {
2466 default:
2467 Error(Parser.getTok().getLoc(), "unexpected token in operand");
2468 return true;
2469 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002470 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00002471 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00002472
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002473 // Almost all registers have been parsed by custom parsers. There is only
2474 // one exception to this. $zero (and it's alias $0) will reach this point
2475 // for div, divu, and similar instructions because it is not an operand
2476 // to the instruction definition but an explicit register. Special case
2477 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00002478 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00002479 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002480
Jack Carterd0bd6422013-04-18 00:41:53 +00002481 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00002482 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002483 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00002484 return true;
2485
Jack Carter873c7242013-01-12 01:03:14 +00002486 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00002487 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00002488 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00002489 const MCExpr *Res =
2490 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00002491
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002492 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002493 return false;
2494 }
Vladimir Medic4c299852013-11-06 11:27:05 +00002495 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00002496 case AsmToken::LParen:
2497 case AsmToken::Minus:
2498 case AsmToken::Plus:
2499 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002500 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00002501 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002502 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002503 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002504 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00002505 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00002506 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002507 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002508 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002509 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00002510 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00002511 return true;
2512
Jack Carter873c7242013-01-12 01:03:14 +00002513 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2514
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002515 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00002516 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002517 } // case AsmToken::Percent
2518 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00002519 return true;
2520}
2521
Vladimir Medic4c299852013-11-06 11:27:05 +00002522const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00002523 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00002524 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00002525 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002526 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00002527 // It's a constant, evaluate reloc value.
2528 int16_t Val;
2529 switch (getVariantKind(RelocStr)) {
2530 case MCSymbolRefExpr::VK_Mips_ABS_LO:
2531 // Get the 1st 16-bits.
2532 Val = MCE->getValue() & 0xffff;
2533 break;
2534 case MCSymbolRefExpr::VK_Mips_ABS_HI:
2535 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2536 // 16 bits being negative.
2537 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2538 break;
2539 case MCSymbolRefExpr::VK_Mips_HIGHER:
2540 // Get the 3rd 16-bits.
2541 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2542 break;
2543 case MCSymbolRefExpr::VK_Mips_HIGHEST:
2544 // Get the 4th 16-bits.
2545 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2546 break;
2547 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00002548 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00002549 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00002550 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002551 }
2552
Jack Carterb5cf5902013-04-17 00:18:04 +00002553 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002554 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00002555 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00002556 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00002557 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002558 return Res;
2559 }
2560
2561 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00002562 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2563
Sasa Stankovic06c47802014-04-03 10:37:45 +00002564 // Try to create target expression.
2565 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
2566 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002567
Jack Carterd0bd6422013-04-18 00:41:53 +00002568 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2569 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00002570 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
2571 return Res;
2572 }
2573
2574 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002575 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
2576 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
2577 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002578 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002579 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002580 return Expr;
2581}
2582
2583bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2584
2585 switch (Expr->getKind()) {
2586 case MCExpr::Constant:
2587 return true;
2588 case MCExpr::SymbolRef:
2589 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2590 case MCExpr::Binary:
2591 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2592 if (!isEvaluated(BE->getLHS()))
2593 return false;
2594 return isEvaluated(BE->getRHS());
2595 }
2596 case MCExpr::Unary:
2597 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002598 case MCExpr::Target:
2599 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002600 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002601 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002602}
Jack Carterd0bd6422013-04-18 00:41:53 +00002603
Jack Carterb5cf5902013-04-17 00:18:04 +00002604bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002605 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00002606 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002607 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002608 if (Tok.isNot(AsmToken::Identifier))
2609 return true;
2610
Yaron Keren075759a2015-03-30 15:42:36 +00002611 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00002612
Jack Carterd0bd6422013-04-18 00:41:53 +00002613 Parser.Lex(); // Eat the identifier.
2614 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002615 const MCExpr *IdVal;
2616 SMLoc EndLoc;
2617
2618 if (getLexer().getKind() == AsmToken::LParen) {
2619 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002620 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002621 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002622 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002623 const AsmToken &nextTok = Parser.getTok();
2624 if (nextTok.isNot(AsmToken::Identifier))
2625 return true;
2626 Str += "(%";
2627 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002628 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002629 if (getLexer().getKind() != AsmToken::LParen)
2630 return true;
2631 } else
2632 break;
2633 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002634 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002635 return true;
2636
2637 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002638 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002639
2640 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002641 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002642
Jack Carterd0bd6422013-04-18 00:41:53 +00002643 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002644 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002645}
2646
Jack Carterb4dbc172012-09-05 23:34:03 +00002647bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2648 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002649 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002650 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002651 if (ResTy == MatchOperand_Success) {
2652 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002653 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002654 StartLoc = Operand.getStartLoc();
2655 EndLoc = Operand.getEndLoc();
2656
2657 // AFAIK, we only support numeric registers and named GPR's in CFI
2658 // directives.
2659 // Don't worry about eating tokens before failing. Using an unrecognised
2660 // register is a parse error.
2661 if (Operand.isGPRAsmReg()) {
2662 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002663 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002664 }
2665
2666 return (RegNo == (unsigned)-1);
2667 }
2668
2669 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002670 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002671}
2672
Jack Carterb5cf5902013-04-17 00:18:04 +00002673bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002674 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00002675 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002676 bool Result = true;
2677
2678 while (getLexer().getKind() == AsmToken::LParen)
2679 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002680
Jack Carterd0bd6422013-04-18 00:41:53 +00002681 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002682 default:
2683 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002684 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002685 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002686 case AsmToken::Integer:
2687 case AsmToken::Minus:
2688 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002689 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002690 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002691 else
2692 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002693 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002694 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002695 break;
Jack Carter873c7242013-01-12 01:03:14 +00002696 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002697 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002698 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002699 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002700}
2701
David Blaikie960ea3f2014-06-08 16:18:35 +00002702MipsAsmParser::OperandMatchResultTy
2703MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002704 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002705 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002706 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002707 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002708 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002709 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002710 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002711 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002712
Jack Carterb5cf5902013-04-17 00:18:04 +00002713 if (getLexer().getKind() == AsmToken::LParen) {
2714 Parser.Lex();
2715 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002716 }
2717
Jack Carterb5cf5902013-04-17 00:18:04 +00002718 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002719 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002720 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002721
Jack Carterd0bd6422013-04-18 00:41:53 +00002722 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002723 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002724 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2725 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002726 SMLoc E =
2727 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002728 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002729 return MatchOperand_Success;
2730 }
2731 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002732 SMLoc E =
2733 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002734
Jack Carterd0bd6422013-04-18 00:41:53 +00002735 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002736 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002737 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002738 S, E, *this);
2739 Operands.push_back(
2740 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002741 return MatchOperand_Success;
2742 }
2743 Error(Parser.getTok().getLoc(), "'(' expected");
2744 return MatchOperand_ParseFail;
2745 }
2746
Jack Carterd0bd6422013-04-18 00:41:53 +00002747 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002748 }
2749
Toma Tabacu13964452014-09-04 13:23:44 +00002750 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002751 if (Res != MatchOperand_Success)
2752 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002753
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002754 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002755 Error(Parser.getTok().getLoc(), "')' expected");
2756 return MatchOperand_ParseFail;
2757 }
2758
Jack Carter873c7242013-01-12 01:03:14 +00002759 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2760
Jack Carterd0bd6422013-04-18 00:41:53 +00002761 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002762
Craig Topper062a2ba2014-04-25 05:30:21 +00002763 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002764 IdVal = MCConstantExpr::Create(0, getContext());
2765
Jack Carterd0bd6422013-04-18 00:41:53 +00002766 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002767 std::unique_ptr<MipsOperand> op(
2768 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002769 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002770 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002771 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002772 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002773 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2774 int64_t Imm;
2775 if (IdVal->EvaluateAsAbsolute(Imm))
2776 IdVal = MCConstantExpr::Create(Imm, getContext());
2777 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2778 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2779 getContext());
2780 }
2781
David Blaikie960ea3f2014-06-08 16:18:35 +00002782 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002783 return MatchOperand_Success;
2784}
2785
David Blaikie960ea3f2014-06-08 16:18:35 +00002786bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002787 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00002788 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2789 if (Sym) {
2790 SMLoc S = Parser.getTok().getLoc();
2791 const MCExpr *Expr;
2792 if (Sym->isVariable())
2793 Expr = Sym->getVariableValue();
2794 else
2795 return false;
2796 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002797 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002798 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002799 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002800 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002801 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002802 if (ResTy == MatchOperand_Success) {
2803 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002804 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002805 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002806 llvm_unreachable("Should never ParseFail");
2807 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002808 }
2809 } else if (Expr->getKind() == MCExpr::Constant) {
2810 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002811 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002812 Operands.push_back(
2813 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002814 return true;
2815 }
2816 }
2817 return false;
2818}
Jack Carterd0bd6422013-04-18 00:41:53 +00002819
Jack Carter873c7242013-01-12 01:03:14 +00002820MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002821MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002822 StringRef Identifier,
2823 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002824 int Index = matchCPURegisterName(Identifier);
2825 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002826 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002827 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2828 return MatchOperand_Success;
2829 }
2830
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002831 Index = matchHWRegsRegisterName(Identifier);
2832 if (Index != -1) {
2833 Operands.push_back(MipsOperand::createHWRegsReg(
2834 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2835 return MatchOperand_Success;
2836 }
2837
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002838 Index = matchFPURegisterName(Identifier);
2839 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002840 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002841 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2842 return MatchOperand_Success;
2843 }
2844
2845 Index = matchFCCRegisterName(Identifier);
2846 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002847 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002848 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2849 return MatchOperand_Success;
2850 }
2851
2852 Index = matchACRegisterName(Identifier);
2853 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002854 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002855 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2856 return MatchOperand_Success;
2857 }
2858
2859 Index = matchMSA128RegisterName(Identifier);
2860 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002861 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002862 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2863 return MatchOperand_Success;
2864 }
2865
2866 Index = matchMSA128CtrlRegisterName(Identifier);
2867 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002868 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002869 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2870 return MatchOperand_Success;
2871 }
2872
2873 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002874}
2875
2876MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002877MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002878 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00002879 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002880
2881 if (Token.is(AsmToken::Identifier)) {
2882 DEBUG(dbgs() << ".. identifier\n");
2883 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002884 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002885 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002886 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002887 } else if (Token.is(AsmToken::Integer)) {
2888 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002889 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002890 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2891 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002892 return MatchOperand_Success;
2893 }
2894
2895 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2896
2897 return MatchOperand_NoMatch;
2898}
2899
David Blaikie960ea3f2014-06-08 16:18:35 +00002900MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002901MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002902 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002903 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002904
2905 auto Token = Parser.getTok();
2906
2907 SMLoc S = Token.getLoc();
2908
2909 if (Token.isNot(AsmToken::Dollar)) {
2910 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2911 if (Token.is(AsmToken::Identifier)) {
2912 if (searchSymbolAlias(Operands))
2913 return MatchOperand_Success;
2914 }
2915 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2916 return MatchOperand_NoMatch;
2917 }
2918 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002919
Toma Tabacu13964452014-09-04 13:23:44 +00002920 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002921 if (ResTy == MatchOperand_Success) {
2922 Parser.Lex(); // $
2923 Parser.Lex(); // identifier
2924 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002925 return ResTy;
2926}
2927
2928MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002929MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002930 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002931 switch (getLexer().getKind()) {
2932 default:
2933 return MatchOperand_NoMatch;
2934 case AsmToken::LParen:
2935 case AsmToken::Minus:
2936 case AsmToken::Plus:
2937 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002938 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002939 case AsmToken::String:
2940 break;
2941 }
2942
2943 const MCExpr *IdVal;
2944 SMLoc S = Parser.getTok().getLoc();
2945 if (getParser().parseExpression(IdVal))
2946 return MatchOperand_ParseFail;
2947
2948 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2949 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2950 return MatchOperand_Success;
2951}
2952
David Blaikie960ea3f2014-06-08 16:18:35 +00002953MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002954MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002955 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002956 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002957
2958 SMLoc S = getLexer().getLoc();
2959
2960 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002961 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002962 if (ResTy != MatchOperand_NoMatch)
2963 return ResTy;
2964
Daniel Sanders315386c2014-04-01 10:40:14 +00002965 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002966 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002967 if (ResTy != MatchOperand_NoMatch)
2968 return ResTy;
2969
Daniel Sandersffd84362014-04-01 10:41:48 +00002970 const MCExpr *Expr = nullptr;
2971 if (Parser.parseExpression(Expr)) {
2972 // We have no way of knowing if a symbol was consumed so we must ParseFail
2973 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002974 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002975 Operands.push_back(
2976 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002977 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002978}
2979
Vladimir Medic2b953d02013-10-01 09:48:56 +00002980MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002981MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002982 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00002983 const MCExpr *IdVal;
2984 // If the first token is '$' we may have register operand.
2985 if (Parser.getTok().is(AsmToken::Dollar))
2986 return MatchOperand_NoMatch;
2987 SMLoc S = Parser.getTok().getLoc();
2988 if (getParser().parseExpression(IdVal))
2989 return MatchOperand_ParseFail;
2990 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002991 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002992 int64_t Val = MCE->getValue();
2993 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2994 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002995 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002996 return MatchOperand_Success;
2997}
2998
Matheus Almeida779c5932013-11-18 12:32:49 +00002999MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003000MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003001 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00003002 switch (getLexer().getKind()) {
3003 default:
3004 return MatchOperand_NoMatch;
3005 case AsmToken::LParen:
3006 case AsmToken::Plus:
3007 case AsmToken::Minus:
3008 case AsmToken::Integer:
3009 break;
3010 }
3011
3012 const MCExpr *Expr;
3013 SMLoc S = Parser.getTok().getLoc();
3014
3015 if (getParser().parseExpression(Expr))
3016 return MatchOperand_ParseFail;
3017
3018 int64_t Val;
3019 if (!Expr->EvaluateAsAbsolute(Val)) {
3020 Error(S, "expected immediate value");
3021 return MatchOperand_ParseFail;
3022 }
3023
3024 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
3025 // and because the CPU always adds one to the immediate field, the allowed
3026 // range becomes 1..4. We'll only check the range here and will deal
3027 // with the addition/subtraction when actually decoding/encoding
3028 // the instruction.
3029 if (Val < 1 || Val > 4) {
3030 Error(S, "immediate not in range (1..4)");
3031 return MatchOperand_ParseFail;
3032 }
3033
Jack Carter3b2c96e2014-01-22 23:31:38 +00003034 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003035 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00003036 return MatchOperand_Success;
3037}
3038
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00003039MipsAsmParser::OperandMatchResultTy
3040MipsAsmParser::parseRegisterList(OperandVector &Operands) {
3041 MCAsmParser &Parser = getParser();
3042 SmallVector<unsigned, 10> Regs;
3043 unsigned RegNo;
3044 unsigned PrevReg = Mips::NoRegister;
3045 bool RegRange = false;
3046 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3047
3048 if (Parser.getTok().isNot(AsmToken::Dollar))
3049 return MatchOperand_ParseFail;
3050
3051 SMLoc S = Parser.getTok().getLoc();
3052 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
3053 SMLoc E = getLexer().getLoc();
3054 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
3055 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
3056 if (RegRange) {
3057 // Remove last register operand because registers from register range
3058 // should be inserted first.
3059 if (RegNo == Mips::RA) {
3060 Regs.push_back(RegNo);
3061 } else {
3062 unsigned TmpReg = PrevReg + 1;
3063 while (TmpReg <= RegNo) {
3064 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
3065 Error(E, "invalid register operand");
3066 return MatchOperand_ParseFail;
3067 }
3068
3069 PrevReg = TmpReg;
3070 Regs.push_back(TmpReg++);
3071 }
3072 }
3073
3074 RegRange = false;
3075 } else {
3076 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
3077 (RegNo != Mips::RA)) {
3078 Error(E, "$16 or $31 expected");
3079 return MatchOperand_ParseFail;
3080 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
3081 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3082 Error(E, "invalid register operand");
3083 return MatchOperand_ParseFail;
3084 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
3085 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3086 Error(E, "consecutive register numbers expected");
3087 return MatchOperand_ParseFail;
3088 }
3089
3090 Regs.push_back(RegNo);
3091 }
3092
3093 if (Parser.getTok().is(AsmToken::Minus))
3094 RegRange = true;
3095
3096 if (!Parser.getTok().isNot(AsmToken::Minus) &&
3097 !Parser.getTok().isNot(AsmToken::Comma)) {
3098 Error(E, "',' or '-' expected");
3099 return MatchOperand_ParseFail;
3100 }
3101
3102 Lex(); // Consume comma or minus
3103 if (Parser.getTok().isNot(AsmToken::Dollar))
3104 break;
3105
3106 PrevReg = RegNo;
3107 }
3108
3109 SMLoc E = Parser.getTok().getLoc();
3110 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3111 parseMemOperand(Operands);
3112 return MatchOperand_Success;
3113}
3114
Zoran Jovanovic2deca342014-12-16 14:59:10 +00003115MipsAsmParser::OperandMatchResultTy
3116MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
3117 MCAsmParser &Parser = getParser();
3118
3119 SMLoc S = Parser.getTok().getLoc();
3120 if (parseAnyRegister(Operands) != MatchOperand_Success)
3121 return MatchOperand_ParseFail;
3122
3123 SMLoc E = Parser.getTok().getLoc();
3124 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
3125 unsigned Reg = Op.getGPR32Reg();
3126 Operands.pop_back();
3127 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
3128 return MatchOperand_Success;
3129}
3130
Zoran Jovanovic41688672015-02-10 16:36:20 +00003131MipsAsmParser::OperandMatchResultTy
3132MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
3133 MCAsmParser &Parser = getParser();
3134 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3135 SmallVector<unsigned, 10> Regs;
3136
3137 if (Parser.getTok().isNot(AsmToken::Dollar))
3138 return MatchOperand_ParseFail;
3139
3140 SMLoc S = Parser.getTok().getLoc();
3141
3142 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3143 return MatchOperand_ParseFail;
3144
3145 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3146 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3147 Regs.push_back(RegNo);
3148
3149 SMLoc E = Parser.getTok().getLoc();
3150 if (Parser.getTok().isNot(AsmToken::Comma)) {
3151 Error(E, "',' expected");
3152 return MatchOperand_ParseFail;
3153 }
3154
3155 // Remove comma.
3156 Parser.Lex();
3157
3158 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3159 return MatchOperand_ParseFail;
3160
3161 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3162 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3163 Regs.push_back(RegNo);
3164
3165 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3166
3167 return MatchOperand_Success;
3168}
3169
Jack Carterdc1e35d2012-09-06 20:00:02 +00003170MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
3171
Vladimir Medic4c299852013-11-06 11:27:05 +00003172 MCSymbolRefExpr::VariantKind VK =
3173 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
3174 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
3175 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
3176 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
3177 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
3178 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
3179 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
3180 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
3181 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
3182 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
3183 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
3184 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
3185 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
3186 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
3187 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
3188 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
3189 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
3190 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00003191 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
3192 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
3193 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
3194 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
3195 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
3196 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00003197 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
3198 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00003199 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003200
Matheus Almeida2852af82014-04-22 10:15:54 +00003201 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00003202
Jack Carterdc1e35d2012-09-06 20:00:02 +00003203 return VK;
3204}
Jack Cartera63b16a2012-09-07 00:23:42 +00003205
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003206/// Sometimes (i.e. load/stores) the operand may be followed immediately by
3207/// either this.
3208/// ::= '(', register, ')'
3209/// handle it before we iterate so we don't get tripped up by the lack of
3210/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003211bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003212 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003213 if (getLexer().is(AsmToken::LParen)) {
3214 Operands.push_back(
3215 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
3216 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003217 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003218 SMLoc Loc = getLexer().getLoc();
3219 Parser.eatToEndOfStatement();
3220 return Error(Loc, "unexpected token in argument list");
3221 }
3222 if (Parser.getTok().isNot(AsmToken::RParen)) {
3223 SMLoc Loc = getLexer().getLoc();
3224 Parser.eatToEndOfStatement();
3225 return Error(Loc, "unexpected token, expected ')'");
3226 }
3227 Operands.push_back(
3228 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
3229 Parser.Lex();
3230 }
3231 return false;
3232}
3233
3234/// Sometimes (i.e. in MSA) the operand may be followed immediately by
3235/// either one of these.
3236/// ::= '[', register, ']'
3237/// ::= '[', integer, ']'
3238/// handle it before we iterate so we don't get tripped up by the lack of
3239/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003240bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00003241 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003242 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003243 if (getLexer().is(AsmToken::LBrac)) {
3244 Operands.push_back(
3245 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
3246 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003247 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003248 SMLoc Loc = getLexer().getLoc();
3249 Parser.eatToEndOfStatement();
3250 return Error(Loc, "unexpected token in argument list");
3251 }
3252 if (Parser.getTok().isNot(AsmToken::RBrac)) {
3253 SMLoc Loc = getLexer().getLoc();
3254 Parser.eatToEndOfStatement();
3255 return Error(Loc, "unexpected token, expected ']'");
3256 }
3257 Operands.push_back(
3258 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
3259 Parser.Lex();
3260 }
3261 return false;
3262}
3263
David Blaikie960ea3f2014-06-08 16:18:35 +00003264bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
3265 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003266 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003267 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003268
3269 // We have reached first instruction, module directive are now forbidden.
3270 getTargetStreamer().forbidModuleDirective();
3271
Vladimir Medic74593e62013-07-17 15:00:42 +00003272 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00003273 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00003274 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00003275 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00003276 }
Vladimir Medic64828a12013-07-16 10:07:14 +00003277 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003278 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003279
3280 // Read the remaining operands.
3281 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3282 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003283 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003284 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003285 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003286 return Error(Loc, "unexpected token in argument list");
3287 }
Toma Tabacu13964452014-09-04 13:23:44 +00003288 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003289 return true;
3290 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00003291
Jack Carterd0bd6422013-04-18 00:41:53 +00003292 while (getLexer().is(AsmToken::Comma)) {
3293 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00003294 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003295 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003296 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003297 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003298 return Error(Loc, "unexpected token in argument list");
3299 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003300 // Parse bracket and parenthesis suffixes before we iterate
3301 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00003302 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003303 return true;
3304 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00003305 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003306 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003307 }
3308 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003309 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3310 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003311 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003312 return Error(Loc, "unexpected token in argument list");
3313 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003314 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00003315 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00003316}
3317
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003318bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003319 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003320 SMLoc Loc = getLexer().getLoc();
3321 Parser.eatToEndOfStatement();
3322 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00003323}
3324
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003325bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003326 return Error(Loc, ErrorMsg);
3327}
3328
Jack Carter0b744b32012-10-04 02:29:46 +00003329bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003330 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003331 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00003332
3333 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00003334 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00003335
3336 Parser.Lex(); // Eat "noat".
3337
Jack Carterd0bd6422013-04-18 00:41:53 +00003338 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003339 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003340 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003341 return false;
3342 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003343
3344 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003345 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003346 return false;
3347}
Jack Carterd0bd6422013-04-18 00:41:53 +00003348
Jack Carter0b744b32012-10-04 02:29:46 +00003349bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00003350 // Line can be: ".set at", which sets $at to $1
3351 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00003352 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00003353 Parser.Lex(); // Eat "at".
3354
Jack Carter0b744b32012-10-04 02:29:46 +00003355 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003356 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00003357 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00003358
3359 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003360 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003361 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00003362 }
3363
3364 if (getLexer().isNot(AsmToken::Equal)) {
3365 reportParseError("unexpected token, expected equals sign");
3366 return false;
3367 }
3368 Parser.Lex(); // Eat "=".
3369
3370 if (getLexer().isNot(AsmToken::Dollar)) {
3371 if (getLexer().is(AsmToken::EndOfStatement)) {
3372 reportParseError("no register specified");
3373 return false;
3374 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00003375 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00003376 return false;
3377 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003378 }
3379 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00003380
Toma Tabacu16a74492015-02-13 10:30:57 +00003381 // Find out what "reg" is.
3382 unsigned AtRegNo;
3383 const AsmToken &Reg = Parser.getTok();
3384 if (Reg.is(AsmToken::Identifier)) {
3385 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
3386 } else if (Reg.is(AsmToken::Integer)) {
3387 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00003388 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00003389 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00003390 return false;
3391 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003392
3393 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00003394 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003395 reportParseError("invalid register");
3396 return false;
3397 }
3398 Parser.Lex(); // Eat "reg".
3399
3400 // If this is not the end of the statement, report an error.
3401 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3402 reportParseError("unexpected token, expected end of statement");
3403 return false;
3404 }
3405
3406 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
3407
3408 Parser.Lex(); // Consume the EndOfStatement.
3409 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003410}
3411
3412bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003413 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003414 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003415 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003416 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003417 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003418 return false;
3419 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003420 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00003421 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003422 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003423 return false;
3424}
3425
3426bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003427 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003428 Parser.Lex();
3429 // If this is not the end of the statement, report an error.
3430 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003431 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003432 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003433 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003434 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00003435 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003436 Parser.Lex(); // Consume the EndOfStatement.
3437 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003438}
3439
3440bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003441 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003442 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003443 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003444 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003445 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003446 return false;
3447 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003448 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003449 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003450 return false;
3451}
3452
3453bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003454 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003455 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003456 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003457 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003458 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003459 return false;
3460 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003461 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00003462 reportParseError("`noreorder' must be set before `nomacro'");
3463 return false;
3464 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003465 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003466 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003467 return false;
3468}
Jack Carterd76b2372013-03-21 21:44:16 +00003469
Daniel Sanders44934432014-08-07 12:03:36 +00003470bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003471 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003472 Parser.Lex();
3473
3474 // If this is not the end of the statement, report an error.
3475 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003476 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003477
3478 setFeatureBits(Mips::FeatureMSA, "msa");
3479 getTargetStreamer().emitDirectiveSetMsa();
3480 return false;
3481}
3482
3483bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003484 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003485 Parser.Lex();
3486
3487 // If this is not the end of the statement, report an error.
3488 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003489 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003490
3491 clearFeatureBits(Mips::FeatureMSA, "msa");
3492 getTargetStreamer().emitDirectiveSetNoMsa();
3493 return false;
3494}
3495
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003496bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003497 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003498 Parser.Lex(); // Eat "nodsp".
3499
3500 // If this is not the end of the statement, report an error.
3501 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3502 reportParseError("unexpected token, expected end of statement");
3503 return false;
3504 }
3505
3506 clearFeatureBits(Mips::FeatureDSP, "dsp");
3507 getTargetStreamer().emitDirectiveSetNoDsp();
3508 return false;
3509}
3510
Toma Tabacucc2502d2014-11-04 17:18:07 +00003511bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003512 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003513 Parser.Lex(); // Eat "mips16".
3514
Jack Carter39536722014-01-22 23:08:42 +00003515 // If this is not the end of the statement, report an error.
3516 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003517 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00003518 return false;
3519 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00003520
3521 setFeatureBits(Mips::FeatureMips16, "mips16");
3522 getTargetStreamer().emitDirectiveSetMips16();
3523 Parser.Lex(); // Consume the EndOfStatement.
3524 return false;
3525}
3526
3527bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003528 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003529 Parser.Lex(); // Eat "nomips16".
3530
3531 // If this is not the end of the statement, report an error.
3532 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3533 reportParseError("unexpected token, expected end of statement");
3534 return false;
3535 }
3536
3537 clearFeatureBits(Mips::FeatureMips16, "mips16");
3538 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00003539 Parser.Lex(); // Consume the EndOfStatement.
3540 return false;
3541}
3542
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003543bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003544 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003545 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003546 // Line can be: .set fp=32
3547 // .set fp=xx
3548 // .set fp=64
3549 Parser.Lex(); // Eat fp token
3550 AsmToken Tok = Parser.getTok();
3551 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003552 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003553 return false;
3554 }
3555 Parser.Lex(); // Eat '=' token.
3556 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003557
3558 if (!parseFpABIValue(FpAbiVal, ".set"))
3559 return false;
3560
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003561 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003562 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003563 return false;
3564 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003565 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003566 Parser.Lex(); // Consume the EndOfStatement.
3567 return false;
3568}
3569
Toma Tabacu9db22db2014-09-09 10:15:38 +00003570bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003571 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003572 SMLoc Loc = getLexer().getLoc();
3573
3574 Parser.Lex();
3575 if (getLexer().isNot(AsmToken::EndOfStatement))
3576 return reportParseError("unexpected token, expected end of statement");
3577
3578 // Always keep an element on the options "stack" to prevent the user
3579 // from changing the initial options. This is how we remember them.
3580 if (AssemblerOptions.size() == 2)
3581 return reportParseError(Loc, ".set pop with no .set push");
3582
3583 AssemblerOptions.pop_back();
3584 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
3585
3586 getTargetStreamer().emitDirectiveSetPop();
3587 return false;
3588}
3589
3590bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003591 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003592 Parser.Lex();
3593 if (getLexer().isNot(AsmToken::EndOfStatement))
3594 return reportParseError("unexpected token, expected end of statement");
3595
3596 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00003597 AssemblerOptions.push_back(
3598 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00003599
3600 getTargetStreamer().emitDirectiveSetPush();
3601 return false;
3602}
3603
Jack Carterd76b2372013-03-21 21:44:16 +00003604bool MipsAsmParser::parseSetAssignment() {
3605 StringRef Name;
3606 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00003607 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00003608
3609 if (Parser.parseIdentifier(Name))
3610 reportParseError("expected identifier after .set");
3611
3612 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003613 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00003614 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00003615
Jack Carter3b2c96e2014-01-22 23:31:38 +00003616 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00003617 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00003618
Toma Tabacuf25949b2015-04-07 13:59:39 +00003619 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00003620 Sym->setVariableValue(Value);
3621
3622 return false;
3623}
Jack Carterd0bd6422013-04-18 00:41:53 +00003624
Toma Tabacu26647792014-09-09 12:52:14 +00003625bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003626 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00003627 Parser.Lex();
3628 if (getLexer().isNot(AsmToken::EndOfStatement))
3629 return reportParseError("unexpected token, expected end of statement");
3630
3631 // Reset assembler options to their initial values.
3632 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
3633 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
3634
3635 getTargetStreamer().emitDirectiveSetMips0();
3636 return false;
3637}
3638
Toma Tabacu85618b32014-08-19 14:22:52 +00003639bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003640 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00003641 Parser.Lex();
3642 if (getLexer().isNot(AsmToken::Equal))
3643 return reportParseError("unexpected token, expected equals sign");
3644
3645 Parser.Lex();
3646 StringRef Arch;
3647 if (Parser.parseIdentifier(Arch))
3648 return reportParseError("expected arch identifier");
3649
3650 StringRef ArchFeatureName =
3651 StringSwitch<StringRef>(Arch)
3652 .Case("mips1", "mips1")
3653 .Case("mips2", "mips2")
3654 .Case("mips3", "mips3")
3655 .Case("mips4", "mips4")
3656 .Case("mips5", "mips5")
3657 .Case("mips32", "mips32")
3658 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003659 .Case("mips32r3", "mips32r3")
3660 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003661 .Case("mips32r6", "mips32r6")
3662 .Case("mips64", "mips64")
3663 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003664 .Case("mips64r3", "mips64r3")
3665 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003666 .Case("mips64r6", "mips64r6")
3667 .Case("cnmips", "cnmips")
3668 .Case("r4000", "mips3") // This is an implementation of Mips3.
3669 .Default("");
3670
3671 if (ArchFeatureName.empty())
3672 return reportParseError("unsupported architecture");
3673
3674 selectArch(ArchFeatureName);
3675 getTargetStreamer().emitDirectiveSetArch(Arch);
3676 return false;
3677}
3678
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003679bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003680 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003681 Parser.Lex();
3682 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003683 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003684
Matheus Almeida2852af82014-04-22 10:15:54 +00003685 switch (Feature) {
3686 default:
3687 llvm_unreachable("Unimplemented feature");
3688 case Mips::FeatureDSP:
3689 setFeatureBits(Mips::FeatureDSP, "dsp");
3690 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003691 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003692 case Mips::FeatureMicroMips:
3693 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003694 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003695 case Mips::FeatureMips1:
3696 selectArch("mips1");
3697 getTargetStreamer().emitDirectiveSetMips1();
3698 break;
3699 case Mips::FeatureMips2:
3700 selectArch("mips2");
3701 getTargetStreamer().emitDirectiveSetMips2();
3702 break;
3703 case Mips::FeatureMips3:
3704 selectArch("mips3");
3705 getTargetStreamer().emitDirectiveSetMips3();
3706 break;
3707 case Mips::FeatureMips4:
3708 selectArch("mips4");
3709 getTargetStreamer().emitDirectiveSetMips4();
3710 break;
3711 case Mips::FeatureMips5:
3712 selectArch("mips5");
3713 getTargetStreamer().emitDirectiveSetMips5();
3714 break;
3715 case Mips::FeatureMips32:
3716 selectArch("mips32");
3717 getTargetStreamer().emitDirectiveSetMips32();
3718 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003719 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003720 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003721 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003722 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003723 case Mips::FeatureMips32r3:
3724 selectArch("mips32r3");
3725 getTargetStreamer().emitDirectiveSetMips32R3();
3726 break;
3727 case Mips::FeatureMips32r5:
3728 selectArch("mips32r5");
3729 getTargetStreamer().emitDirectiveSetMips32R5();
3730 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003731 case Mips::FeatureMips32r6:
3732 selectArch("mips32r6");
3733 getTargetStreamer().emitDirectiveSetMips32R6();
3734 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003735 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003736 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00003737 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003738 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003739 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003740 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003741 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003742 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003743 case Mips::FeatureMips64r3:
3744 selectArch("mips64r3");
3745 getTargetStreamer().emitDirectiveSetMips64R3();
3746 break;
3747 case Mips::FeatureMips64r5:
3748 selectArch("mips64r5");
3749 getTargetStreamer().emitDirectiveSetMips64R5();
3750 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003751 case Mips::FeatureMips64r6:
3752 selectArch("mips64r6");
3753 getTargetStreamer().emitDirectiveSetMips64R6();
3754 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003755 }
3756 return false;
3757}
3758
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003759bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003760 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003761 if (getLexer().isNot(AsmToken::Comma)) {
3762 SMLoc Loc = getLexer().getLoc();
3763 Parser.eatToEndOfStatement();
3764 return Error(Loc, ErrorStr);
3765 }
3766
Matheus Almeida2852af82014-04-22 10:15:54 +00003767 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003768 return true;
3769}
3770
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003771bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003772 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00003773 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003774
Toma Tabacudde4c462014-11-06 10:02:45 +00003775 if (inMips16Mode()) {
3776 reportParseError(".cpload is not supported in Mips16 mode");
3777 return false;
3778 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003779
David Blaikie960ea3f2014-06-08 16:18:35 +00003780 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00003781 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003782 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3783 reportParseError("expected register containing function address");
3784 return false;
3785 }
3786
David Blaikie960ea3f2014-06-08 16:18:35 +00003787 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
3788 if (!RegOpnd.isGPRAsmReg()) {
3789 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003790 return false;
3791 }
3792
Toma Tabacudde4c462014-11-06 10:02:45 +00003793 // If this is not the end of the statement, report an error.
3794 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3795 reportParseError("unexpected token, expected end of statement");
3796 return false;
3797 }
3798
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003799 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003800 return false;
3801}
3802
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003803bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003804 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003805 unsigned FuncReg;
3806 unsigned Save;
3807 bool SaveIsReg = true;
3808
Matheus Almeida7e815762014-06-18 13:08:59 +00003809 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003810 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003811 if (ResTy == MatchOperand_NoMatch) {
3812 reportParseError("expected register containing function address");
3813 Parser.eatToEndOfStatement();
3814 return false;
3815 }
3816
3817 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3818 if (!FuncRegOpnd.isGPRAsmReg()) {
3819 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3820 Parser.eatToEndOfStatement();
3821 return false;
3822 }
3823
3824 FuncReg = FuncRegOpnd.getGPR32Reg();
3825 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003826
Toma Tabacu65f10572014-09-16 15:00:52 +00003827 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003828 return true;
3829
Toma Tabacu13964452014-09-04 13:23:44 +00003830 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003831 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003832 const AsmToken &Tok = Parser.getTok();
3833 if (Tok.is(AsmToken::Integer)) {
3834 Save = Tok.getIntVal();
3835 SaveIsReg = false;
3836 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003837 } else {
3838 reportParseError("expected save register or stack offset");
3839 Parser.eatToEndOfStatement();
3840 return false;
3841 }
3842 } else {
3843 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3844 if (!SaveOpnd.isGPRAsmReg()) {
3845 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3846 Parser.eatToEndOfStatement();
3847 return false;
3848 }
3849 Save = SaveOpnd.getGPR32Reg();
3850 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003851
Toma Tabacu65f10572014-09-16 15:00:52 +00003852 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003853 return true;
3854
Toma Tabacu8874eac2015-02-18 13:46:53 +00003855 const MCExpr *Expr;
3856 if (Parser.parseExpression(Expr)) {
3857 reportParseError("expected expression");
3858 return false;
3859 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003860
Toma Tabacu8874eac2015-02-18 13:46:53 +00003861 if (Expr->getKind() != MCExpr::SymbolRef) {
3862 reportParseError("expected symbol");
3863 return false;
3864 }
3865 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
3866
3867 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
3868 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003869 return false;
3870}
3871
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003872bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003873 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003874 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3875 const AsmToken &Tok = Parser.getTok();
3876
3877 if (Tok.getString() == "2008") {
3878 Parser.Lex();
3879 getTargetStreamer().emitDirectiveNaN2008();
3880 return false;
3881 } else if (Tok.getString() == "legacy") {
3882 Parser.Lex();
3883 getTargetStreamer().emitDirectiveNaNLegacy();
3884 return false;
3885 }
3886 }
3887 // If we don't recognize the option passed to the .nan
3888 // directive (e.g. no option or unknown option), emit an error.
3889 reportParseError("invalid option in .nan directive");
3890 return false;
3891}
3892
Jack Carter0b744b32012-10-04 02:29:46 +00003893bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003894 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003895 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003896 const AsmToken &Tok = Parser.getTok();
3897
3898 if (Tok.getString() == "noat") {
3899 return parseSetNoAtDirective();
3900 } else if (Tok.getString() == "at") {
3901 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003902 } else if (Tok.getString() == "arch") {
3903 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003904 } else if (Tok.getString() == "fp") {
3905 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003906 } else if (Tok.getString() == "pop") {
3907 return parseSetPopDirective();
3908 } else if (Tok.getString() == "push") {
3909 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003910 } else if (Tok.getString() == "reorder") {
3911 return parseSetReorderDirective();
3912 } else if (Tok.getString() == "noreorder") {
3913 return parseSetNoReorderDirective();
3914 } else if (Tok.getString() == "macro") {
3915 return parseSetMacroDirective();
3916 } else if (Tok.getString() == "nomacro") {
3917 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003918 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00003919 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003920 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003921 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003922 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003923 getTargetStreamer().emitDirectiveSetNoMicroMips();
3924 Parser.eatToEndOfStatement();
3925 return false;
3926 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003927 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003928 } else if (Tok.getString() == "mips0") {
3929 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003930 } else if (Tok.getString() == "mips1") {
3931 return parseSetFeature(Mips::FeatureMips1);
3932 } else if (Tok.getString() == "mips2") {
3933 return parseSetFeature(Mips::FeatureMips2);
3934 } else if (Tok.getString() == "mips3") {
3935 return parseSetFeature(Mips::FeatureMips3);
3936 } else if (Tok.getString() == "mips4") {
3937 return parseSetFeature(Mips::FeatureMips4);
3938 } else if (Tok.getString() == "mips5") {
3939 return parseSetFeature(Mips::FeatureMips5);
3940 } else if (Tok.getString() == "mips32") {
3941 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003942 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003943 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003944 } else if (Tok.getString() == "mips32r3") {
3945 return parseSetFeature(Mips::FeatureMips32r3);
3946 } else if (Tok.getString() == "mips32r5") {
3947 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003948 } else if (Tok.getString() == "mips32r6") {
3949 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003950 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003951 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003952 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003953 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003954 } else if (Tok.getString() == "mips64r3") {
3955 return parseSetFeature(Mips::FeatureMips64r3);
3956 } else if (Tok.getString() == "mips64r5") {
3957 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003958 } else if (Tok.getString() == "mips64r6") {
3959 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003960 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003961 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003962 } else if (Tok.getString() == "nodsp") {
3963 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003964 } else if (Tok.getString() == "msa") {
3965 return parseSetMsaDirective();
3966 } else if (Tok.getString() == "nomsa") {
3967 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003968 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003969 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003970 parseSetAssignment();
3971 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003972 }
Jack Carter07c818d2013-01-25 01:31:34 +00003973
Jack Carter0b744b32012-10-04 02:29:46 +00003974 return true;
3975}
3976
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003977/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003978/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003979bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003980 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003981 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3982 for (;;) {
3983 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003984 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003985 return true;
3986
3987 getParser().getStreamer().EmitValue(Value, Size);
3988
3989 if (getLexer().is(AsmToken::EndOfStatement))
3990 break;
3991
Jack Carter07c818d2013-01-25 01:31:34 +00003992 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003993 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00003994 Parser.Lex();
3995 }
3996 }
3997
3998 Parser.Lex();
3999 return false;
4000}
4001
Vladimir Medic4c299852013-11-06 11:27:05 +00004002/// parseDirectiveGpWord
4003/// ::= .gpword local_sym
4004bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004005 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004006 const MCExpr *Value;
4007 // EmitGPRel32Value requires an expression, so we are using base class
4008 // method to evaluate the expression.
4009 if (getParser().parseExpression(Value))
4010 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00004011 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00004012
Vladimir Medice10c1122013-11-13 13:18:04 +00004013 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004014 return Error(getLexer().getLoc(),
4015 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00004016 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00004017 return false;
4018}
4019
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004020/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00004021/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004022bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004023 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004024 const MCExpr *Value;
4025 // EmitGPRel64Value requires an expression, so we are using base class
4026 // method to evaluate the expression.
4027 if (getParser().parseExpression(Value))
4028 return true;
4029 getParser().getStreamer().EmitGPRel64Value(Value);
4030
4031 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004032 return Error(getLexer().getLoc(),
4033 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00004034 Parser.Lex(); // Eat EndOfStatement token.
4035 return false;
4036}
4037
Jack Carter0cd3c192014-01-06 23:27:31 +00004038bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004039 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00004040 // Get the option token.
4041 AsmToken Tok = Parser.getTok();
4042 // At the moment only identifiers are supported.
4043 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004044 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00004045 Parser.eatToEndOfStatement();
4046 return false;
4047 }
4048
4049 StringRef Option = Tok.getIdentifier();
4050
4051 if (Option == "pic0") {
4052 getTargetStreamer().emitDirectiveOptionPic0();
4053 Parser.Lex();
4054 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4055 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004056 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004057 Parser.eatToEndOfStatement();
4058 }
4059 return false;
4060 }
4061
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004062 if (Option == "pic2") {
4063 getTargetStreamer().emitDirectiveOptionPic2();
4064 Parser.Lex();
4065 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4066 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004067 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004068 Parser.eatToEndOfStatement();
4069 }
4070 return false;
4071 }
4072
Jack Carter0cd3c192014-01-06 23:27:31 +00004073 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00004074 Warning(Parser.getTok().getLoc(),
4075 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00004076 Parser.eatToEndOfStatement();
4077 return false;
4078}
4079
Toma Tabacu9ca50962015-04-16 09:53:47 +00004080/// parseInsnDirective
4081/// ::= .insn
4082bool MipsAsmParser::parseInsnDirective() {
4083 // If this is not the end of the statement, report an error.
4084 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4085 reportParseError("unexpected token, expected end of statement");
4086 return false;
4087 }
4088
4089 // The actual label marking happens in
4090 // MipsELFStreamer::createPendingLabelRelocs().
4091 getTargetStreamer().emitDirectiveInsn();
4092
4093 getParser().Lex(); // Eat EndOfStatement token.
4094 return false;
4095}
4096
Daniel Sanders7e527422014-07-10 13:38:23 +00004097/// parseDirectiveModule
4098/// ::= .module oddspreg
4099/// ::= .module nooddspreg
4100/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004101bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004102 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004103 MCAsmLexer &Lexer = getLexer();
4104 SMLoc L = Lexer.getLoc();
4105
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004106 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004107 // TODO : get a better message.
4108 reportParseError(".module directive must appear before any code");
4109 return false;
4110 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004111
Toma Tabacuc405c822015-01-23 10:40:19 +00004112 StringRef Option;
4113 if (Parser.parseIdentifier(Option)) {
4114 reportParseError("expected .module option identifier");
4115 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004116 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004117
Toma Tabacuc405c822015-01-23 10:40:19 +00004118 if (Option == "oddspreg") {
4119 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
4120 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4121
4122 // If this is not the end of the statement, report an error.
4123 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4124 reportParseError("unexpected token, expected end of statement");
4125 return false;
4126 }
4127
4128 return false; // parseDirectiveModule has finished successfully.
4129 } else if (Option == "nooddspreg") {
4130 if (!isABI_O32()) {
4131 Error(L, "'.module nooddspreg' requires the O32 ABI");
4132 return false;
4133 }
4134
4135 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
4136 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4137
4138 // If this is not the end of the statement, report an error.
4139 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4140 reportParseError("unexpected token, expected end of statement");
4141 return false;
4142 }
4143
4144 return false; // parseDirectiveModule has finished successfully.
4145 } else if (Option == "fp") {
4146 return parseDirectiveModuleFP();
4147 } else {
4148 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
4149 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004150}
4151
4152/// parseDirectiveModuleFP
4153/// ::= =32
4154/// ::= =xx
4155/// ::= =64
4156bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004157 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004158 MCAsmLexer &Lexer = getLexer();
4159
4160 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004161 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004162 return false;
4163 }
4164 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004165
Daniel Sanders7e527422014-07-10 13:38:23 +00004166 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004167 if (!parseFpABIValue(FpABI, ".module"))
4168 return false;
4169
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004170 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004171 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004172 return false;
4173 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004174
Daniel Sanders7201a3e2014-07-08 10:35:52 +00004175 // Emit appropriate flags.
4176 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00004177 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004178 return false;
4179}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004180
Daniel Sanders7e527422014-07-10 13:38:23 +00004181bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004182 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004183 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004184 MCAsmLexer &Lexer = getLexer();
4185
4186 if (Lexer.is(AsmToken::Identifier)) {
4187 StringRef Value = Parser.getTok().getString();
4188 Parser.Lex();
4189
4190 if (Value != "xx") {
4191 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4192 return false;
4193 }
4194
4195 if (!isABI_O32()) {
4196 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
4197 return false;
4198 }
4199
Daniel Sanders7e527422014-07-10 13:38:23 +00004200 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004201 return true;
4202 }
4203
4204 if (Lexer.is(AsmToken::Integer)) {
4205 unsigned Value = Parser.getTok().getIntVal();
4206 Parser.Lex();
4207
4208 if (Value != 32 && Value != 64) {
4209 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4210 return false;
4211 }
4212
4213 if (Value == 32) {
4214 if (!isABI_O32()) {
4215 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
4216 return false;
4217 }
4218
Daniel Sanders7e527422014-07-10 13:38:23 +00004219 FpABI = MipsABIFlagsSection::FpABIKind::S32;
4220 } else
4221 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004222
Daniel Sanders7e527422014-07-10 13:38:23 +00004223 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004224 }
4225
4226 return false;
4227}
4228
Jack Carter0b744b32012-10-04 02:29:46 +00004229bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004230 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004231 StringRef IDVal = DirectiveID.getString();
4232
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004233 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004234 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00004235 if (IDVal == ".dword") {
4236 parseDataDirective(8, DirectiveID.getLoc());
4237 return false;
4238 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004239 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004240 StringRef SymbolName;
4241
4242 if (Parser.parseIdentifier(SymbolName)) {
4243 reportParseError("expected identifier after .ent");
4244 return false;
4245 }
4246
4247 // There's an undocumented extension that allows an integer to
4248 // follow the name of the procedure which AFAICS is ignored by GAS.
4249 // Example: .ent foo,2
4250 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4251 if (getLexer().isNot(AsmToken::Comma)) {
4252 // Even though we accept this undocumented extension for compatibility
4253 // reasons, the additional integer argument does not actually change
4254 // the behaviour of the '.ent' directive, so we would like to discourage
4255 // its use. We do this by not referring to the extended version in
4256 // error messages which are not directly related to its use.
4257 reportParseError("unexpected token, expected end of statement");
4258 return false;
4259 }
4260 Parser.Lex(); // Eat the comma.
4261 const MCExpr *DummyNumber;
4262 int64_t DummyNumberVal;
4263 // If the user was explicitly trying to use the extended version,
4264 // we still give helpful extension-related error messages.
4265 if (Parser.parseExpression(DummyNumber)) {
4266 reportParseError("expected number after comma");
4267 return false;
4268 }
4269 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
4270 reportParseError("expected an absolute expression after comma");
4271 return false;
4272 }
4273 }
4274
4275 // If this is not the end of the statement, report an error.
4276 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4277 reportParseError("unexpected token, expected end of statement");
4278 return false;
4279 }
4280
4281 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
4282
4283 getTargetStreamer().emitDirectiveEnt(*Sym);
4284 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00004285 return false;
4286 }
4287
Jack Carter07c818d2013-01-25 01:31:34 +00004288 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004289 StringRef SymbolName;
4290
4291 if (Parser.parseIdentifier(SymbolName)) {
4292 reportParseError("expected identifier after .end");
4293 return false;
4294 }
4295
4296 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4297 reportParseError("unexpected token, expected end of statement");
4298 return false;
4299 }
4300
4301 if (CurrentFn == nullptr) {
4302 reportParseError(".end used without .ent");
4303 return false;
4304 }
4305
4306 if ((SymbolName != CurrentFn->getName())) {
4307 reportParseError(".end symbol does not match .ent symbol");
4308 return false;
4309 }
4310
4311 getTargetStreamer().emitDirectiveEnd(SymbolName);
4312 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00004313 return false;
4314 }
4315
Jack Carter07c818d2013-01-25 01:31:34 +00004316 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004317 // .frame $stack_reg, frame_size_in_bytes, $return_reg
4318 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004319 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004320 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4321 reportParseError("expected stack register");
4322 return false;
4323 }
4324
4325 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4326 if (!StackRegOpnd.isGPRAsmReg()) {
4327 reportParseError(StackRegOpnd.getStartLoc(),
4328 "expected general purpose register");
4329 return false;
4330 }
4331 unsigned StackReg = StackRegOpnd.getGPR32Reg();
4332
4333 if (Parser.getTok().is(AsmToken::Comma))
4334 Parser.Lex();
4335 else {
4336 reportParseError("unexpected token, expected comma");
4337 return false;
4338 }
4339
4340 // Parse the frame size.
4341 const MCExpr *FrameSize;
4342 int64_t FrameSizeVal;
4343
4344 if (Parser.parseExpression(FrameSize)) {
4345 reportParseError("expected frame size value");
4346 return false;
4347 }
4348
4349 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
4350 reportParseError("frame size not an absolute expression");
4351 return false;
4352 }
4353
4354 if (Parser.getTok().is(AsmToken::Comma))
4355 Parser.Lex();
4356 else {
4357 reportParseError("unexpected token, expected comma");
4358 return false;
4359 }
4360
4361 // Parse the return register.
4362 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00004363 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004364 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4365 reportParseError("expected return register");
4366 return false;
4367 }
4368
4369 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4370 if (!ReturnRegOpnd.isGPRAsmReg()) {
4371 reportParseError(ReturnRegOpnd.getStartLoc(),
4372 "expected general purpose register");
4373 return false;
4374 }
4375
4376 // If this is not the end of the statement, report an error.
4377 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4378 reportParseError("unexpected token, expected end of statement");
4379 return false;
4380 }
4381
4382 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
4383 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00004384 return false;
4385 }
4386
Jack Carter07c818d2013-01-25 01:31:34 +00004387 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00004388 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00004389 }
4390
Daniel Sandersd97a6342014-08-13 10:07:34 +00004391 if (IDVal == ".mask" || IDVal == ".fmask") {
4392 // .mask bitmask, frame_offset
4393 // bitmask: One bit for each register used.
4394 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
4395 // first register is expected to be saved.
4396 // Examples:
4397 // .mask 0x80000000, -4
4398 // .fmask 0x80000000, -4
4399 //
Jack Carterbe332172012-09-07 00:48:02 +00004400
Daniel Sandersd97a6342014-08-13 10:07:34 +00004401 // Parse the bitmask
4402 const MCExpr *BitMask;
4403 int64_t BitMaskVal;
4404
4405 if (Parser.parseExpression(BitMask)) {
4406 reportParseError("expected bitmask value");
4407 return false;
4408 }
4409
4410 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
4411 reportParseError("bitmask not an absolute expression");
4412 return false;
4413 }
4414
4415 if (Parser.getTok().is(AsmToken::Comma))
4416 Parser.Lex();
4417 else {
4418 reportParseError("unexpected token, expected comma");
4419 return false;
4420 }
4421
4422 // Parse the frame_offset
4423 const MCExpr *FrameOffset;
4424 int64_t FrameOffsetVal;
4425
4426 if (Parser.parseExpression(FrameOffset)) {
4427 reportParseError("expected frame offset value");
4428 return false;
4429 }
4430
4431 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
4432 reportParseError("frame offset not an absolute expression");
4433 return false;
4434 }
4435
4436 // If this is not the end of the statement, report an error.
4437 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4438 reportParseError("unexpected token, expected end of statement");
4439 return false;
4440 }
4441
4442 if (IDVal == ".mask")
4443 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
4444 else
4445 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00004446 return false;
4447 }
4448
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004449 if (IDVal == ".nan")
4450 return parseDirectiveNaN();
4451
Jack Carter07c818d2013-01-25 01:31:34 +00004452 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004453 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00004454 return false;
4455 }
4456
Rafael Espindolab59fb732014-03-28 18:50:26 +00004457 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004458 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004459 return false;
4460 }
4461
Jack Carter07c818d2013-01-25 01:31:34 +00004462 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004463 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00004464 return false;
4465 }
4466
Jack Carter0cd3c192014-01-06 23:27:31 +00004467 if (IDVal == ".option")
4468 return parseDirectiveOption();
4469
4470 if (IDVal == ".abicalls") {
4471 getTargetStreamer().emitDirectiveAbiCalls();
4472 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004473 Error(Parser.getTok().getLoc(),
4474 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004475 // Clear line
4476 Parser.eatToEndOfStatement();
4477 }
4478 return false;
4479 }
4480
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004481 if (IDVal == ".cpsetup")
4482 return parseDirectiveCPSetup();
4483
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004484 if (IDVal == ".module")
4485 return parseDirectiveModule();
4486
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004487 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
4488 return parseInternalDirectiveReallowModule();
4489
Toma Tabacu9ca50962015-04-16 09:53:47 +00004490 if (IDVal == ".insn")
4491 return parseInsnDirective();
4492
Rafael Espindola870c4e92012-01-11 03:56:41 +00004493 return true;
4494}
4495
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004496bool MipsAsmParser::parseInternalDirectiveReallowModule() {
4497 // If this is not the end of the statement, report an error.
4498 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4499 reportParseError("unexpected token, expected end of statement");
4500 return false;
4501 }
4502
4503 getTargetStreamer().reallowModuleDirective();
4504
4505 getParser().Lex(); // Eat EndOfStatement token.
4506 return false;
4507}
4508
Rafael Espindola870c4e92012-01-11 03:56:41 +00004509extern "C" void LLVMInitializeMipsAsmParser() {
4510 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
4511 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
4512 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
4513 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
4514}
Jack Carterb4dbc172012-09-05 23:34:03 +00004515
4516#define GET_REGISTER_MATCHER
4517#define GET_MATCHER_IMPLEMENTATION
4518#include "MipsGenAsmMatcher.inc"