blob: 5b8d633554b856b2758c391f432eab67e19a355b [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Eric Christophera5762812015-01-26 17:33:46 +000010#include "MCTargetDesc/MipsABIInfo.h"
Petar Jovanovica5da5882014-02-04 18:41:57 +000011#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000012#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000013#include "MipsRegisterInfo.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000014#include "MipsTargetStreamer.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000015#include "llvm/ADT/APInt.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000016#include "llvm/ADT/SmallVector.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000017#include "llvm/ADT/StringSwitch.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000018#include "llvm/MC/MCContext.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000021#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000022#include "llvm/MC/MCParser/MCAsmLexer.h"
23#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000024#include "llvm/MC/MCStreamer.h"
25#include "llvm/MC/MCSubtargetInfo.h"
26#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000027#include "llvm/MC/MCTargetAsmParser.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000028#include "llvm/Support/Debug.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000029#include "llvm/Support/MathExtras.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000030#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000031#include "llvm/Support/TargetRegistry.h"
Benjamin Kramer799003b2015-03-23 19:32:43 +000032#include "llvm/Support/raw_ostream.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000033#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000034
35using namespace llvm;
36
Chandler Carruthe96dd892014-04-21 22:55:11 +000037#define DEBUG_TYPE "mips-asm-parser"
38
Joey Gouly0e76fa72013-09-12 10:28:05 +000039namespace llvm {
40class MCInstrInfo;
41}
42
Rafael Espindola870c4e92012-01-11 03:56:41 +000043namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000044class MipsAssemblerOptions {
45public:
Toma Tabacu465acfd2015-06-09 13:33:26 +000046 MipsAssemblerOptions(const FeatureBitset &Features_) :
Toma Tabacu9db22db2014-09-09 10:15:38 +000047 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000048
Toma Tabacu9db22db2014-09-09 10:15:38 +000049 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000050 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000051 Reorder = Opts->isReorder();
52 Macro = Opts->isMacro();
53 Features = Opts->getFeatures();
54 }
55
Toma Tabacub19cf202015-04-27 13:12:59 +000056 unsigned getATRegIndex() const { return ATReg; }
57 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000058 if (Reg > 31)
59 return false;
60
61 ATReg = Reg;
62 return true;
63 }
Jack Carter0b744b32012-10-04 02:29:46 +000064
Toma Tabacu9db22db2014-09-09 10:15:38 +000065 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000066 void setReorder() { Reorder = true; }
67 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000068
Toma Tabacu9db22db2014-09-09 10:15:38 +000069 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000070 void setMacro() { Macro = true; }
71 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000072
Toma Tabacu465acfd2015-06-09 13:33:26 +000073 const FeatureBitset &getFeatures() const { return Features; }
74 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000075
Daniel Sandersf0df2212014-08-04 12:20:00 +000076 // Set of features that are either architecture features or referenced
77 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
78 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
79 // The reason we need this mask is explained in the selectArch function.
80 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +000081 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +000082
Jack Carter0b744b32012-10-04 02:29:46 +000083private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000084 unsigned ATReg;
85 bool Reorder;
86 bool Macro;
Toma Tabacu465acfd2015-06-09 13:33:26 +000087 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +000088};
89}
90
Michael Kupersteindb0712f2015-05-26 10:47:10 +000091const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
92 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
93 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
94 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
95 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
96 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
97 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
98 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
99 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
100};
101
Jack Carter0b744b32012-10-04 02:29:46 +0000102namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +0000103class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000104 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000105 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000106 return static_cast<MipsTargetStreamer &>(TS);
107 }
108
Jack Carterb4dbc172012-09-05 23:34:03 +0000109 MCSubtargetInfo &STI;
Eric Christophera5762812015-01-26 17:33:46 +0000110 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000111 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000112 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
113 // nullptr, which indicates that no function is currently
114 // selected. This usually happens after an '.end func'
115 // directive.
Jack Carter0b744b32012-10-04 02:29:46 +0000116
Daniel Sandersef638fe2014-10-03 15:37:37 +0000117 // Print a warning along with its fix-it message at the given range.
118 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
119 SMRange Range, bool ShowColors = true);
120
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000121#define GET_ASSEMBLER_HEADER
122#include "MipsGenAsmMatcher.inc"
123
Matheus Almeida595fcab2014-06-11 15:05:56 +0000124 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
125
Chad Rosier49963552012-10-13 00:26:04 +0000126 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000127 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000128 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000129 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000130
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000131 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000132 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000133
Toma Tabacu13964452014-09-04 13:23:44 +0000134 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000135
Toma Tabacu13964452014-09-04 13:23:44 +0000136 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000137
David Blaikie960ea3f2014-06-08 16:18:35 +0000138 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
139 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000140
Craig Topper56c590a2014-04-29 07:58:02 +0000141 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000142
David Blaikie960ea3f2014-06-08 16:18:35 +0000143 MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000144
145 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000146 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000147 StringRef Identifier, SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000148
Jack Carter873c7242013-01-12 01:03:14 +0000149 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000150 matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
Jack Carter873c7242013-01-12 01:03:14 +0000151
Toma Tabacu13964452014-09-04 13:23:44 +0000152 MipsAsmParser::OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000153
Toma Tabacu13964452014-09-04 13:23:44 +0000154 MipsAsmParser::OperandMatchResultTy parseImm(OperandVector &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000155
Toma Tabacu13964452014-09-04 13:23:44 +0000156 MipsAsmParser::OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000157
David Blaikie960ea3f2014-06-08 16:18:35 +0000158 MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000159
Toma Tabacu13964452014-09-04 13:23:44 +0000160 MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000161
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000162 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000163 parseRegisterPair (OperandVector &Operands);
164
165 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +0000166 parseMovePRegPair(OperandVector &Operands);
167
168 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000169 parseRegisterList (OperandVector &Operands);
170
David Blaikie960ea3f2014-06-08 16:18:35 +0000171 bool searchSymbolAlias(OperandVector &Operands);
172
Toma Tabacu13964452014-09-04 13:23:44 +0000173 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000174
Jack Carter30a59822012-10-04 04:03:53 +0000175 bool needsExpansion(MCInst &Inst);
176
Matheus Almeida3813d572014-06-19 14:39:14 +0000177 // Expands assembly pseudo instructions.
178 // Returns false on success, true otherwise.
179 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000180 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000181
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000182 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
183 SmallVectorImpl<MCInst> &Instructions);
184
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000185 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
186 bool Is32BitImm, SMLoc IDLoc,
187 SmallVectorImpl<MCInst> &Instructions);
188
Toma Tabacuf712ede2015-06-17 14:31:51 +0000189 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
190 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
191 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacu674825c2015-06-16 12:16:24 +0000192
Toma Tabacu00e98672015-05-01 12:19:27 +0000193 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000194 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000195
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000196 bool expandLoadAddressImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000197 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000198
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000199 bool expandLoadAddressReg(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000200 SmallVectorImpl<MCInst> &Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000201 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
202 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000203
Jack Carter9e65aa32013-03-22 00:05:30 +0000204 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000205 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
206 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000207
208 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
209 SmallVectorImpl<MCInst> &Instructions);
210
Toma Tabacue1e460d2015-06-11 10:36:10 +0000211 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc,
212 SmallVectorImpl<MCInst> &Instructions);
213
Toma Tabacu1a108322015-06-17 13:20:24 +0000214 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc,
215 SmallVectorImpl<MCInst> &Instructions);
216
Toma Tabacu234482a2015-03-16 12:03:39 +0000217 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
218 SmallVectorImpl<MCInst> &Instructions);
219
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000220 void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
221 SmallVectorImpl<MCInst> &Instructions);
222
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000223 bool reportParseError(Twine ErrorMsg);
224 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000225
Jack Carterb5cf5902013-04-17 00:18:04 +0000226 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000227 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000228
Vladimir Medic4c299852013-11-06 11:27:05 +0000229 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000230
231 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000232 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000233 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000234 bool parseSetFeature(uint64_t Feature);
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000235 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000236 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000237 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000238 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000239 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000240 bool parseInsnDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000241
242 bool parseSetAtDirective();
243 bool parseSetNoAtDirective();
244 bool parseSetMacroDirective();
245 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000246 bool parseSetMsaDirective();
247 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000248 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000249 bool parseSetReorderDirective();
250 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000251 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000252 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000253 bool parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000254 bool parseSetPopDirective();
255 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000256 bool parseSetSoftFloatDirective();
257 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000258
Jack Carterd76b2372013-03-21 21:44:16 +0000259 bool parseSetAssignment();
260
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000261 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000262 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000263 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000264 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000265 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000266 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
267 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000268
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000269 bool parseInternalDirectiveReallowModule();
270
Jack Carterdc1e35d2012-09-06 20:00:02 +0000271 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000272
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000273 bool eatComma(StringRef ErrorStr);
274
Jack Carter1ac53222013-02-20 23:11:17 +0000275 int matchCPURegisterName(StringRef Symbol);
276
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000277 int matchHWRegsRegisterName(StringRef Symbol);
278
Jack Carter873c7242013-01-12 01:03:14 +0000279 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000280
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000281 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000282
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000283 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000284
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000285 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000286
Jack Carter5dc8ac92013-09-25 23:50:44 +0000287 int matchMSA128RegisterName(StringRef Name);
288
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000289 int matchMSA128CtrlRegisterName(StringRef Name);
290
Jack Carterd0bd6422013-04-18 00:41:53 +0000291 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000292
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000293 unsigned getGPR(int RegNo);
294
Toma Tabacu89a712b2015-04-15 10:48:56 +0000295 /// Returns the internal register number for the current AT. Also checks if
296 /// the current AT is unavailable (set to $0) and gives an error if it is.
297 /// This should be used in pseudo-instruction expansions which need AT.
298 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000299
300 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000301 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000302
303 // Helper function that checks if the value of a vector index is within the
304 // boundaries of accepted values for each RegisterKind
305 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
306 bool validateMSAIndex(int Val, int RegKind);
307
Daniel Sandersf0df2212014-08-04 12:20:00 +0000308 // Selects a new architecture by updating the FeatureBits with the necessary
309 // info including implied dependencies.
310 // Internally, it clears all the feature bits related to *any* architecture
311 // and selects the new one using the ToggleFeature functionality of the
312 // MCSubtargetInfo object that handles implied dependencies. The reason we
313 // clear all the arch related bits manually is because ToggleFeature only
314 // clears the features that imply the feature being cleared and not the
315 // features implied by the feature being cleared. This is easier to see
316 // with an example:
317 // --------------------------------------------------
318 // | Feature | Implies |
319 // | -------------------------------------------------|
320 // | FeatureMips1 | None |
321 // | FeatureMips2 | FeatureMips1 |
322 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
323 // | FeatureMips4 | FeatureMips3 |
324 // | ... | |
325 // --------------------------------------------------
326 //
327 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
328 // FeatureMipsGP64 | FeatureMips1)
329 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
330 void selectArch(StringRef ArchFeature) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000331 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000332 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
333 STI.setFeatureBits(FeatureBits);
334 setAvailableFeatures(
335 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000336 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000337 }
338
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000339 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000340 if (!(STI.getFeatureBits()[Feature])) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000341 setAvailableFeatures(
342 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000343 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000344 }
345 }
346
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000347 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000348 if (STI.getFeatureBits()[Feature]) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000349 setAvailableFeatures(
350 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000351 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000352 }
353 }
354
Rafael Espindola870c4e92012-01-11 03:56:41 +0000355public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000356 enum MipsMatchResultTy {
357 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
358#define GET_OPERAND_DIAGNOSTIC_TYPES
359#include "MipsGenAsmMatcher.inc"
360#undef GET_OPERAND_DIAGNOSTIC_TYPES
361
362 };
363
Joey Gouly0e76fa72013-09-12 10:28:05 +0000364 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000365 const MCInstrInfo &MII, const MCTargetOptions &Options)
Eric Christophera5762812015-01-26 17:33:46 +0000366 : MCTargetAsmParser(), STI(sti),
367 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
368 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000369 MCAsmParserExtension::Initialize(parser);
370
Toma Tabacu11e14a92015-04-21 11:50:52 +0000371 parser.addAliasForDirective(".asciiz", ".asciz");
372
Jack Carterb4dbc172012-09-05 23:34:03 +0000373 // Initialize the set of available features.
374 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000375
376 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000377 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000378 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000379
380 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000381 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000382 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000383
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000384 getTargetStreamer().updateABIInfo(*this);
385
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000386 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000387 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000388
389 CurrentFn = nullptr;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000390 }
391
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000392 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
393 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
394
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000395 bool isGP64bit() const { return STI.getFeatureBits()[Mips::FeatureGP64Bit]; }
396 bool isFP64bit() const { return STI.getFeatureBits()[Mips::FeatureFP64Bit]; }
Eric Christophera5762812015-01-26 17:33:46 +0000397 const MipsABIInfo &getABI() const { return ABI; }
398 bool isABI_N32() const { return ABI.IsN32(); }
399 bool isABI_N64() const { return ABI.IsN64(); }
400 bool isABI_O32() const { return ABI.IsO32(); }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000401 bool isABI_FPXX() const { return STI.getFeatureBits()[Mips::FeatureFPXX]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000402
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000403 bool useOddSPReg() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000404 return !(STI.getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000405 }
406
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000407 bool inMicroMipsMode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000408 return STI.getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000409 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000410 bool hasMips1() const { return STI.getFeatureBits()[Mips::FeatureMips1]; }
411 bool hasMips2() const { return STI.getFeatureBits()[Mips::FeatureMips2]; }
412 bool hasMips3() const { return STI.getFeatureBits()[Mips::FeatureMips3]; }
413 bool hasMips4() const { return STI.getFeatureBits()[Mips::FeatureMips4]; }
414 bool hasMips5() const { return STI.getFeatureBits()[Mips::FeatureMips5]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000415 bool hasMips32() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000416 return STI.getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000417 }
418 bool hasMips64() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000419 return STI.getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000420 }
421 bool hasMips32r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000422 return STI.getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000423 }
424 bool hasMips64r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000425 return STI.getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000426 }
Daniel Sanders17793142015-02-18 16:24:50 +0000427 bool hasMips32r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000428 return (STI.getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000429 }
430 bool hasMips64r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000431 return (STI.getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000432 }
433 bool hasMips32r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000434 return (STI.getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000435 }
436 bool hasMips64r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000437 return (STI.getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000438 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000439 bool hasMips32r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000440 return STI.getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000441 }
442 bool hasMips64r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000443 return STI.getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000444 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000445
446 bool hasDSP() const { return STI.getFeatureBits()[Mips::FeatureDSP]; }
447 bool hasDSPR2() const { return STI.getFeatureBits()[Mips::FeatureDSPR2]; }
448 bool hasMSA() const { return STI.getFeatureBits()[Mips::FeatureMSA]; }
Kai Nackee0245392015-01-27 19:11:28 +0000449 bool hasCnMips() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000450 return (STI.getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000451 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000452
453 bool inMips16Mode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000454 return STI.getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000455 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000456
Eric Christophere8ae3e32015-05-07 23:10:21 +0000457 bool useSoftFloat() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000458 return STI.getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000459 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000460
Toma Tabacud9d344b2015-04-27 14:05:04 +0000461 /// Warn if RegIndex is the same as the current AT.
462 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000463
464 void warnIfNoMacro(SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000465};
466}
467
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000468namespace {
469
470/// MipsOperand - Instances of this class represent a parsed Mips machine
471/// instruction.
472class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000473public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000474 /// Broad categories of register classes
475 /// The exact class is finalized by the render method.
476 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000477 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000478 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000479 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000480 RegKind_FCC = 4, /// FCC
481 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
482 RegKind_MSACtrl = 16, /// MSA control registers
483 RegKind_COP2 = 32, /// COP2
484 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
485 /// context).
486 RegKind_CCR = 128, /// CCR
487 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000488 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000489
490 /// Potentially any (e.g. $1)
491 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
492 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000493 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000494 };
495
496private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000497 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000498 k_Immediate, /// An immediate (possibly involving symbol references)
499 k_Memory, /// Base + Offset Memory Address
500 k_PhysRegister, /// A physical register from the Mips namespace
501 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000502 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000503 k_RegList, /// A physical register list
504 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000505 } Kind;
506
David Blaikie960ea3f2014-06-08 16:18:35 +0000507public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000508 MipsOperand(KindTy K, MipsAsmParser &Parser)
509 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
510
David Blaikie960ea3f2014-06-08 16:18:35 +0000511private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000512 /// For diagnostics, and checking the assembler temporary
513 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000514
Eric Christopher8996c5d2013-03-15 00:42:55 +0000515 struct Token {
516 const char *Data;
517 unsigned Length;
518 };
519
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000520 struct PhysRegOp {
521 unsigned Num; /// Register Number
522 };
523
524 struct RegIdxOp {
525 unsigned Index; /// Index into the register class
526 RegKind Kind; /// Bitfield of the kinds it could possibly be
527 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000528 };
529
530 struct ImmOp {
531 const MCExpr *Val;
532 };
533
534 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000535 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000536 const MCExpr *Off;
537 };
538
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000539 struct RegListOp {
540 SmallVector<unsigned, 10> *List;
541 };
542
Jack Carterb4dbc172012-09-05 23:34:03 +0000543 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000544 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000545 struct PhysRegOp PhysReg;
546 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000547 struct ImmOp Imm;
548 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000549 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000550 };
551
552 SMLoc StartLoc, EndLoc;
553
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000554 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000555 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
556 const MCRegisterInfo *RegInfo,
557 SMLoc S, SMLoc E,
558 MipsAsmParser &Parser) {
559 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000560 Op->RegIdx.Index = Index;
561 Op->RegIdx.RegInfo = RegInfo;
562 Op->RegIdx.Kind = RegKind;
563 Op->StartLoc = S;
564 Op->EndLoc = E;
565 return Op;
566 }
567
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000568public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000569 /// Coerce the register to GPR32 and return the real register for the current
570 /// target.
571 unsigned getGPR32Reg() const {
572 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000573 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000574 unsigned ClassID = Mips::GPR32RegClassID;
575 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000576 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000577
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000578 /// Coerce the register to GPR32 and return the real register for the current
579 /// target.
580 unsigned getGPRMM16Reg() const {
581 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
582 unsigned ClassID = Mips::GPR32RegClassID;
583 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
584 }
585
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000586 /// Coerce the register to GPR64 and return the real register for the current
587 /// target.
588 unsigned getGPR64Reg() const {
589 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
590 unsigned ClassID = Mips::GPR64RegClassID;
591 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000592 }
593
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000594private:
595 /// Coerce the register to AFGR64 and return the real register for the current
596 /// target.
597 unsigned getAFGR64Reg() const {
598 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
599 if (RegIdx.Index % 2 != 0)
600 AsmParser.Warning(StartLoc, "Float register should be even.");
601 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
602 .getRegister(RegIdx.Index / 2);
603 }
604
605 /// Coerce the register to FGR64 and return the real register for the current
606 /// target.
607 unsigned getFGR64Reg() const {
608 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
609 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
610 .getRegister(RegIdx.Index);
611 }
612
613 /// Coerce the register to FGR32 and return the real register for the current
614 /// target.
615 unsigned getFGR32Reg() const {
616 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
617 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
618 .getRegister(RegIdx.Index);
619 }
620
621 /// Coerce the register to FGRH32 and return the real register for the current
622 /// target.
623 unsigned getFGRH32Reg() const {
624 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
625 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
626 .getRegister(RegIdx.Index);
627 }
628
629 /// Coerce the register to FCC and return the real register for the current
630 /// target.
631 unsigned getFCCReg() const {
632 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
633 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
634 .getRegister(RegIdx.Index);
635 }
636
637 /// Coerce the register to MSA128 and return the real register for the current
638 /// target.
639 unsigned getMSA128Reg() const {
640 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
641 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
642 // identical
643 unsigned ClassID = Mips::MSA128BRegClassID;
644 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
645 }
646
647 /// Coerce the register to MSACtrl and return the real register for the
648 /// current target.
649 unsigned getMSACtrlReg() const {
650 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
651 unsigned ClassID = Mips::MSACtrlRegClassID;
652 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
653 }
654
655 /// Coerce the register to COP2 and return the real register for the
656 /// current target.
657 unsigned getCOP2Reg() const {
658 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
659 unsigned ClassID = Mips::COP2RegClassID;
660 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
661 }
662
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000663 /// Coerce the register to COP3 and return the real register for the
664 /// current target.
665 unsigned getCOP3Reg() const {
666 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
667 unsigned ClassID = Mips::COP3RegClassID;
668 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
669 }
670
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000671 /// Coerce the register to ACC64DSP and return the real register for the
672 /// current target.
673 unsigned getACC64DSPReg() const {
674 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
675 unsigned ClassID = Mips::ACC64DSPRegClassID;
676 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
677 }
678
679 /// Coerce the register to HI32DSP and return the real register for the
680 /// current target.
681 unsigned getHI32DSPReg() const {
682 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
683 unsigned ClassID = Mips::HI32DSPRegClassID;
684 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
685 }
686
687 /// Coerce the register to LO32DSP and return the real register for the
688 /// current target.
689 unsigned getLO32DSPReg() const {
690 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
691 unsigned ClassID = Mips::LO32DSPRegClassID;
692 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
693 }
694
695 /// Coerce the register to CCR and return the real register for the
696 /// current target.
697 unsigned getCCRReg() const {
698 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
699 unsigned ClassID = Mips::CCRRegClassID;
700 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
701 }
702
703 /// Coerce the register to HWRegs and return the real register for the
704 /// current target.
705 unsigned getHWRegsReg() const {
706 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
707 unsigned ClassID = Mips::HWRegsRegClassID;
708 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
709 }
710
711public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000712 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000713 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000714 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000715 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000716 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000717 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000718 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000719 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000720 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000721
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000722 void addRegOperands(MCInst &Inst, unsigned N) const {
723 llvm_unreachable("Use a custom parser instead");
724 }
725
Daniel Sanders21bce302014-04-01 12:35:23 +0000726 /// Render the operand to an MCInst as a GPR32
727 /// Asserts if the wrong number of operands are requested, or the operand
728 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000729 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
730 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000731 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000732 }
733
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000734 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
735 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000736 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000737 }
738
Jozef Kolek1904fa22014-11-24 14:25:53 +0000739 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
740 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000741 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000742 }
743
Zoran Jovanovic41688672015-02-10 16:36:20 +0000744 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
745 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000746 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000747 }
748
Daniel Sanders21bce302014-04-01 12:35:23 +0000749 /// Render the operand to an MCInst as a GPR64
750 /// Asserts if the wrong number of operands are requested, or the operand
751 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000752 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
753 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000754 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000755 }
756
757 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
758 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000759 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000760 }
761
762 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
763 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000764 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000765 }
766
767 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
768 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000769 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000770 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000771 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000772 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
773 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000774 }
775
776 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
777 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000778 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000779 }
780
781 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
782 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000783 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000784 }
785
786 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
787 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000788 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000789 }
790
791 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
792 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000793 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000794 }
795
796 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
797 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000798 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000799 }
800
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000801 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
802 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000803 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000804 }
805
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000806 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
807 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000808 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000809 }
810
811 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
812 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000813 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000814 }
815
816 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
817 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000818 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000819 }
820
821 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
822 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000823 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000824 }
825
826 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
827 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000828 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000829 }
830
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000831 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000832 assert(N == 1 && "Invalid number of operands!");
833 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000834 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000835 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000836
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000837 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000838 assert(N == 2 && "Invalid number of operands!");
839
Jim Grosbache9119e42015-05-13 18:37:00 +0000840 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000841
842 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000843 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000844 }
845
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000846 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
847 assert(N == 2 && "Invalid number of operands!");
848
Jim Grosbache9119e42015-05-13 18:37:00 +0000849 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000850
851 const MCExpr *Expr = getMemOff();
852 addExpr(Inst, Expr);
853 }
854
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000855 void addRegListOperands(MCInst &Inst, unsigned N) const {
856 assert(N == 1 && "Invalid number of operands!");
857
858 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000859 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000860 }
861
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000862 void addRegPairOperands(MCInst &Inst, unsigned N) const {
863 assert(N == 2 && "Invalid number of operands!");
864 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +0000865 Inst.addOperand(MCOperand::createReg(RegNo++));
866 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000867 }
868
Zoran Jovanovic41688672015-02-10 16:36:20 +0000869 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
870 assert(N == 2 && "Invalid number of operands!");
871 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000872 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000873 }
874
Craig Topper56c590a2014-04-29 07:58:02 +0000875 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000876 // As a special case until we sort out the definition of div/divu, pretend
877 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
878 if (isGPRAsmReg() && RegIdx.Index == 0)
879 return true;
880
881 return Kind == k_PhysRegister;
882 }
883 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000884 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000885 bool isConstantImm() const {
886 return isImm() && dyn_cast<MCConstantExpr>(getImm());
887 }
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +0000888 template <unsigned Bits> bool isUImm() const {
889 return isImm() && isConstantImm() && isUInt<Bits>(getConstantImm());
890 }
Craig Topper56c590a2014-04-29 07:58:02 +0000891 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000892 // Note: It's not possible to pretend that other operand kinds are tokens.
893 // The matcher emitter checks tokens first.
894 return Kind == k_Token;
895 }
Craig Topper56c590a2014-04-29 07:58:02 +0000896 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000897 bool isConstantMemOff() const {
898 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
899 }
900 template <unsigned Bits> bool isMemWithSimmOffset() const {
901 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
902 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000903 bool isMemWithGRPMM16Base() const {
904 return isMem() && getMemBase()->isMM16AsmReg();
905 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000906 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
907 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
908 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
909 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000910 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
911 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
912 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
913 && (getMemBase()->getGPR32Reg() == Mips::SP);
914 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000915 bool isRegList16() const {
916 if (!isRegList())
917 return false;
918
919 int Size = RegList.List->size();
920 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
921 RegList.List->back() != Mips::RA)
922 return false;
923
924 int PrevReg = *RegList.List->begin();
925 for (int i = 1; i < Size - 1; i++) {
926 int Reg = (*(RegList.List))[i];
927 if ( Reg != PrevReg + 1)
928 return false;
929 PrevReg = Reg;
930 }
931
932 return true;
933 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000934 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000935 bool isLSAImm() const {
936 if (!isConstantImm())
937 return false;
938 int64_t Val = getConstantImm();
939 return 1 <= Val && Val <= 4;
940 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000941 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +0000942 bool isMovePRegPair() const {
943 if (Kind != k_RegList || RegList.List->size() != 2)
944 return false;
945
946 unsigned R0 = RegList.List->front();
947 unsigned R1 = RegList.List->back();
948
949 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
950 (R0 == Mips::A1 && R1 == Mips::A3) ||
951 (R0 == Mips::A2 && R1 == Mips::A3) ||
952 (R0 == Mips::A0 && R1 == Mips::S5) ||
953 (R0 == Mips::A0 && R1 == Mips::S6) ||
954 (R0 == Mips::A0 && R1 == Mips::A1) ||
955 (R0 == Mips::A0 && R1 == Mips::A2) ||
956 (R0 == Mips::A0 && R1 == Mips::A3))
957 return true;
958
959 return false;
960 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000961
962 StringRef getToken() const {
963 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000964 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000965 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000966 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000967
Craig Topper56c590a2014-04-29 07:58:02 +0000968 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000969 // As a special case until we sort out the definition of div/divu, pretend
970 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
971 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
972 RegIdx.Kind & RegKind_GPR)
973 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000974
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000975 assert(Kind == k_PhysRegister && "Invalid access!");
976 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000977 }
978
Jack Carterb4dbc172012-09-05 23:34:03 +0000979 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000980 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000981 return Imm.Val;
982 }
983
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000984 int64_t getConstantImm() const {
985 const MCExpr *Val = getImm();
986 return static_cast<const MCConstantExpr *>(Val)->getValue();
987 }
988
989 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000990 assert((Kind == k_Memory) && "Invalid access!");
991 return Mem.Base;
992 }
993
994 const MCExpr *getMemOff() const {
995 assert((Kind == k_Memory) && "Invalid access!");
996 return Mem.Off;
997 }
998
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000999 int64_t getConstantMemOff() const {
1000 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1001 }
1002
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001003 const SmallVectorImpl<unsigned> &getRegList() const {
1004 assert((Kind == k_RegList) && "Invalid access!");
1005 return *(RegList.List);
1006 }
1007
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001008 unsigned getRegPair() const {
1009 assert((Kind == k_RegPair) && "Invalid access!");
1010 return RegIdx.Index;
1011 }
1012
David Blaikie960ea3f2014-06-08 16:18:35 +00001013 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1014 MipsAsmParser &Parser) {
1015 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001016 Op->Tok.Data = Str.data();
1017 Op->Tok.Length = Str.size();
1018 Op->StartLoc = S;
1019 Op->EndLoc = S;
1020 return Op;
1021 }
1022
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001023 /// Create a numeric register (e.g. $1). The exact register remains
1024 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001025 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001026 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001027 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001028 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001029 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001030 }
1031
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001032 /// Create a register that is definitely a GPR.
1033 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001034 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001035 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001036 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001037 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001038 }
1039
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001040 /// Create a register that is definitely a FGR.
1041 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001042 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001043 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001044 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001045 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1046 }
1047
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001048 /// Create a register that is definitely a HWReg.
1049 /// This is typically only used for named registers such as $hwr_cpunum.
1050 static std::unique_ptr<MipsOperand>
1051 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1052 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1053 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1054 }
1055
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001056 /// Create a register that is definitely an FCC.
1057 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001058 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001059 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001060 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001061 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1062 }
1063
1064 /// Create a register that is definitely an ACC.
1065 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001066 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001067 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001068 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001069 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1070 }
1071
1072 /// Create a register that is definitely an MSA128.
1073 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001074 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001075 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001076 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001077 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1078 }
1079
1080 /// Create a register that is definitely an MSACtrl.
1081 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001082 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001083 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001084 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001085 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1086 }
1087
David Blaikie960ea3f2014-06-08 16:18:35 +00001088 static std::unique_ptr<MipsOperand>
1089 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1090 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001091 Op->Imm.Val = Val;
1092 Op->StartLoc = S;
1093 Op->EndLoc = E;
1094 return Op;
1095 }
1096
David Blaikie960ea3f2014-06-08 16:18:35 +00001097 static std::unique_ptr<MipsOperand>
1098 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1099 SMLoc E, MipsAsmParser &Parser) {
1100 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1101 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001102 Op->Mem.Off = Off;
1103 Op->StartLoc = S;
1104 Op->EndLoc = E;
1105 return Op;
1106 }
1107
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001108 static std::unique_ptr<MipsOperand>
1109 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1110 MipsAsmParser &Parser) {
1111 assert (Regs.size() > 0 && "Empty list not allowed");
1112
1113 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001114 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001115 Op->StartLoc = StartLoc;
1116 Op->EndLoc = EndLoc;
1117 return Op;
1118 }
1119
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001120 static std::unique_ptr<MipsOperand>
1121 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1122 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1123 Op->RegIdx.Index = RegNo;
1124 Op->StartLoc = S;
1125 Op->EndLoc = E;
1126 return Op;
1127 }
1128
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001129 bool isGPRAsmReg() const {
1130 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001131 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001132 bool isMM16AsmReg() const {
1133 if (!(isRegIdx() && RegIdx.Kind))
1134 return false;
1135 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1136 || RegIdx.Index == 16 || RegIdx.Index == 17);
1137 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001138 bool isMM16AsmRegZero() const {
1139 if (!(isRegIdx() && RegIdx.Kind))
1140 return false;
1141 return (RegIdx.Index == 0 ||
1142 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1143 RegIdx.Index == 17);
1144 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001145 bool isMM16AsmRegMoveP() const {
1146 if (!(isRegIdx() && RegIdx.Kind))
1147 return false;
1148 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1149 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1150 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001151 bool isFGRAsmReg() const {
1152 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1153 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001154 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001155 bool isHWRegsAsmReg() const {
1156 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001157 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001158 bool isCCRAsmReg() const {
1159 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001160 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001161 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001162 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1163 return false;
1164 if (!AsmParser.hasEightFccRegisters())
1165 return RegIdx.Index == 0;
1166 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001167 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001168 bool isACCAsmReg() const {
1169 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001170 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001171 bool isCOP2AsmReg() const {
1172 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001173 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001174 bool isCOP3AsmReg() const {
1175 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1176 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001177 bool isMSA128AsmReg() const {
1178 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001179 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001180 bool isMSACtrlAsmReg() const {
1181 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001182 }
1183
Jack Carterb4dbc172012-09-05 23:34:03 +00001184 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001185 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001186 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001187 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001188
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001189 virtual ~MipsOperand() {
1190 switch (Kind) {
1191 case k_Immediate:
1192 break;
1193 case k_Memory:
1194 delete Mem.Base;
1195 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001196 case k_RegList:
1197 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001198 case k_PhysRegister:
1199 case k_RegisterIndex:
1200 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001201 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001202 break;
1203 }
1204 }
1205
Craig Topper56c590a2014-04-29 07:58:02 +00001206 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001207 switch (Kind) {
1208 case k_Immediate:
1209 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001210 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001211 OS << ">";
1212 break;
1213 case k_Memory:
1214 OS << "Mem<";
1215 Mem.Base->print(OS);
1216 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001217 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001218 OS << ">";
1219 break;
1220 case k_PhysRegister:
1221 OS << "PhysReg<" << PhysReg.Num << ">";
1222 break;
1223 case k_RegisterIndex:
1224 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1225 break;
1226 case k_Token:
1227 OS << Tok.Data;
1228 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001229 case k_RegList:
1230 OS << "RegList< ";
1231 for (auto Reg : (*RegList.List))
1232 OS << Reg << " ";
1233 OS << ">";
1234 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001235 case k_RegPair:
1236 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1237 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001238 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001239 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001240}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001241} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001242
Jack Carter9e65aa32013-03-22 00:05:30 +00001243namespace llvm {
1244extern const MCInstrDesc MipsInsts[];
1245}
1246static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1247 return MipsInsts[Opcode];
1248}
1249
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001250static bool hasShortDelaySlot(unsigned Opcode) {
1251 switch (Opcode) {
1252 case Mips::JALS_MM:
1253 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001254 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001255 case Mips::BGEZALS_MM:
1256 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001257 return true;
1258 default:
1259 return false;
1260 }
1261}
1262
Jack Carter9e65aa32013-03-22 00:05:30 +00001263bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001264 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001265 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001266
Jack Carter9e65aa32013-03-22 00:05:30 +00001267 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001268
1269 if (MCID.isBranch() || MCID.isCall()) {
1270 const unsigned Opcode = Inst.getOpcode();
1271 MCOperand Offset;
1272
1273 switch (Opcode) {
1274 default:
1275 break;
Kai Nackee0245392015-01-27 19:11:28 +00001276 case Mips::BBIT0:
1277 case Mips::BBIT032:
1278 case Mips::BBIT1:
1279 case Mips::BBIT132:
1280 assert(hasCnMips() && "instruction only valid for octeon cpus");
1281 // Fall through
1282
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001283 case Mips::BEQ:
1284 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001285 case Mips::BEQ_MM:
1286 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001287 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001288 Offset = Inst.getOperand(2);
1289 if (!Offset.isImm())
1290 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001291 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001292 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001293 if (OffsetToAlignment(Offset.getImm(),
1294 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001295 return Error(IDLoc, "branch to misaligned address");
1296 break;
1297 case Mips::BGEZ:
1298 case Mips::BGTZ:
1299 case Mips::BLEZ:
1300 case Mips::BLTZ:
1301 case Mips::BGEZAL:
1302 case Mips::BLTZAL:
1303 case Mips::BC1F:
1304 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001305 case Mips::BGEZ_MM:
1306 case Mips::BGTZ_MM:
1307 case Mips::BLEZ_MM:
1308 case Mips::BLTZ_MM:
1309 case Mips::BGEZAL_MM:
1310 case Mips::BLTZAL_MM:
1311 case Mips::BC1F_MM:
1312 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001313 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001314 Offset = Inst.getOperand(1);
1315 if (!Offset.isImm())
1316 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001317 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001318 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001319 if (OffsetToAlignment(Offset.getImm(),
1320 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001321 return Error(IDLoc, "branch to misaligned address");
1322 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001323 case Mips::BEQZ16_MM:
1324 case Mips::BNEZ16_MM:
1325 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1326 Offset = Inst.getOperand(1);
1327 if (!Offset.isImm())
1328 break; // We'll deal with this situation later on when applying fixups.
1329 if (!isIntN(8, Offset.getImm()))
1330 return Error(IDLoc, "branch target out of range");
1331 if (OffsetToAlignment(Offset.getImm(), 2LL))
1332 return Error(IDLoc, "branch to misaligned address");
1333 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001334 }
1335 }
1336
Daniel Sandersa84989a2014-06-16 13:25:35 +00001337 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1338 // We still accept it but it is a normal nop.
1339 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1340 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1341 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1342 "nop instruction");
1343 }
1344
Kai Nackee0245392015-01-27 19:11:28 +00001345 if (hasCnMips()) {
1346 const unsigned Opcode = Inst.getOpcode();
1347 MCOperand Opnd;
1348 int Imm;
1349
1350 switch (Opcode) {
1351 default:
1352 break;
1353
1354 case Mips::BBIT0:
1355 case Mips::BBIT032:
1356 case Mips::BBIT1:
1357 case Mips::BBIT132:
1358 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1359 // The offset is handled above
1360 Opnd = Inst.getOperand(1);
1361 if (!Opnd.isImm())
1362 return Error(IDLoc, "expected immediate operand kind");
1363 Imm = Opnd.getImm();
1364 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1365 Opcode == Mips::BBIT1 ? 63 : 31))
1366 return Error(IDLoc, "immediate operand value out of range");
1367 if (Imm > 31) {
1368 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1369 : Mips::BBIT132);
1370 Inst.getOperand(1).setImm(Imm - 32);
1371 }
1372 break;
1373
1374 case Mips::CINS:
1375 case Mips::CINS32:
1376 case Mips::EXTS:
1377 case Mips::EXTS32:
1378 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1379 // Check length
1380 Opnd = Inst.getOperand(3);
1381 if (!Opnd.isImm())
1382 return Error(IDLoc, "expected immediate operand kind");
1383 Imm = Opnd.getImm();
1384 if (Imm < 0 || Imm > 31)
1385 return Error(IDLoc, "immediate operand value out of range");
1386 // Check position
1387 Opnd = Inst.getOperand(2);
1388 if (!Opnd.isImm())
1389 return Error(IDLoc, "expected immediate operand kind");
1390 Imm = Opnd.getImm();
1391 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1392 Opcode == Mips::EXTS ? 63 : 31))
1393 return Error(IDLoc, "immediate operand value out of range");
1394 if (Imm > 31) {
1395 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1396 Inst.getOperand(2).setImm(Imm - 32);
1397 }
1398 break;
1399
1400 case Mips::SEQi:
1401 case Mips::SNEi:
1402 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1403 Opnd = Inst.getOperand(2);
1404 if (!Opnd.isImm())
1405 return Error(IDLoc, "expected immediate operand kind");
1406 Imm = Opnd.getImm();
1407 if (!isInt<10>(Imm))
1408 return Error(IDLoc, "immediate operand value out of range");
1409 break;
1410 }
1411 }
1412
Jack Carter9e65aa32013-03-22 00:05:30 +00001413 if (MCID.mayLoad() || MCID.mayStore()) {
1414 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001415 // reference or immediate we may have to expand instructions.
1416 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001417 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001418 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1419 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001420 MCOperand &Op = Inst.getOperand(i);
1421 if (Op.isImm()) {
1422 int MemOffset = Op.getImm();
1423 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001424 // Offset can't exceed 16bit value.
1425 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001426 return false;
1427 }
1428 } else if (Op.isExpr()) {
1429 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001430 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001431 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001432 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001433 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001434 // Expand symbol.
1435 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001436 return false;
1437 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001438 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001439 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001440 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001441 }
1442 }
1443 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001444 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001445 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001446
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001447 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001448 if (MCID.mayLoad()) {
1449 // Try to create 16-bit GP relative load instruction.
1450 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1451 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1452 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1453 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1454 MCOperand &Op = Inst.getOperand(i);
1455 if (Op.isImm()) {
1456 int MemOffset = Op.getImm();
1457 MCOperand &DstReg = Inst.getOperand(0);
1458 MCOperand &BaseReg = Inst.getOperand(1);
1459 if (isIntN(9, MemOffset) && (MemOffset % 4 == 0) &&
1460 getContext().getRegisterInfo()->getRegClass(
1461 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
1462 BaseReg.getReg() == Mips::GP) {
1463 MCInst TmpInst;
1464 TmpInst.setLoc(IDLoc);
1465 TmpInst.setOpcode(Mips::LWGP_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00001466 TmpInst.addOperand(MCOperand::createReg(DstReg.getReg()));
1467 TmpInst.addOperand(MCOperand::createReg(Mips::GP));
1468 TmpInst.addOperand(MCOperand::createImm(MemOffset));
Jozef Koleke10a02e2015-01-28 17:27:26 +00001469 Instructions.push_back(TmpInst);
1470 return false;
1471 }
1472 }
1473 }
1474 } // for
1475 } // if load
1476
1477 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1478
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001479 MCOperand Opnd;
1480 int Imm;
1481
1482 switch (Inst.getOpcode()) {
1483 default:
1484 break;
1485 case Mips::ADDIUS5_MM:
1486 Opnd = Inst.getOperand(2);
1487 if (!Opnd.isImm())
1488 return Error(IDLoc, "expected immediate operand kind");
1489 Imm = Opnd.getImm();
1490 if (Imm < -8 || Imm > 7)
1491 return Error(IDLoc, "immediate operand value out of range");
1492 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001493 case Mips::ADDIUSP_MM:
1494 Opnd = Inst.getOperand(0);
1495 if (!Opnd.isImm())
1496 return Error(IDLoc, "expected immediate operand kind");
1497 Imm = Opnd.getImm();
1498 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1499 Imm % 4 != 0)
1500 return Error(IDLoc, "immediate operand value out of range");
1501 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001502 case Mips::SLL16_MM:
1503 case Mips::SRL16_MM:
1504 Opnd = Inst.getOperand(2);
1505 if (!Opnd.isImm())
1506 return Error(IDLoc, "expected immediate operand kind");
1507 Imm = Opnd.getImm();
1508 if (Imm < 1 || Imm > 8)
1509 return Error(IDLoc, "immediate operand value out of range");
1510 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001511 case Mips::LI16_MM:
1512 Opnd = Inst.getOperand(1);
1513 if (!Opnd.isImm())
1514 return Error(IDLoc, "expected immediate operand kind");
1515 Imm = Opnd.getImm();
1516 if (Imm < -1 || Imm > 126)
1517 return Error(IDLoc, "immediate operand value out of range");
1518 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001519 case Mips::ADDIUR2_MM:
1520 Opnd = Inst.getOperand(2);
1521 if (!Opnd.isImm())
1522 return Error(IDLoc, "expected immediate operand kind");
1523 Imm = Opnd.getImm();
1524 if (!(Imm == 1 || Imm == -1 ||
1525 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1526 return Error(IDLoc, "immediate operand value out of range");
1527 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001528 case Mips::ADDIUR1SP_MM:
1529 Opnd = Inst.getOperand(1);
1530 if (!Opnd.isImm())
1531 return Error(IDLoc, "expected immediate operand kind");
1532 Imm = Opnd.getImm();
1533 if (OffsetToAlignment(Imm, 4LL))
1534 return Error(IDLoc, "misaligned immediate operand value");
1535 if (Imm < 0 || Imm > 255)
1536 return Error(IDLoc, "immediate operand value out of range");
1537 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001538 case Mips::ANDI16_MM:
1539 Opnd = Inst.getOperand(2);
1540 if (!Opnd.isImm())
1541 return Error(IDLoc, "expected immediate operand kind");
1542 Imm = Opnd.getImm();
1543 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1544 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1545 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1546 return Error(IDLoc, "immediate operand value out of range");
1547 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001548 case Mips::LBU16_MM:
1549 Opnd = Inst.getOperand(2);
1550 if (!Opnd.isImm())
1551 return Error(IDLoc, "expected immediate operand kind");
1552 Imm = Opnd.getImm();
1553 if (Imm < -1 || Imm > 14)
1554 return Error(IDLoc, "immediate operand value out of range");
1555 break;
1556 case Mips::SB16_MM:
1557 Opnd = Inst.getOperand(2);
1558 if (!Opnd.isImm())
1559 return Error(IDLoc, "expected immediate operand kind");
1560 Imm = Opnd.getImm();
1561 if (Imm < 0 || Imm > 15)
1562 return Error(IDLoc, "immediate operand value out of range");
1563 break;
1564 case Mips::LHU16_MM:
1565 case Mips::SH16_MM:
1566 Opnd = Inst.getOperand(2);
1567 if (!Opnd.isImm())
1568 return Error(IDLoc, "expected immediate operand kind");
1569 Imm = Opnd.getImm();
1570 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1571 return Error(IDLoc, "immediate operand value out of range");
1572 break;
1573 case Mips::LW16_MM:
1574 case Mips::SW16_MM:
1575 Opnd = Inst.getOperand(2);
1576 if (!Opnd.isImm())
1577 return Error(IDLoc, "expected immediate operand kind");
1578 Imm = Opnd.getImm();
1579 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1580 return Error(IDLoc, "immediate operand value out of range");
1581 break;
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001582 case Mips::CACHE:
1583 case Mips::PREF:
1584 Opnd = Inst.getOperand(2);
1585 if (!Opnd.isImm())
1586 return Error(IDLoc, "expected immediate operand kind");
1587 Imm = Opnd.getImm();
1588 if (!isUInt<5>(Imm))
1589 return Error(IDLoc, "immediate operand value out of range");
1590 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001591 case Mips::ADDIUPC_MM:
1592 MCOperand Opnd = Inst.getOperand(1);
1593 if (!Opnd.isImm())
1594 return Error(IDLoc, "expected immediate operand kind");
1595 int Imm = Opnd.getImm();
1596 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1597 return Error(IDLoc, "immediate operand value out of range");
1598 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001599 }
1600 }
1601
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001602 if (needsExpansion(Inst)) {
1603 if (expandInstruction(Inst, IDLoc, Instructions))
1604 return true;
1605 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001606 Instructions.push_back(Inst);
1607
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001608 // If this instruction has a delay slot and .set reorder is active,
1609 // emit a NOP after it.
1610 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1611 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1612
Jack Carter9e65aa32013-03-22 00:05:30 +00001613 return false;
1614}
1615
Jack Carter30a59822012-10-04 04:03:53 +00001616bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1617
Jack Carterd0bd6422013-04-18 00:41:53 +00001618 switch (Inst.getOpcode()) {
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001619 case Mips::LoadImm32:
1620 case Mips::LoadImm64:
1621 case Mips::LoadAddrImm32:
1622 case Mips::LoadAddrReg32:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001623 case Mips::B_MM_Pseudo:
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001624 case Mips::LWM_MM:
1625 case Mips::SWM_MM:
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001626 case Mips::JalOneReg:
1627 case Mips::JalTwoReg:
Toma Tabacue1e460d2015-06-11 10:36:10 +00001628 case Mips::BneImm:
1629 case Mips::BeqImm:
Toma Tabacu1a108322015-06-17 13:20:24 +00001630 case Mips::BLT:
1631 case Mips::BLE:
1632 case Mips::BGE:
1633 case Mips::BGT:
1634 case Mips::BLTU:
1635 case Mips::BLEU:
1636 case Mips::BGEU:
1637 case Mips::BGTU:
Jack Carterd0bd6422013-04-18 00:41:53 +00001638 return true;
1639 default:
1640 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001641 }
1642}
Jack Carter92995f12012-10-06 00:53:28 +00001643
Matheus Almeida3813d572014-06-19 14:39:14 +00001644bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001645 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001646 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001647 default: llvm_unreachable("unimplemented expansion");
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001648 case Mips::LoadImm32:
Toma Tabacu00e98672015-05-01 12:19:27 +00001649 return expandLoadImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001650 case Mips::LoadImm64:
Toma Tabacu00e98672015-05-01 12:19:27 +00001651 return expandLoadImm(Inst, false, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001652 case Mips::LoadAddrImm32:
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001653 return expandLoadAddressImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001654 case Mips::LoadAddrReg32:
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001655 return expandLoadAddressReg(Inst, true, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001656 case Mips::B_MM_Pseudo:
1657 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001658 case Mips::SWM_MM:
1659 case Mips::LWM_MM:
1660 return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001661 case Mips::JalOneReg:
1662 case Mips::JalTwoReg:
1663 return expandJalWithRegs(Inst, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00001664 case Mips::BneImm:
1665 case Mips::BeqImm:
1666 return expandBranchImm(Inst, IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00001667 case Mips::BLT:
1668 case Mips::BLE:
1669 case Mips::BGE:
1670 case Mips::BGT:
1671 case Mips::BLTU:
1672 case Mips::BLEU:
1673 case Mips::BGEU:
1674 case Mips::BGTU:
1675 return expandCondBranches(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001676 }
Jack Carter30a59822012-10-04 04:03:53 +00001677}
Jack Carter92995f12012-10-06 00:53:28 +00001678
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001679namespace {
Toma Tabacua2861db2015-05-01 10:26:47 +00001680template <unsigned ShiftAmount>
Toma Tabacu61145652015-04-28 13:16:06 +00001681void createLShiftOri(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001682 SmallVectorImpl<MCInst> &Instructions) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001683 MCInst tmpInst;
Toma Tabacua2861db2015-05-01 10:26:47 +00001684 if (ShiftAmount >= 32) {
1685 tmpInst.setOpcode(Mips::DSLL32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001686 tmpInst.addOperand(MCOperand::createReg(RegNo));
1687 tmpInst.addOperand(MCOperand::createReg(RegNo));
1688 tmpInst.addOperand(MCOperand::createImm(ShiftAmount - 32));
Toma Tabacua2861db2015-05-01 10:26:47 +00001689 tmpInst.setLoc(IDLoc);
1690 Instructions.push_back(tmpInst);
1691 tmpInst.clear();
1692 } else if (ShiftAmount > 0) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001693 tmpInst.setOpcode(Mips::DSLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00001694 tmpInst.addOperand(MCOperand::createReg(RegNo));
1695 tmpInst.addOperand(MCOperand::createReg(RegNo));
1696 tmpInst.addOperand(MCOperand::createImm(ShiftAmount));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001697 tmpInst.setLoc(IDLoc);
1698 Instructions.push_back(tmpInst);
1699 tmpInst.clear();
1700 }
Toma Tabacu7dea2e32015-04-28 14:06:35 +00001701 // There's no need for an ORi if the immediate is 0.
1702 if (Operand.isImm() && Operand.getImm() == 0)
1703 return;
1704
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001705 tmpInst.setOpcode(Mips::ORi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001706 tmpInst.addOperand(MCOperand::createReg(RegNo));
1707 tmpInst.addOperand(MCOperand::createReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001708 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001709 tmpInst.setLoc(IDLoc);
1710 Instructions.push_back(tmpInst);
1711}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001712
Toma Tabacua2861db2015-05-01 10:26:47 +00001713template <unsigned ShiftAmount>
Toma Tabacu61145652015-04-28 13:16:06 +00001714void createLShiftOri(int64_t Value, unsigned RegNo, SMLoc IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001715 SmallVectorImpl<MCInst> &Instructions) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001716 createLShiftOri<ShiftAmount>(MCOperand::createImm(Value), RegNo, IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001717 Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001718}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001719}
1720
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001721bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
1722 SmallVectorImpl<MCInst> &Instructions) {
1723 // Create a JALR instruction which is going to replace the pseudo-JAL.
1724 MCInst JalrInst;
1725 JalrInst.setLoc(IDLoc);
1726 const MCOperand FirstRegOp = Inst.getOperand(0);
1727 const unsigned Opcode = Inst.getOpcode();
1728
1729 if (Opcode == Mips::JalOneReg) {
1730 // jal $rs => jalr $rs
1731 if (inMicroMipsMode()) {
1732 JalrInst.setOpcode(Mips::JALR16_MM);
1733 JalrInst.addOperand(FirstRegOp);
1734 } else {
1735 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00001736 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001737 JalrInst.addOperand(FirstRegOp);
1738 }
1739 } else if (Opcode == Mips::JalTwoReg) {
1740 // jal $rd, $rs => jalr $rd, $rs
1741 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
1742 JalrInst.addOperand(FirstRegOp);
1743 const MCOperand SecondRegOp = Inst.getOperand(1);
1744 JalrInst.addOperand(SecondRegOp);
1745 }
1746 Instructions.push_back(JalrInst);
1747
1748 // If .set reorder is active, emit a NOP after it.
1749 if (AssemblerOptions.back()->isReorder()) {
1750 // This is a 32-bit NOP because these 2 pseudo-instructions
1751 // do not have a short delay slot.
1752 MCInst NopInst;
1753 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00001754 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
1755 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
1756 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001757 Instructions.push_back(NopInst);
1758 }
1759
1760 return false;
1761}
1762
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001763bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
1764 unsigned SrcReg, bool Is32BitImm, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001765 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00001766 if (!Is32BitImm && !isGP64bit()) {
1767 Error(IDLoc, "instruction requires a 64-bit architecture");
1768 return true;
1769 }
1770
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001771 bool UseSrcReg = false;
1772 if (SrcReg != Mips::NoRegister)
1773 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00001774
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001775 MCInst tmpInst;
1776
Jack Carter92995f12012-10-06 00:53:28 +00001777 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001778 // FIXME: gas has a special case for values that are 000...1111, which
1779 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001780 if (0 <= ImmValue && ImmValue <= 65535) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001781 // For unsigned and positive signed 16-bit values (0 <= j <= 65535):
Jack Carter30a59822012-10-04 04:03:53 +00001782 // li d,j => ori d,$zero,j
Toma Tabacudf7fd462015-05-13 16:02:41 +00001783 if (!UseSrcReg)
1784 SrcReg = isGP64bit() ? Mips::ZERO_64 : Mips::ZERO;
Jack Carter873c7242013-01-12 01:03:14 +00001785 tmpInst.setOpcode(Mips::ORi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001786 tmpInst.addOperand(MCOperand::createReg(DstReg));
1787 tmpInst.addOperand(MCOperand::createReg(SrcReg));
1788 tmpInst.addOperand(MCOperand::createImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001789 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001790 } else if (ImmValue < 0 && ImmValue >= -32768) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001791 // For negative signed 16-bit values (-32768 <= j < 0):
Jack Carter30a59822012-10-04 04:03:53 +00001792 // li d,j => addiu d,$zero,j
Toma Tabacudf7fd462015-05-13 16:02:41 +00001793 if (!UseSrcReg)
1794 SrcReg = Mips::ZERO;
Jack Carter873c7242013-01-12 01:03:14 +00001795 tmpInst.setOpcode(Mips::ADDiu);
Jim Grosbache9119e42015-05-13 18:37:00 +00001796 tmpInst.addOperand(MCOperand::createReg(DstReg));
1797 tmpInst.addOperand(MCOperand::createReg(SrcReg));
1798 tmpInst.addOperand(MCOperand::createImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001799 Instructions.push_back(tmpInst);
Toma Tabacua3d056f2015-05-15 09:42:11 +00001800 } else if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00001801 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00001802
Toma Tabacuae47f932015-04-10 13:28:16 +00001803 // For all other values which are representable as a 32-bit integer:
Jack Carter30a59822012-10-04 04:03:53 +00001804 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001805 // ori d,d,lo16(j)
Toma Tabacu79588102015-04-29 10:19:56 +00001806 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1807 uint16_t Bits15To0 = ImmValue & 0xffff;
1808
Toma Tabacua3d056f2015-05-15 09:42:11 +00001809 if (!Is32BitImm && !isInt<32>(ImmValue)) {
1810 // For DLI, expand to an ORi instead of a LUi to avoid sign-extending the
1811 // upper 32 bits.
1812 tmpInst.setOpcode(Mips::ORi);
1813 tmpInst.addOperand(MCOperand::createReg(DstReg));
1814 tmpInst.addOperand(MCOperand::createReg(Mips::ZERO));
1815 tmpInst.addOperand(MCOperand::createImm(Bits31To16));
1816 tmpInst.setLoc(IDLoc);
1817 Instructions.push_back(tmpInst);
1818 // Move the value to the upper 16 bits by doing a 16-bit left shift.
1819 createLShiftOri<16>(0, DstReg, IDLoc, Instructions);
1820 } else {
1821 tmpInst.setOpcode(Mips::LUi);
1822 tmpInst.addOperand(MCOperand::createReg(DstReg));
1823 tmpInst.addOperand(MCOperand::createImm(Bits31To16));
1824 Instructions.push_back(tmpInst);
1825 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001826 createLShiftOri<0>(Bits15To0, DstReg, IDLoc, Instructions);
1827
1828 if (UseSrcReg)
1829 createAddu(DstReg, DstReg, SrcReg, Instructions);
1830
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001831 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Toma Tabacu00e98672015-05-01 12:19:27 +00001832 if (Is32BitImm) {
1833 Error(IDLoc, "instruction requires a 32-bit immediate");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001834 return true;
1835 }
Toma Tabacu81496c12015-05-20 08:54:45 +00001836 warnIfNoMacro(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001837
1838 // <------- lo32 ------>
1839 // <------- hi32 ------>
1840 // <- hi16 -> <- lo16 ->
1841 // _________________________________
1842 // | | | |
Toma Tabacubda745f2015-04-27 15:21:38 +00001843 // | 16-bits | 16-bits | 16-bits |
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001844 // |__________|__________|__________|
1845 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001846 // For any 64-bit value that is representable as a 48-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001847 // li d,j => lui d,hi16(j)
1848 // ori d,d,hi16(lo32(j))
1849 // dsll d,d,16
1850 // ori d,d,lo16(lo32(j))
Toma Tabacu79588102015-04-29 10:19:56 +00001851 uint16_t Bits47To32 = (ImmValue >> 32) & 0xffff;
1852 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1853 uint16_t Bits15To0 = ImmValue & 0xffff;
1854
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001855 tmpInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001856 tmpInst.addOperand(MCOperand::createReg(DstReg));
1857 tmpInst.addOperand(MCOperand::createImm(Bits47To32));
Jack Carter30a59822012-10-04 04:03:53 +00001858 Instructions.push_back(tmpInst);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001859 createLShiftOri<0>(Bits31To16, DstReg, IDLoc, Instructions);
1860 createLShiftOri<16>(Bits15To0, DstReg, IDLoc, Instructions);
1861
1862 if (UseSrcReg)
1863 createAddu(DstReg, DstReg, SrcReg, Instructions);
1864
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001865 } else {
Toma Tabacu00e98672015-05-01 12:19:27 +00001866 if (Is32BitImm) {
1867 Error(IDLoc, "instruction requires a 32-bit immediate");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001868 return true;
1869 }
Toma Tabacu81496c12015-05-20 08:54:45 +00001870 warnIfNoMacro(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001871
1872 // <------- hi32 ------> <------- lo32 ------>
1873 // <- hi16 -> <- lo16 ->
1874 // ___________________________________________
1875 // | | | | |
Toma Tabacubda745f2015-04-27 15:21:38 +00001876 // | 16-bits | 16-bits | 16-bits | 16-bits |
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001877 // |__________|__________|__________|__________|
1878 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001879 // For all other values which are representable as a 64-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001880 // li d,j => lui d,hi16(j)
1881 // ori d,d,lo16(hi32(j))
1882 // dsll d,d,16
1883 // ori d,d,hi16(lo32(j))
1884 // dsll d,d,16
1885 // ori d,d,lo16(lo32(j))
Toma Tabacu79588102015-04-29 10:19:56 +00001886 uint16_t Bits63To48 = (ImmValue >> 48) & 0xffff;
1887 uint16_t Bits47To32 = (ImmValue >> 32) & 0xffff;
1888 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1889 uint16_t Bits15To0 = ImmValue & 0xffff;
1890
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001891 tmpInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001892 tmpInst.addOperand(MCOperand::createReg(DstReg));
1893 tmpInst.addOperand(MCOperand::createImm(Bits63To48));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001894 Instructions.push_back(tmpInst);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001895 createLShiftOri<0>(Bits47To32, DstReg, IDLoc, Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001896
1897 // When Bits31To16 is 0, do a left shift of 32 bits instead of doing
1898 // two left shifts of 16 bits.
1899 if (Bits31To16 == 0) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001900 createLShiftOri<32>(Bits15To0, DstReg, IDLoc, Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001901 } else {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001902 createLShiftOri<16>(Bits31To16, DstReg, IDLoc, Instructions);
1903 createLShiftOri<16>(Bits15To0, DstReg, IDLoc, Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001904 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001905
1906 if (UseSrcReg)
1907 createAddu(DstReg, DstReg, SrcReg, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001908 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001909 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001910}
Jack Carter92995f12012-10-06 00:53:28 +00001911
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001912bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
1913 SmallVectorImpl<MCInst> &Instructions) {
1914 const MCOperand &ImmOp = Inst.getOperand(1);
1915 assert(ImmOp.isImm() && "expected immediate operand kind");
1916 const MCOperand &DstRegOp = Inst.getOperand(0);
1917 assert(DstRegOp.isReg() && "expected register operand kind");
1918
1919 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
1920 Is32BitImm, IDLoc, Instructions))
1921 return true;
1922
1923 return false;
1924}
1925
Matheus Almeida3813d572014-06-19 14:39:14 +00001926bool
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001927MipsAsmParser::expandLoadAddressReg(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001928 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacub5592ee2015-05-14 10:02:58 +00001929 const MCOperand &DstRegOp = Inst.getOperand(0);
1930 assert(DstRegOp.isReg() && "expected register operand kind");
1931
Toma Tabacuf712ede2015-06-17 14:31:51 +00001932 const MCOperand &SrcRegOp = Inst.getOperand(1);
1933 assert(SrcRegOp.isReg() && "expected register operand kind");
1934
Jack Carter543fdf82012-10-09 23:29:45 +00001935 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001936 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1937 "expected immediate operand kind");
1938 if (!ImmOp.isImm()) {
Toma Tabacuf712ede2015-06-17 14:31:51 +00001939 if (loadAndAddSymbolAddress(ImmOp.getExpr(), DstRegOp.getReg(),
1940 SrcRegOp.getReg(), Is32BitImm, IDLoc,
1941 Instructions))
Toma Tabacu674825c2015-06-16 12:16:24 +00001942 return true;
1943
Toma Tabacu0d64b202014-08-14 10:29:17 +00001944 return false;
1945 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001946
1947 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), SrcRegOp.getReg(),
1948 Is32BitImm, IDLoc, Instructions))
1949 return true;
1950
Matheus Almeida3813d572014-06-19 14:39:14 +00001951 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001952}
1953
Matheus Almeida3813d572014-06-19 14:39:14 +00001954bool
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001955MipsAsmParser::expandLoadAddressImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001956 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacub5592ee2015-05-14 10:02:58 +00001957 const MCOperand &DstRegOp = Inst.getOperand(0);
1958 assert(DstRegOp.isReg() && "expected register operand kind");
1959
Jack Carter543fdf82012-10-09 23:29:45 +00001960 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001961 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1962 "expected immediate operand kind");
1963 if (!ImmOp.isImm()) {
Toma Tabacuf712ede2015-06-17 14:31:51 +00001964 if (loadAndAddSymbolAddress(ImmOp.getExpr(), DstRegOp.getReg(),
1965 Mips::NoRegister, Is32BitImm, IDLoc,
1966 Instructions))
Toma Tabacu674825c2015-06-16 12:16:24 +00001967 return true;
1968
Toma Tabacu0d64b202014-08-14 10:29:17 +00001969 return false;
1970 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001971
1972 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
1973 Is32BitImm, IDLoc, Instructions))
1974 return true;
1975
Matheus Almeida3813d572014-06-19 14:39:14 +00001976 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001977}
1978
Toma Tabacuf712ede2015-06-17 14:31:51 +00001979bool MipsAsmParser::loadAndAddSymbolAddress(
1980 const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
1981 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00001982 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00001983
Toma Tabacuec1de822015-05-14 10:53:40 +00001984 if (Is32BitSym && isABI_N64())
1985 Warning(IDLoc, "instruction loads the 32-bit address of a 64-bit symbol");
1986
Toma Tabacu0d64b202014-08-14 10:29:17 +00001987 MCInst tmpInst;
Toma Tabacu674825c2015-06-16 12:16:24 +00001988 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymExpr);
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00001989 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::create(
1990 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1991 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::create(
1992 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1993
Toma Tabacuec1de822015-05-14 10:53:40 +00001994 if (!Is32BitSym) {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001995 // If it's a 64-bit architecture, expand to:
1996 // la d,sym => lui d,highest(sym)
1997 // ori d,d,higher(sym)
1998 // dsll d,d,16
1999 // ori d,d,hi16(sym)
2000 // dsll d,d,16
2001 // ori d,d,lo16(sym)
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002002 const MCSymbolRefExpr *HighestExpr = MCSymbolRefExpr::create(
2003 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
2004 const MCSymbolRefExpr *HigherExpr = MCSymbolRefExpr::create(
2005 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
Toma Tabacu0d64b202014-08-14 10:29:17 +00002006
2007 tmpInst.setOpcode(Mips::LUi);
Toma Tabacu674825c2015-06-16 12:16:24 +00002008 tmpInst.addOperand(MCOperand::createReg(DstReg));
Jim Grosbache9119e42015-05-13 18:37:00 +00002009 tmpInst.addOperand(MCOperand::createExpr(HighestExpr));
Toma Tabacu0d64b202014-08-14 10:29:17 +00002010 Instructions.push_back(tmpInst);
2011
Toma Tabacu674825c2015-06-16 12:16:24 +00002012 createLShiftOri<0>(MCOperand::createExpr(HigherExpr), DstReg, SMLoc(),
Toma Tabacua2861db2015-05-01 10:26:47 +00002013 Instructions);
Toma Tabacu674825c2015-06-16 12:16:24 +00002014 createLShiftOri<16>(MCOperand::createExpr(HiExpr), DstReg, SMLoc(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00002015 Instructions);
Toma Tabacu674825c2015-06-16 12:16:24 +00002016 createLShiftOri<16>(MCOperand::createExpr(LoExpr), DstReg, SMLoc(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00002017 Instructions);
2018 } else {
2019 // Otherwise, expand to:
2020 // la d,sym => lui d,hi16(sym)
2021 // ori d,d,lo16(sym)
2022 tmpInst.setOpcode(Mips::LUi);
Toma Tabacu674825c2015-06-16 12:16:24 +00002023 tmpInst.addOperand(MCOperand::createReg(DstReg));
Jim Grosbache9119e42015-05-13 18:37:00 +00002024 tmpInst.addOperand(MCOperand::createExpr(HiExpr));
Toma Tabacu0d64b202014-08-14 10:29:17 +00002025 Instructions.push_back(tmpInst);
2026
Toma Tabacu674825c2015-06-16 12:16:24 +00002027 createLShiftOri<0>(MCOperand::createExpr(LoExpr), DstReg, SMLoc(),
Toma Tabacua2861db2015-05-01 10:26:47 +00002028 Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00002029 }
Toma Tabacuf712ede2015-06-17 14:31:51 +00002030
2031 if (SrcReg != Mips::NoRegister)
2032 createAddu(DstReg, DstReg, SrcReg, Instructions);
2033
Toma Tabacu674825c2015-06-16 12:16:24 +00002034 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002035}
2036
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002037bool MipsAsmParser::expandUncondBranchMMPseudo(
2038 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002039 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2040 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002041
2042 MCOperand Offset = Inst.getOperand(0);
2043 if (Offset.isExpr()) {
2044 Inst.clear();
2045 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002046 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2047 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2048 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002049 } else {
2050 assert(Offset.isImm() && "expected immediate operand kind");
2051 if (isIntN(11, Offset.getImm())) {
2052 // If offset fits into 11 bits then this instruction becomes microMIPS
2053 // 16-bit unconditional branch instruction.
2054 Inst.setOpcode(Mips::B16_MM);
2055 } else {
2056 if (!isIntN(17, Offset.getImm()))
2057 Error(IDLoc, "branch target out of range");
2058 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2059 Error(IDLoc, "branch to misaligned address");
2060 Inst.clear();
2061 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002062 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2063 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2064 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002065 }
2066 }
2067 Instructions.push_back(Inst);
2068
Toma Tabacu234482a2015-03-16 12:03:39 +00002069 // If .set reorder is active, emit a NOP after the branch instruction.
2070 if (AssemblerOptions.back()->isReorder())
2071 createNop(true, IDLoc, Instructions);
2072
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002073 return false;
2074}
2075
Toma Tabacue1e460d2015-06-11 10:36:10 +00002076bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2077 SmallVectorImpl<MCInst> &Instructions) {
2078 const MCOperand &DstRegOp = Inst.getOperand(0);
2079 assert(DstRegOp.isReg() && "expected register operand kind");
2080
2081 const MCOperand &ImmOp = Inst.getOperand(1);
2082 assert(ImmOp.isImm() && "expected immediate operand kind");
2083
2084 const MCOperand &MemOffsetOp = Inst.getOperand(2);
2085 assert(MemOffsetOp.isImm() && "expected immediate operand kind");
2086
2087 unsigned OpCode = 0;
2088 switch(Inst.getOpcode()) {
2089 case Mips::BneImm:
2090 OpCode = Mips::BNE;
2091 break;
2092 case Mips::BeqImm:
2093 OpCode = Mips::BEQ;
2094 break;
2095 default:
2096 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2097 break;
2098 }
2099
2100 int64_t ImmValue = ImmOp.getImm();
2101 if (ImmValue == 0) {
2102 MCInst BranchInst;
2103 BranchInst.setOpcode(OpCode);
2104 BranchInst.addOperand(DstRegOp);
2105 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2106 BranchInst.addOperand(MemOffsetOp);
2107 Instructions.push_back(BranchInst);
2108 } else {
2109 warnIfNoMacro(IDLoc);
2110
2111 unsigned ATReg = getATReg(IDLoc);
2112 if (!ATReg)
2113 return true;
2114
2115 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), IDLoc,
2116 Instructions))
2117 return true;
2118
2119 MCInst BranchInst;
2120 BranchInst.setOpcode(OpCode);
2121 BranchInst.addOperand(DstRegOp);
2122 BranchInst.addOperand(MCOperand::createReg(ATReg));
2123 BranchInst.addOperand(MemOffsetOp);
2124 Instructions.push_back(BranchInst);
2125 }
2126 return false;
2127}
2128
Jack Carter9e65aa32013-03-22 00:05:30 +00002129void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002130 SmallVectorImpl<MCInst> &Instructions,
2131 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002132 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00002133 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002134 const MCExpr *ExprOffset;
2135 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002136 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002137 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2138 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002139 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002140 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2141 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002142 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002143 if (isImmOpnd) {
2144 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2145 ImmOffset = Inst.getOperand(2).getImm();
2146 LoOffset = ImmOffset & 0x0000ffff;
2147 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002148 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002149 if (LoOffset & 0x8000)
2150 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002151 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002152 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002153 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002154 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002155 // These are some of the types of expansions we perform here:
2156 // 1) lw $8, sym => lui $8, %hi(sym)
2157 // lw $8, %lo(sym)($8)
2158 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2159 // add $8, $8, $9
2160 // lw $8, %lo(offset)($9)
2161 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2162 // add $at, $at, $8
2163 // lw $8, %lo(offset)($at)
2164 // 4) sw $8, sym => lui $at, %hi(sym)
2165 // sw $8, %lo(sym)($at)
2166 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2167 // add $at, $at, $8
2168 // sw $8, %lo(offset)($at)
2169 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2170 // ldc1 $f0, %lo(sym)($at)
2171 //
2172 // For load instructions we can use the destination register as a temporary
2173 // if base and dst are different (examples 1 and 2) and if the base register
2174 // is general purpose otherwise we must use $at (example 6) and error if it's
2175 // not available. For stores we must use $at (examples 4 and 5) because we
2176 // must not clobber the source register setting up the offset.
2177 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2178 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2179 unsigned RegClassIDOp0 =
2180 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2181 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2182 (RegClassIDOp0 == Mips::GPR64RegClassID);
2183 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002184 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002185 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002186 // At this point we need AT to perform the expansions and we exit if it is
2187 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002188 TmpRegNum = getATReg(IDLoc);
2189 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002190 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002191 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002192
Jack Carter9e65aa32013-03-22 00:05:30 +00002193 TempInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00002194 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002195 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002196 TempInst.addOperand(MCOperand::createImm(HiOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002197 else {
Toma Tabacu07c97b32015-06-17 10:43:45 +00002198 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
2199 TempInst.addOperand(MCOperand::createExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002200 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002201 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002202 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002203 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002204 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002205 // Add temp register to base.
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002206 if (BaseRegNum != Mips::ZERO) {
2207 TempInst.setOpcode(Mips::ADDu);
Jim Grosbache9119e42015-05-13 18:37:00 +00002208 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2209 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2210 TempInst.addOperand(MCOperand::createReg(BaseRegNum));
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002211 Instructions.push_back(TempInst);
2212 TempInst.clear();
2213 }
Alp Tokercb402912014-01-24 17:20:08 +00002214 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002215 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002216 TempInst.setOpcode(Inst.getOpcode());
Jim Grosbache9119e42015-05-13 18:37:00 +00002217 TempInst.addOperand(MCOperand::createReg(RegOpNum));
2218 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002219 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002220 TempInst.addOperand(MCOperand::createImm(LoOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002221 else {
Toma Tabacu07c97b32015-06-17 10:43:45 +00002222 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
2223 TempInst.addOperand(MCOperand::createExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002224 }
2225 Instructions.push_back(TempInst);
2226 TempInst.clear();
2227}
2228
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002229bool
2230MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2231 SmallVectorImpl<MCInst> &Instructions) {
2232 unsigned OpNum = Inst.getNumOperands();
2233 unsigned Opcode = Inst.getOpcode();
2234 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2235
2236 assert (Inst.getOperand(OpNum - 1).isImm() &&
2237 Inst.getOperand(OpNum - 2).isReg() &&
2238 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2239
2240 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2241 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2242 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2243 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2244 // It can be implemented as SWM16 or LWM16 instruction.
2245 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2246
2247 Inst.setOpcode(NewOpcode);
2248 Instructions.push_back(Inst);
2249 return false;
2250}
2251
Toma Tabacu1a108322015-06-17 13:20:24 +00002252bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2253 SmallVectorImpl<MCInst> &Instructions) {
2254 unsigned PseudoOpcode = Inst.getOpcode();
2255 unsigned SrcReg = Inst.getOperand(0).getReg();
2256 unsigned TrgReg = Inst.getOperand(1).getReg();
2257 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2258
2259 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
2260 bool ReverseOrderSLT, IsUnsigned, AcceptsEquality;
2261
2262 switch (PseudoOpcode) {
2263 case Mips::BLT:
2264 case Mips::BLTU:
2265 AcceptsEquality = false;
2266 ReverseOrderSLT = false;
2267 IsUnsigned = (PseudoOpcode == Mips::BLTU);
2268 ZeroSrcOpcode = Mips::BGTZ;
2269 ZeroTrgOpcode = Mips::BLTZ;
2270 break;
2271 case Mips::BLE:
2272 case Mips::BLEU:
2273 AcceptsEquality = true;
2274 ReverseOrderSLT = true;
2275 IsUnsigned = (PseudoOpcode == Mips::BLEU);
2276 ZeroSrcOpcode = Mips::BGEZ;
2277 ZeroTrgOpcode = Mips::BLEZ;
2278 break;
2279 case Mips::BGE:
2280 case Mips::BGEU:
2281 AcceptsEquality = true;
2282 ReverseOrderSLT = false;
2283 IsUnsigned = (PseudoOpcode == Mips::BGEU);
2284 ZeroSrcOpcode = Mips::BLEZ;
2285 ZeroTrgOpcode = Mips::BGEZ;
2286 break;
2287 case Mips::BGT:
2288 case Mips::BGTU:
2289 AcceptsEquality = false;
2290 ReverseOrderSLT = true;
2291 IsUnsigned = (PseudoOpcode == Mips::BGTU);
2292 ZeroSrcOpcode = Mips::BLTZ;
2293 ZeroTrgOpcode = Mips::BGTZ;
2294 break;
2295 default:
2296 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2297 }
2298
2299 MCInst BranchInst;
2300 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2301 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2302 if (IsSrcRegZero && IsTrgRegZero) {
2303 // FIXME: All of these Opcode-specific if's are needed for compatibility
2304 // with GAS' behaviour. However, they may not generate the most efficient
2305 // code in some circumstances.
2306 if (PseudoOpcode == Mips::BLT) {
2307 BranchInst.setOpcode(Mips::BLTZ);
2308 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2309 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2310 Instructions.push_back(BranchInst);
2311 return false;
2312 }
2313 if (PseudoOpcode == Mips::BLE) {
2314 BranchInst.setOpcode(Mips::BLEZ);
2315 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2316 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2317 Instructions.push_back(BranchInst);
2318 Warning(IDLoc, "branch is always taken");
2319 return false;
2320 }
2321 if (PseudoOpcode == Mips::BGE) {
2322 BranchInst.setOpcode(Mips::BGEZ);
2323 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2324 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2325 Instructions.push_back(BranchInst);
2326 Warning(IDLoc, "branch is always taken");
2327 return false;
2328 }
2329 if (PseudoOpcode == Mips::BGT) {
2330 BranchInst.setOpcode(Mips::BGTZ);
2331 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2332 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2333 Instructions.push_back(BranchInst);
2334 return false;
2335 }
2336 if (PseudoOpcode == Mips::BGTU) {
2337 BranchInst.setOpcode(Mips::BNE);
2338 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2339 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2340 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2341 Instructions.push_back(BranchInst);
2342 return false;
2343 }
2344 if (AcceptsEquality) {
2345 // If both registers are $0 and the pseudo-branch accepts equality, it
2346 // will always be taken, so we emit an unconditional branch.
2347 BranchInst.setOpcode(Mips::BEQ);
2348 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2349 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2350 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2351 Instructions.push_back(BranchInst);
2352 Warning(IDLoc, "branch is always taken");
2353 return false;
2354 }
2355 // If both registers are $0 and the pseudo-branch does not accept
2356 // equality, it will never be taken, so we don't have to emit anything.
2357 return false;
2358 }
2359 if (IsSrcRegZero || IsTrgRegZero) {
2360 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2361 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2362 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2363 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2364 // the pseudo-branch will never be taken, so we don't emit anything.
2365 // This only applies to unsigned pseudo-branches.
2366 return false;
2367 }
2368 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2369 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2370 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2371 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2372 // the pseudo-branch will always be taken, so we emit an unconditional
2373 // branch.
2374 // This only applies to unsigned pseudo-branches.
2375 BranchInst.setOpcode(Mips::BEQ);
2376 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2377 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2378 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2379 Instructions.push_back(BranchInst);
2380 Warning(IDLoc, "branch is always taken");
2381 return false;
2382 }
2383 if (IsUnsigned) {
2384 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2385 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2386 // the pseudo-branch will be taken only when the non-zero register is
2387 // different from 0, so we emit a BNEZ.
2388 //
2389 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2390 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2391 // the pseudo-branch will be taken only when the non-zero register is
2392 // equal to 0, so we emit a BEQZ.
2393 //
2394 // Because only BLEU and BGEU branch on equality, we can use the
2395 // AcceptsEquality variable to decide when to emit the BEQZ.
2396 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQ : Mips::BNE);
2397 BranchInst.addOperand(
2398 MCOperand::createReg(IsSrcRegZero ? TrgReg : SrcReg));
2399 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2400 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2401 Instructions.push_back(BranchInst);
2402 return false;
2403 }
2404 // If we have a signed pseudo-branch and one of the registers is $0,
2405 // we can use an appropriate compare-to-zero branch. We select which one
2406 // to use in the switch statement above.
2407 BranchInst.setOpcode(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode);
2408 BranchInst.addOperand(MCOperand::createReg(IsSrcRegZero ? TrgReg : SrcReg));
2409 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2410 Instructions.push_back(BranchInst);
2411 return false;
2412 }
2413
2414 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2415 // expansions. If it is not available, we return.
2416 unsigned ATRegNum = getATReg(IDLoc);
2417 if (!ATRegNum)
2418 return true;
2419
2420 warnIfNoMacro(IDLoc);
2421
2422 // SLT fits well with 2 of our 4 pseudo-branches:
2423 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2424 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2425 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2426 // This is accomplished by using a BNEZ with the result of the SLT.
2427 //
2428 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2429 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2430 // Because only BGE and BLE branch on equality, we can use the
2431 // AcceptsEquality variable to decide when to emit the BEQZ.
2432 // Note that the order of the SLT arguments doesn't change between
2433 // opposites.
2434 //
2435 // The same applies to the unsigned variants, except that SLTu is used
2436 // instead of SLT.
2437 MCInst SetInst;
2438 SetInst.setOpcode(IsUnsigned ? Mips::SLTu : Mips::SLT);
2439 SetInst.addOperand(MCOperand::createReg(ATRegNum));
2440 SetInst.addOperand(MCOperand::createReg(ReverseOrderSLT ? TrgReg : SrcReg));
2441 SetInst.addOperand(MCOperand::createReg(ReverseOrderSLT ? SrcReg : TrgReg));
2442 Instructions.push_back(SetInst);
2443
2444 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQ : Mips::BNE);
2445 BranchInst.addOperand(MCOperand::createReg(ATRegNum));
2446 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2447 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2448 Instructions.push_back(BranchInst);
2449 return false;
2450}
2451
Toma Tabacu234482a2015-03-16 12:03:39 +00002452void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
2453 SmallVectorImpl<MCInst> &Instructions) {
2454 MCInst NopInst;
2455 if (hasShortDelaySlot) {
2456 NopInst.setOpcode(Mips::MOVE16_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002457 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2458 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
Toma Tabacu234482a2015-03-16 12:03:39 +00002459 } else {
2460 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00002461 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2462 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2463 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu234482a2015-03-16 12:03:39 +00002464 }
2465 Instructions.push_back(NopInst);
2466}
2467
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002468void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
2469 unsigned TrgReg,
2470 SmallVectorImpl<MCInst> &Instructions) {
2471 MCInst AdduInst;
2472 AdduInst.setOpcode(Mips::ADDu);
Jim Grosbache9119e42015-05-13 18:37:00 +00002473 AdduInst.addOperand(MCOperand::createReg(DstReg));
2474 AdduInst.addOperand(MCOperand::createReg(SrcReg));
2475 AdduInst.addOperand(MCOperand::createReg(TrgReg));
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002476 Instructions.push_back(AdduInst);
2477}
2478
Matheus Almeida595fcab2014-06-11 15:05:56 +00002479unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
2480 // As described by the Mips32r2 spec, the registers Rd and Rs for
2481 // jalr.hb must be different.
2482 unsigned Opcode = Inst.getOpcode();
2483
2484 if (Opcode == Mips::JALR_HB &&
2485 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
2486 return Match_RequiresDifferentSrcAndDst;
2487
2488 return Match_Success;
2489}
2490
David Blaikie960ea3f2014-06-08 16:18:35 +00002491bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
2492 OperandVector &Operands,
2493 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00002494 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00002495 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00002496
Jack Carterb4dbc172012-09-05 23:34:03 +00002497 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00002498 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00002499 unsigned MatchResult =
2500 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00002501
2502 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002503 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002504 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00002505 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00002506 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00002507 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00002508 return false;
2509 }
2510 case Match_MissingFeature:
2511 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
2512 return true;
2513 case Match_InvalidOperand: {
2514 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00002515 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002516 if (ErrorInfo >= Operands.size())
2517 return Error(IDLoc, "too few operands for instruction");
2518
David Blaikie960ea3f2014-06-08 16:18:35 +00002519 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00002520 if (ErrorLoc == SMLoc())
2521 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00002522 }
2523
2524 return Error(ErrorLoc, "invalid operand for instruction");
2525 }
2526 case Match_MnemonicFail:
2527 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00002528 case Match_RequiresDifferentSrcAndDst:
2529 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00002530 }
Craig Topper589ceee2015-01-03 08:16:34 +00002531
2532 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00002533}
2534
Toma Tabacud9d344b2015-04-27 14:05:04 +00002535void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
2536 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
2537 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
2538 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002539}
2540
Toma Tabacu81496c12015-05-20 08:54:45 +00002541void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
2542 if (!AssemblerOptions.back()->isMacro())
2543 Warning(Loc, "macro instruction expanded into multiple instructions");
2544}
2545
Daniel Sandersef638fe2014-10-03 15:37:37 +00002546void
2547MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
2548 SMRange Range, bool ShowColors) {
2549 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00002550 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00002551 ShowColors);
2552}
2553
Jack Carter1ac53222013-02-20 23:11:17 +00002554int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002555 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002556
Vladimir Medic4c299852013-11-06 11:27:05 +00002557 CC = StringSwitch<unsigned>(Name)
2558 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002559 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00002560 .Case("a0", 4)
2561 .Case("a1", 5)
2562 .Case("a2", 6)
2563 .Case("a3", 7)
2564 .Case("v0", 2)
2565 .Case("v1", 3)
2566 .Case("s0", 16)
2567 .Case("s1", 17)
2568 .Case("s2", 18)
2569 .Case("s3", 19)
2570 .Case("s4", 20)
2571 .Case("s5", 21)
2572 .Case("s6", 22)
2573 .Case("s7", 23)
2574 .Case("k0", 26)
2575 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002576 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00002577 .Case("sp", 29)
2578 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002579 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00002580 .Case("ra", 31)
2581 .Case("t0", 8)
2582 .Case("t1", 9)
2583 .Case("t2", 10)
2584 .Case("t3", 11)
2585 .Case("t4", 12)
2586 .Case("t5", 13)
2587 .Case("t6", 14)
2588 .Case("t7", 15)
2589 .Case("t8", 24)
2590 .Case("t9", 25)
2591 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002592
Toma Tabacufda445c2014-09-15 15:33:01 +00002593 if (!(isABI_N32() || isABI_N64()))
2594 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002595
Daniel Sandersef638fe2014-10-03 15:37:37 +00002596 if (12 <= CC && CC <= 15) {
2597 // Name is one of t4-t7
2598 AsmToken RegTok = getLexer().peekTok();
2599 SMRange RegRange = RegTok.getLocRange();
2600
2601 StringRef FixedName = StringSwitch<StringRef>(Name)
2602 .Case("t4", "t0")
2603 .Case("t5", "t1")
2604 .Case("t6", "t2")
2605 .Case("t7", "t3")
2606 .Default("");
2607 assert(FixedName != "" && "Register name is not one of t4-t7.");
2608
2609 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
2610 "Did you mean $" + FixedName + "?", RegRange);
2611 }
2612
Toma Tabacufda445c2014-09-15 15:33:01 +00002613 // Although SGI documentation just cuts out t0-t3 for n32/n64,
2614 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
2615 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
2616 if (8 <= CC && CC <= 11)
2617 CC += 4;
2618
2619 if (CC == -1)
2620 CC = StringSwitch<unsigned>(Name)
2621 .Case("a4", 8)
2622 .Case("a5", 9)
2623 .Case("a6", 10)
2624 .Case("a7", 11)
2625 .Case("kt0", 26)
2626 .Case("kt1", 27)
2627 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002628
2629 return CC;
2630}
Jack Carterd0bd6422013-04-18 00:41:53 +00002631
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002632int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
2633 int CC;
2634
2635 CC = StringSwitch<unsigned>(Name)
2636 .Case("hwr_cpunum", 0)
2637 .Case("hwr_synci_step", 1)
2638 .Case("hwr_cc", 2)
2639 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00002640 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002641 .Default(-1);
2642
2643 return CC;
2644}
2645
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002646int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002647
Jack Cartera63b16a2012-09-07 00:23:42 +00002648 if (Name[0] == 'f') {
2649 StringRef NumString = Name.substr(1);
2650 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002651 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002652 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002653 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00002654 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002655 return IntVal;
2656 }
2657 return -1;
2658}
Jack Cartera63b16a2012-09-07 00:23:42 +00002659
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002660int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
2661
2662 if (Name.startswith("fcc")) {
2663 StringRef NumString = Name.substr(3);
2664 unsigned IntVal;
2665 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002666 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002667 if (IntVal > 7) // There are only 8 fcc registers.
2668 return -1;
2669 return IntVal;
2670 }
2671 return -1;
2672}
2673
2674int MipsAsmParser::matchACRegisterName(StringRef Name) {
2675
Akira Hatanaka274d24c2013-08-14 01:15:52 +00002676 if (Name.startswith("ac")) {
2677 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002678 unsigned IntVal;
2679 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002680 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002681 if (IntVal > 3) // There are only 3 acc registers.
2682 return -1;
2683 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00002684 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002685 return -1;
2686}
Jack Carterd0bd6422013-04-18 00:41:53 +00002687
Jack Carter5dc8ac92013-09-25 23:50:44 +00002688int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
2689 unsigned IntVal;
2690
2691 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2692 return -1;
2693
2694 if (IntVal > 31)
2695 return -1;
2696
2697 return IntVal;
2698}
2699
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002700int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
2701 int CC;
2702
2703 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00002704 .Case("msair", 0)
2705 .Case("msacsr", 1)
2706 .Case("msaaccess", 2)
2707 .Case("msasave", 3)
2708 .Case("msamodify", 4)
2709 .Case("msarequest", 5)
2710 .Case("msamap", 6)
2711 .Case("msaunmap", 7)
2712 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002713
2714 return CC;
2715}
2716
Toma Tabacu89a712b2015-04-15 10:48:56 +00002717unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00002718 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00002719 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002720 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00002721 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00002722 return 0;
2723 }
2724 unsigned AT = getReg(
2725 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00002726 return AT;
2727}
Jack Carter0b744b32012-10-04 02:29:46 +00002728
Jack Carterd0bd6422013-04-18 00:41:53 +00002729unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00002730 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00002731}
2732
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002733unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002734 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00002735 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002736}
2737
Jack Carter873c7242013-01-12 01:03:14 +00002738int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002739 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00002740 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00002741 return -1;
2742
Jack Carter873c7242013-01-12 01:03:14 +00002743 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00002744}
2745
Toma Tabacu13964452014-09-04 13:23:44 +00002746bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002747 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002748 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002749
Jack Carter30a59822012-10-04 04:03:53 +00002750 // Check if the current operand has a custom associated parser, if so, try to
2751 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00002752 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2753 if (ResTy == MatchOperand_Success)
2754 return false;
2755 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2756 // there was a match, but an error occurred, in which case, just return that
2757 // the operand parsing failed.
2758 if (ResTy == MatchOperand_ParseFail)
2759 return true;
2760
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002761 DEBUG(dbgs() << ".. Generic Parser\n");
2762
Jack Carterb4dbc172012-09-05 23:34:03 +00002763 switch (getLexer().getKind()) {
2764 default:
2765 Error(Parser.getTok().getLoc(), "unexpected token in operand");
2766 return true;
2767 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002768 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00002769 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00002770
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002771 // Almost all registers have been parsed by custom parsers. There is only
2772 // one exception to this. $zero (and it's alias $0) will reach this point
2773 // for div, divu, and similar instructions because it is not an operand
2774 // to the instruction definition but an explicit register. Special case
2775 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00002776 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00002777 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002778
Jack Carterd0bd6422013-04-18 00:41:53 +00002779 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00002780 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002781 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00002782 return true;
2783
Jack Carter873c7242013-01-12 01:03:14 +00002784 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00002785 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00002786 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00002787 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002788 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00002789
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002790 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002791 return false;
2792 }
Vladimir Medic4c299852013-11-06 11:27:05 +00002793 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00002794 case AsmToken::LParen:
2795 case AsmToken::Minus:
2796 case AsmToken::Plus:
2797 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002798 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00002799 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002800 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002801 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002802 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00002803 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00002804 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002805 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002806 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002807 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00002808 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00002809 return true;
2810
Jack Carter873c7242013-01-12 01:03:14 +00002811 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2812
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002813 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00002814 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002815 } // case AsmToken::Percent
2816 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00002817 return true;
2818}
2819
Vladimir Medic4c299852013-11-06 11:27:05 +00002820const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00002821 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00002822 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00002823 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002824 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00002825 // It's a constant, evaluate reloc value.
2826 int16_t Val;
2827 switch (getVariantKind(RelocStr)) {
2828 case MCSymbolRefExpr::VK_Mips_ABS_LO:
2829 // Get the 1st 16-bits.
2830 Val = MCE->getValue() & 0xffff;
2831 break;
2832 case MCSymbolRefExpr::VK_Mips_ABS_HI:
2833 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2834 // 16 bits being negative.
2835 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2836 break;
2837 case MCSymbolRefExpr::VK_Mips_HIGHER:
2838 // Get the 3rd 16-bits.
2839 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2840 break;
2841 case MCSymbolRefExpr::VK_Mips_HIGHEST:
2842 // Get the 4th 16-bits.
2843 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2844 break;
2845 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00002846 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00002847 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00002848 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002849 }
2850
Jack Carterb5cf5902013-04-17 00:18:04 +00002851 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002852 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00002853 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00002854 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00002855 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002856 return Res;
2857 }
2858
2859 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00002860 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2861
Sasa Stankovic06c47802014-04-03 10:37:45 +00002862 // Try to create target expression.
2863 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00002864 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002865
Jack Carterd0bd6422013-04-18 00:41:53 +00002866 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2867 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00002868 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002869 return Res;
2870 }
2871
2872 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002873 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00002874 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00002875 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002876 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002877 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002878 return Expr;
2879}
2880
2881bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2882
2883 switch (Expr->getKind()) {
2884 case MCExpr::Constant:
2885 return true;
2886 case MCExpr::SymbolRef:
2887 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2888 case MCExpr::Binary:
2889 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2890 if (!isEvaluated(BE->getLHS()))
2891 return false;
2892 return isEvaluated(BE->getRHS());
2893 }
2894 case MCExpr::Unary:
2895 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002896 case MCExpr::Target:
2897 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002898 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002899 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002900}
Jack Carterd0bd6422013-04-18 00:41:53 +00002901
Jack Carterb5cf5902013-04-17 00:18:04 +00002902bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002903 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00002904 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002905 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002906 if (Tok.isNot(AsmToken::Identifier))
2907 return true;
2908
Yaron Keren075759a2015-03-30 15:42:36 +00002909 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00002910
Jack Carterd0bd6422013-04-18 00:41:53 +00002911 Parser.Lex(); // Eat the identifier.
2912 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002913 const MCExpr *IdVal;
2914 SMLoc EndLoc;
2915
2916 if (getLexer().getKind() == AsmToken::LParen) {
2917 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002918 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002919 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002920 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002921 const AsmToken &nextTok = Parser.getTok();
2922 if (nextTok.isNot(AsmToken::Identifier))
2923 return true;
2924 Str += "(%";
2925 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002926 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002927 if (getLexer().getKind() != AsmToken::LParen)
2928 return true;
2929 } else
2930 break;
2931 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002932 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002933 return true;
2934
2935 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002936 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002937
2938 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002939 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002940
Jack Carterd0bd6422013-04-18 00:41:53 +00002941 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002942 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002943}
2944
Jack Carterb4dbc172012-09-05 23:34:03 +00002945bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2946 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002947 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002948 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002949 if (ResTy == MatchOperand_Success) {
2950 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002951 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002952 StartLoc = Operand.getStartLoc();
2953 EndLoc = Operand.getEndLoc();
2954
2955 // AFAIK, we only support numeric registers and named GPR's in CFI
2956 // directives.
2957 // Don't worry about eating tokens before failing. Using an unrecognised
2958 // register is a parse error.
2959 if (Operand.isGPRAsmReg()) {
2960 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002961 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002962 }
2963
2964 return (RegNo == (unsigned)-1);
2965 }
2966
2967 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002968 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002969}
2970
Jack Carterb5cf5902013-04-17 00:18:04 +00002971bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002972 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00002973 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002974 bool Result = true;
2975
2976 while (getLexer().getKind() == AsmToken::LParen)
2977 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002978
Jack Carterd0bd6422013-04-18 00:41:53 +00002979 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002980 default:
2981 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002982 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002983 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002984 case AsmToken::Integer:
2985 case AsmToken::Minus:
2986 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002987 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002988 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002989 else
2990 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002991 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002992 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002993 break;
Jack Carter873c7242013-01-12 01:03:14 +00002994 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002995 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002996 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002997 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002998}
2999
David Blaikie960ea3f2014-06-08 16:18:35 +00003000MipsAsmParser::OperandMatchResultTy
3001MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003002 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003003 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00003004 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00003005 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003006 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003007 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00003008 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00003009 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00003010
Jack Carterb5cf5902013-04-17 00:18:04 +00003011 if (getLexer().getKind() == AsmToken::LParen) {
3012 Parser.Lex();
3013 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003014 }
3015
Jack Carterb5cf5902013-04-17 00:18:04 +00003016 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003017 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00003018 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003019
Jack Carterd0bd6422013-04-18 00:41:53 +00003020 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003021 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003022 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
3023 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003024 SMLoc E =
3025 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003026 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003027 return MatchOperand_Success;
3028 }
3029 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003030 SMLoc E =
3031 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00003032
Jack Carterd0bd6422013-04-18 00:41:53 +00003033 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003034 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00003035 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003036 S, E, *this);
3037 Operands.push_back(
3038 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003039 return MatchOperand_Success;
3040 }
3041 Error(Parser.getTok().getLoc(), "'(' expected");
3042 return MatchOperand_ParseFail;
3043 }
3044
Jack Carterd0bd6422013-04-18 00:41:53 +00003045 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003046 }
3047
Toma Tabacu13964452014-09-04 13:23:44 +00003048 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003049 if (Res != MatchOperand_Success)
3050 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003051
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003052 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003053 Error(Parser.getTok().getLoc(), "')' expected");
3054 return MatchOperand_ParseFail;
3055 }
3056
Jack Carter873c7242013-01-12 01:03:14 +00003057 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3058
Jack Carterd0bd6422013-04-18 00:41:53 +00003059 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003060
Craig Topper062a2ba2014-04-25 05:30:21 +00003061 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003062 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003063
Jack Carterd0bd6422013-04-18 00:41:53 +00003064 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00003065 std::unique_ptr<MipsOperand> op(
3066 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00003067 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003068 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003069 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00003070 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003071 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
3072 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003073 if (IdVal->evaluateAsAbsolute(Imm))
3074 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003075 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003076 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00003077 getContext());
3078 }
3079
David Blaikie960ea3f2014-06-08 16:18:35 +00003080 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003081 return MatchOperand_Success;
3082}
3083
David Blaikie960ea3f2014-06-08 16:18:35 +00003084bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003085 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00003086 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00003087 if (Sym) {
3088 SMLoc S = Parser.getTok().getLoc();
3089 const MCExpr *Expr;
3090 if (Sym->isVariable())
3091 Expr = Sym->getVariableValue();
3092 else
3093 return false;
3094 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003095 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00003096 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00003097 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003098 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003099 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00003100 if (ResTy == MatchOperand_Success) {
3101 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00003102 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00003103 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003104 llvm_unreachable("Should never ParseFail");
3105 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00003106 }
3107 } else if (Expr->getKind() == MCExpr::Constant) {
3108 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00003109 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00003110 Operands.push_back(
3111 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00003112 return true;
3113 }
3114 }
3115 return false;
3116}
Jack Carterd0bd6422013-04-18 00:41:53 +00003117
Jack Carter873c7242013-01-12 01:03:14 +00003118MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003119MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00003120 StringRef Identifier,
3121 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003122 int Index = matchCPURegisterName(Identifier);
3123 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003124 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003125 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3126 return MatchOperand_Success;
3127 }
3128
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003129 Index = matchHWRegsRegisterName(Identifier);
3130 if (Index != -1) {
3131 Operands.push_back(MipsOperand::createHWRegsReg(
3132 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3133 return MatchOperand_Success;
3134 }
3135
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003136 Index = matchFPURegisterName(Identifier);
3137 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003138 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003139 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3140 return MatchOperand_Success;
3141 }
3142
3143 Index = matchFCCRegisterName(Identifier);
3144 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003145 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003146 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3147 return MatchOperand_Success;
3148 }
3149
3150 Index = matchACRegisterName(Identifier);
3151 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003152 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003153 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3154 return MatchOperand_Success;
3155 }
3156
3157 Index = matchMSA128RegisterName(Identifier);
3158 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003159 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003160 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3161 return MatchOperand_Success;
3162 }
3163
3164 Index = matchMSA128CtrlRegisterName(Identifier);
3165 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003166 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003167 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3168 return MatchOperand_Success;
3169 }
3170
3171 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00003172}
3173
3174MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003175MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003176 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00003177 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003178
3179 if (Token.is(AsmToken::Identifier)) {
3180 DEBUG(dbgs() << ".. identifier\n");
3181 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00003182 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003183 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00003184 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003185 } else if (Token.is(AsmToken::Integer)) {
3186 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003187 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003188 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
3189 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003190 return MatchOperand_Success;
3191 }
3192
3193 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
3194
3195 return MatchOperand_NoMatch;
3196}
3197
David Blaikie960ea3f2014-06-08 16:18:35 +00003198MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003199MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003200 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003201 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003202
3203 auto Token = Parser.getTok();
3204
3205 SMLoc S = Token.getLoc();
3206
3207 if (Token.isNot(AsmToken::Dollar)) {
3208 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
3209 if (Token.is(AsmToken::Identifier)) {
3210 if (searchSymbolAlias(Operands))
3211 return MatchOperand_Success;
3212 }
3213 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
3214 return MatchOperand_NoMatch;
3215 }
3216 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003217
Toma Tabacu13964452014-09-04 13:23:44 +00003218 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00003219 if (ResTy == MatchOperand_Success) {
3220 Parser.Lex(); // $
3221 Parser.Lex(); // identifier
3222 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003223 return ResTy;
3224}
3225
3226MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003227MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003228 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003229 switch (getLexer().getKind()) {
3230 default:
3231 return MatchOperand_NoMatch;
3232 case AsmToken::LParen:
3233 case AsmToken::Minus:
3234 case AsmToken::Plus:
3235 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003236 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003237 case AsmToken::String:
3238 break;
3239 }
3240
3241 const MCExpr *IdVal;
3242 SMLoc S = Parser.getTok().getLoc();
3243 if (getParser().parseExpression(IdVal))
3244 return MatchOperand_ParseFail;
3245
3246 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3247 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
3248 return MatchOperand_Success;
3249}
3250
David Blaikie960ea3f2014-06-08 16:18:35 +00003251MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003252MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003253 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003254 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003255
3256 SMLoc S = getLexer().getLoc();
3257
3258 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00003259 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003260 if (ResTy != MatchOperand_NoMatch)
3261 return ResTy;
3262
Daniel Sanders315386c2014-04-01 10:40:14 +00003263 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00003264 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00003265 if (ResTy != MatchOperand_NoMatch)
3266 return ResTy;
3267
Daniel Sandersffd84362014-04-01 10:41:48 +00003268 const MCExpr *Expr = nullptr;
3269 if (Parser.parseExpression(Expr)) {
3270 // We have no way of knowing if a symbol was consumed so we must ParseFail
3271 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003272 }
Daniel Sandersffd84362014-04-01 10:41:48 +00003273 Operands.push_back(
3274 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003275 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00003276}
3277
Vladimir Medic2b953d02013-10-01 09:48:56 +00003278MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00003279MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003280 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00003281 const MCExpr *IdVal;
3282 // If the first token is '$' we may have register operand.
3283 if (Parser.getTok().is(AsmToken::Dollar))
3284 return MatchOperand_NoMatch;
3285 SMLoc S = Parser.getTok().getLoc();
3286 if (getParser().parseExpression(IdVal))
3287 return MatchOperand_ParseFail;
3288 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00003289 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00003290 int64_t Val = MCE->getValue();
3291 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3292 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003293 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00003294 return MatchOperand_Success;
3295}
3296
Matheus Almeida779c5932013-11-18 12:32:49 +00003297MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003298MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003299 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00003300 switch (getLexer().getKind()) {
3301 default:
3302 return MatchOperand_NoMatch;
3303 case AsmToken::LParen:
3304 case AsmToken::Plus:
3305 case AsmToken::Minus:
3306 case AsmToken::Integer:
3307 break;
3308 }
3309
3310 const MCExpr *Expr;
3311 SMLoc S = Parser.getTok().getLoc();
3312
3313 if (getParser().parseExpression(Expr))
3314 return MatchOperand_ParseFail;
3315
3316 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003317 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00003318 Error(S, "expected immediate value");
3319 return MatchOperand_ParseFail;
3320 }
3321
3322 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
3323 // and because the CPU always adds one to the immediate field, the allowed
3324 // range becomes 1..4. We'll only check the range here and will deal
3325 // with the addition/subtraction when actually decoding/encoding
3326 // the instruction.
3327 if (Val < 1 || Val > 4) {
3328 Error(S, "immediate not in range (1..4)");
3329 return MatchOperand_ParseFail;
3330 }
3331
Jack Carter3b2c96e2014-01-22 23:31:38 +00003332 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003333 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00003334 return MatchOperand_Success;
3335}
3336
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00003337MipsAsmParser::OperandMatchResultTy
3338MipsAsmParser::parseRegisterList(OperandVector &Operands) {
3339 MCAsmParser &Parser = getParser();
3340 SmallVector<unsigned, 10> Regs;
3341 unsigned RegNo;
3342 unsigned PrevReg = Mips::NoRegister;
3343 bool RegRange = false;
3344 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3345
3346 if (Parser.getTok().isNot(AsmToken::Dollar))
3347 return MatchOperand_ParseFail;
3348
3349 SMLoc S = Parser.getTok().getLoc();
3350 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
3351 SMLoc E = getLexer().getLoc();
3352 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
3353 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
3354 if (RegRange) {
3355 // Remove last register operand because registers from register range
3356 // should be inserted first.
3357 if (RegNo == Mips::RA) {
3358 Regs.push_back(RegNo);
3359 } else {
3360 unsigned TmpReg = PrevReg + 1;
3361 while (TmpReg <= RegNo) {
3362 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
3363 Error(E, "invalid register operand");
3364 return MatchOperand_ParseFail;
3365 }
3366
3367 PrevReg = TmpReg;
3368 Regs.push_back(TmpReg++);
3369 }
3370 }
3371
3372 RegRange = false;
3373 } else {
3374 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
3375 (RegNo != Mips::RA)) {
3376 Error(E, "$16 or $31 expected");
3377 return MatchOperand_ParseFail;
3378 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
3379 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3380 Error(E, "invalid register operand");
3381 return MatchOperand_ParseFail;
3382 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
3383 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3384 Error(E, "consecutive register numbers expected");
3385 return MatchOperand_ParseFail;
3386 }
3387
3388 Regs.push_back(RegNo);
3389 }
3390
3391 if (Parser.getTok().is(AsmToken::Minus))
3392 RegRange = true;
3393
3394 if (!Parser.getTok().isNot(AsmToken::Minus) &&
3395 !Parser.getTok().isNot(AsmToken::Comma)) {
3396 Error(E, "',' or '-' expected");
3397 return MatchOperand_ParseFail;
3398 }
3399
3400 Lex(); // Consume comma or minus
3401 if (Parser.getTok().isNot(AsmToken::Dollar))
3402 break;
3403
3404 PrevReg = RegNo;
3405 }
3406
3407 SMLoc E = Parser.getTok().getLoc();
3408 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3409 parseMemOperand(Operands);
3410 return MatchOperand_Success;
3411}
3412
Zoran Jovanovic2deca342014-12-16 14:59:10 +00003413MipsAsmParser::OperandMatchResultTy
3414MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
3415 MCAsmParser &Parser = getParser();
3416
3417 SMLoc S = Parser.getTok().getLoc();
3418 if (parseAnyRegister(Operands) != MatchOperand_Success)
3419 return MatchOperand_ParseFail;
3420
3421 SMLoc E = Parser.getTok().getLoc();
3422 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
3423 unsigned Reg = Op.getGPR32Reg();
3424 Operands.pop_back();
3425 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
3426 return MatchOperand_Success;
3427}
3428
Zoran Jovanovic41688672015-02-10 16:36:20 +00003429MipsAsmParser::OperandMatchResultTy
3430MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
3431 MCAsmParser &Parser = getParser();
3432 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3433 SmallVector<unsigned, 10> Regs;
3434
3435 if (Parser.getTok().isNot(AsmToken::Dollar))
3436 return MatchOperand_ParseFail;
3437
3438 SMLoc S = Parser.getTok().getLoc();
3439
3440 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3441 return MatchOperand_ParseFail;
3442
3443 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3444 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3445 Regs.push_back(RegNo);
3446
3447 SMLoc E = Parser.getTok().getLoc();
3448 if (Parser.getTok().isNot(AsmToken::Comma)) {
3449 Error(E, "',' expected");
3450 return MatchOperand_ParseFail;
3451 }
3452
3453 // Remove comma.
3454 Parser.Lex();
3455
3456 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3457 return MatchOperand_ParseFail;
3458
3459 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3460 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3461 Regs.push_back(RegNo);
3462
3463 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3464
3465 return MatchOperand_Success;
3466}
3467
Jack Carterdc1e35d2012-09-06 20:00:02 +00003468MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
3469
Vladimir Medic4c299852013-11-06 11:27:05 +00003470 MCSymbolRefExpr::VariantKind VK =
3471 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
3472 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
3473 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
3474 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
3475 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
3476 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
3477 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
3478 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
3479 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
3480 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
3481 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
3482 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
3483 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
3484 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
3485 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
3486 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
3487 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
3488 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00003489 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
3490 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
3491 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
3492 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
3493 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
3494 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00003495 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
3496 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00003497 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003498
Matheus Almeida2852af82014-04-22 10:15:54 +00003499 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00003500
Jack Carterdc1e35d2012-09-06 20:00:02 +00003501 return VK;
3502}
Jack Cartera63b16a2012-09-07 00:23:42 +00003503
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003504/// Sometimes (i.e. load/stores) the operand may be followed immediately by
3505/// either this.
3506/// ::= '(', register, ')'
3507/// handle it before we iterate so we don't get tripped up by the lack of
3508/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003509bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003510 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003511 if (getLexer().is(AsmToken::LParen)) {
3512 Operands.push_back(
3513 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
3514 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003515 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003516 SMLoc Loc = getLexer().getLoc();
3517 Parser.eatToEndOfStatement();
3518 return Error(Loc, "unexpected token in argument list");
3519 }
3520 if (Parser.getTok().isNot(AsmToken::RParen)) {
3521 SMLoc Loc = getLexer().getLoc();
3522 Parser.eatToEndOfStatement();
3523 return Error(Loc, "unexpected token, expected ')'");
3524 }
3525 Operands.push_back(
3526 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
3527 Parser.Lex();
3528 }
3529 return false;
3530}
3531
3532/// Sometimes (i.e. in MSA) the operand may be followed immediately by
3533/// either one of these.
3534/// ::= '[', register, ']'
3535/// ::= '[', integer, ']'
3536/// handle it before we iterate so we don't get tripped up by the lack of
3537/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003538bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00003539 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003540 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003541 if (getLexer().is(AsmToken::LBrac)) {
3542 Operands.push_back(
3543 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
3544 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003545 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003546 SMLoc Loc = getLexer().getLoc();
3547 Parser.eatToEndOfStatement();
3548 return Error(Loc, "unexpected token in argument list");
3549 }
3550 if (Parser.getTok().isNot(AsmToken::RBrac)) {
3551 SMLoc Loc = getLexer().getLoc();
3552 Parser.eatToEndOfStatement();
3553 return Error(Loc, "unexpected token, expected ']'");
3554 }
3555 Operands.push_back(
3556 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
3557 Parser.Lex();
3558 }
3559 return false;
3560}
3561
David Blaikie960ea3f2014-06-08 16:18:35 +00003562bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
3563 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003564 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003565 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003566
3567 // We have reached first instruction, module directive are now forbidden.
3568 getTargetStreamer().forbidModuleDirective();
3569
Vladimir Medic74593e62013-07-17 15:00:42 +00003570 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00003571 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00003572 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00003573 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00003574 }
Vladimir Medic64828a12013-07-16 10:07:14 +00003575 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003576 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003577
3578 // Read the remaining operands.
3579 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3580 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003581 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003582 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003583 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003584 return Error(Loc, "unexpected token in argument list");
3585 }
Toma Tabacu13964452014-09-04 13:23:44 +00003586 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003587 return true;
3588 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00003589
Jack Carterd0bd6422013-04-18 00:41:53 +00003590 while (getLexer().is(AsmToken::Comma)) {
3591 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00003592 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003593 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003594 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003595 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003596 return Error(Loc, "unexpected token in argument list");
3597 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003598 // Parse bracket and parenthesis suffixes before we iterate
3599 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00003600 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003601 return true;
3602 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00003603 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003604 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003605 }
3606 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003607 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3608 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003609 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003610 return Error(Loc, "unexpected token in argument list");
3611 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003612 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00003613 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00003614}
3615
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003616bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003617 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003618 SMLoc Loc = getLexer().getLoc();
3619 Parser.eatToEndOfStatement();
3620 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00003621}
3622
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003623bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003624 return Error(Loc, ErrorMsg);
3625}
3626
Jack Carter0b744b32012-10-04 02:29:46 +00003627bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003628 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003629 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00003630
3631 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00003632 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00003633
3634 Parser.Lex(); // Eat "noat".
3635
Jack Carterd0bd6422013-04-18 00:41:53 +00003636 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003637 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003638 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003639 return false;
3640 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003641
3642 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003643 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003644 return false;
3645}
Jack Carterd0bd6422013-04-18 00:41:53 +00003646
Jack Carter0b744b32012-10-04 02:29:46 +00003647bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00003648 // Line can be: ".set at", which sets $at to $1
3649 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00003650 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00003651 Parser.Lex(); // Eat "at".
3652
Jack Carter0b744b32012-10-04 02:29:46 +00003653 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003654 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00003655 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00003656
3657 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003658 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003659 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00003660 }
3661
3662 if (getLexer().isNot(AsmToken::Equal)) {
3663 reportParseError("unexpected token, expected equals sign");
3664 return false;
3665 }
3666 Parser.Lex(); // Eat "=".
3667
3668 if (getLexer().isNot(AsmToken::Dollar)) {
3669 if (getLexer().is(AsmToken::EndOfStatement)) {
3670 reportParseError("no register specified");
3671 return false;
3672 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00003673 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00003674 return false;
3675 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003676 }
3677 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00003678
Toma Tabacu16a74492015-02-13 10:30:57 +00003679 // Find out what "reg" is.
3680 unsigned AtRegNo;
3681 const AsmToken &Reg = Parser.getTok();
3682 if (Reg.is(AsmToken::Identifier)) {
3683 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
3684 } else if (Reg.is(AsmToken::Integer)) {
3685 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00003686 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00003687 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00003688 return false;
3689 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003690
3691 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00003692 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003693 reportParseError("invalid register");
3694 return false;
3695 }
3696 Parser.Lex(); // Eat "reg".
3697
3698 // If this is not the end of the statement, report an error.
3699 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3700 reportParseError("unexpected token, expected end of statement");
3701 return false;
3702 }
3703
3704 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
3705
3706 Parser.Lex(); // Consume the EndOfStatement.
3707 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003708}
3709
3710bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003711 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003712 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003713 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003714 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003715 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003716 return false;
3717 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003718 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00003719 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003720 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003721 return false;
3722}
3723
3724bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003725 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003726 Parser.Lex();
3727 // If this is not the end of the statement, report an error.
3728 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003729 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003730 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003731 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003732 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00003733 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003734 Parser.Lex(); // Consume the EndOfStatement.
3735 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003736}
3737
3738bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003739 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003740 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003741 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003742 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003743 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003744 return false;
3745 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003746 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00003747 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003748 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003749 return false;
3750}
3751
3752bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003753 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003754 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003755 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003756 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003757 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003758 return false;
3759 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003760 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00003761 reportParseError("`noreorder' must be set before `nomacro'");
3762 return false;
3763 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003764 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00003765 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003766 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003767 return false;
3768}
Jack Carterd76b2372013-03-21 21:44:16 +00003769
Daniel Sanders44934432014-08-07 12:03:36 +00003770bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003771 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003772 Parser.Lex();
3773
3774 // If this is not the end of the statement, report an error.
3775 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003776 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003777
3778 setFeatureBits(Mips::FeatureMSA, "msa");
3779 getTargetStreamer().emitDirectiveSetMsa();
3780 return false;
3781}
3782
3783bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003784 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003785 Parser.Lex();
3786
3787 // If this is not the end of the statement, report an error.
3788 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003789 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003790
3791 clearFeatureBits(Mips::FeatureMSA, "msa");
3792 getTargetStreamer().emitDirectiveSetNoMsa();
3793 return false;
3794}
3795
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003796bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003797 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003798 Parser.Lex(); // Eat "nodsp".
3799
3800 // If this is not the end of the statement, report an error.
3801 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3802 reportParseError("unexpected token, expected end of statement");
3803 return false;
3804 }
3805
3806 clearFeatureBits(Mips::FeatureDSP, "dsp");
3807 getTargetStreamer().emitDirectiveSetNoDsp();
3808 return false;
3809}
3810
Toma Tabacucc2502d2014-11-04 17:18:07 +00003811bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003812 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003813 Parser.Lex(); // Eat "mips16".
3814
Jack Carter39536722014-01-22 23:08:42 +00003815 // If this is not the end of the statement, report an error.
3816 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003817 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00003818 return false;
3819 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00003820
3821 setFeatureBits(Mips::FeatureMips16, "mips16");
3822 getTargetStreamer().emitDirectiveSetMips16();
3823 Parser.Lex(); // Consume the EndOfStatement.
3824 return false;
3825}
3826
3827bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003828 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003829 Parser.Lex(); // Eat "nomips16".
3830
3831 // If this is not the end of the statement, report an error.
3832 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3833 reportParseError("unexpected token, expected end of statement");
3834 return false;
3835 }
3836
3837 clearFeatureBits(Mips::FeatureMips16, "mips16");
3838 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00003839 Parser.Lex(); // Consume the EndOfStatement.
3840 return false;
3841}
3842
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003843bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003844 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003845 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003846 // Line can be: .set fp=32
3847 // .set fp=xx
3848 // .set fp=64
3849 Parser.Lex(); // Eat fp token
3850 AsmToken Tok = Parser.getTok();
3851 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003852 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003853 return false;
3854 }
3855 Parser.Lex(); // Eat '=' token.
3856 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003857
3858 if (!parseFpABIValue(FpAbiVal, ".set"))
3859 return false;
3860
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003861 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003862 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003863 return false;
3864 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003865 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003866 Parser.Lex(); // Consume the EndOfStatement.
3867 return false;
3868}
3869
Toma Tabacu9db22db2014-09-09 10:15:38 +00003870bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003871 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003872 SMLoc Loc = getLexer().getLoc();
3873
3874 Parser.Lex();
3875 if (getLexer().isNot(AsmToken::EndOfStatement))
3876 return reportParseError("unexpected token, expected end of statement");
3877
3878 // Always keep an element on the options "stack" to prevent the user
3879 // from changing the initial options. This is how we remember them.
3880 if (AssemblerOptions.size() == 2)
3881 return reportParseError(Loc, ".set pop with no .set push");
3882
3883 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00003884 setAvailableFeatures(
3885 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
3886 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00003887
3888 getTargetStreamer().emitDirectiveSetPop();
3889 return false;
3890}
3891
3892bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003893 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003894 Parser.Lex();
3895 if (getLexer().isNot(AsmToken::EndOfStatement))
3896 return reportParseError("unexpected token, expected end of statement");
3897
3898 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00003899 AssemblerOptions.push_back(
3900 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00003901
3902 getTargetStreamer().emitDirectiveSetPush();
3903 return false;
3904}
3905
Toma Tabacu29696502015-06-02 09:48:04 +00003906bool MipsAsmParser::parseSetSoftFloatDirective() {
3907 MCAsmParser &Parser = getParser();
3908 Parser.Lex();
3909 if (getLexer().isNot(AsmToken::EndOfStatement))
3910 return reportParseError("unexpected token, expected end of statement");
3911
3912 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
3913 getTargetStreamer().emitDirectiveSetSoftFloat();
3914 return false;
3915}
3916
3917bool MipsAsmParser::parseSetHardFloatDirective() {
3918 MCAsmParser &Parser = getParser();
3919 Parser.Lex();
3920 if (getLexer().isNot(AsmToken::EndOfStatement))
3921 return reportParseError("unexpected token, expected end of statement");
3922
3923 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
3924 getTargetStreamer().emitDirectiveSetHardFloat();
3925 return false;
3926}
3927
Jack Carterd76b2372013-03-21 21:44:16 +00003928bool MipsAsmParser::parseSetAssignment() {
3929 StringRef Name;
3930 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00003931 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00003932
3933 if (Parser.parseIdentifier(Name))
3934 reportParseError("expected identifier after .set");
3935
3936 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003937 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00003938 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00003939
Jack Carter3b2c96e2014-01-22 23:31:38 +00003940 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00003941 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00003942
Jim Grosbach6f482002015-05-18 18:43:14 +00003943 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00003944 Sym->setVariableValue(Value);
3945
3946 return false;
3947}
Jack Carterd0bd6422013-04-18 00:41:53 +00003948
Toma Tabacu26647792014-09-09 12:52:14 +00003949bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003950 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00003951 Parser.Lex();
3952 if (getLexer().isNot(AsmToken::EndOfStatement))
3953 return reportParseError("unexpected token, expected end of statement");
3954
3955 // Reset assembler options to their initial values.
Toma Tabacu465acfd2015-06-09 13:33:26 +00003956 setAvailableFeatures(
3957 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
3958 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00003959 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
3960
3961 getTargetStreamer().emitDirectiveSetMips0();
3962 return false;
3963}
3964
Toma Tabacu85618b32014-08-19 14:22:52 +00003965bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003966 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00003967 Parser.Lex();
3968 if (getLexer().isNot(AsmToken::Equal))
3969 return reportParseError("unexpected token, expected equals sign");
3970
3971 Parser.Lex();
3972 StringRef Arch;
3973 if (Parser.parseIdentifier(Arch))
3974 return reportParseError("expected arch identifier");
3975
3976 StringRef ArchFeatureName =
3977 StringSwitch<StringRef>(Arch)
3978 .Case("mips1", "mips1")
3979 .Case("mips2", "mips2")
3980 .Case("mips3", "mips3")
3981 .Case("mips4", "mips4")
3982 .Case("mips5", "mips5")
3983 .Case("mips32", "mips32")
3984 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003985 .Case("mips32r3", "mips32r3")
3986 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003987 .Case("mips32r6", "mips32r6")
3988 .Case("mips64", "mips64")
3989 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003990 .Case("mips64r3", "mips64r3")
3991 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003992 .Case("mips64r6", "mips64r6")
3993 .Case("cnmips", "cnmips")
3994 .Case("r4000", "mips3") // This is an implementation of Mips3.
3995 .Default("");
3996
3997 if (ArchFeatureName.empty())
3998 return reportParseError("unsupported architecture");
3999
4000 selectArch(ArchFeatureName);
4001 getTargetStreamer().emitDirectiveSetArch(Arch);
4002 return false;
4003}
4004
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004005bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004006 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004007 Parser.Lex();
4008 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004009 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004010
Matheus Almeida2852af82014-04-22 10:15:54 +00004011 switch (Feature) {
4012 default:
4013 llvm_unreachable("Unimplemented feature");
4014 case Mips::FeatureDSP:
4015 setFeatureBits(Mips::FeatureDSP, "dsp");
4016 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004017 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004018 case Mips::FeatureMicroMips:
4019 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004020 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004021 case Mips::FeatureMips1:
4022 selectArch("mips1");
4023 getTargetStreamer().emitDirectiveSetMips1();
4024 break;
4025 case Mips::FeatureMips2:
4026 selectArch("mips2");
4027 getTargetStreamer().emitDirectiveSetMips2();
4028 break;
4029 case Mips::FeatureMips3:
4030 selectArch("mips3");
4031 getTargetStreamer().emitDirectiveSetMips3();
4032 break;
4033 case Mips::FeatureMips4:
4034 selectArch("mips4");
4035 getTargetStreamer().emitDirectiveSetMips4();
4036 break;
4037 case Mips::FeatureMips5:
4038 selectArch("mips5");
4039 getTargetStreamer().emitDirectiveSetMips5();
4040 break;
4041 case Mips::FeatureMips32:
4042 selectArch("mips32");
4043 getTargetStreamer().emitDirectiveSetMips32();
4044 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004045 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004046 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004047 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004048 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004049 case Mips::FeatureMips32r3:
4050 selectArch("mips32r3");
4051 getTargetStreamer().emitDirectiveSetMips32R3();
4052 break;
4053 case Mips::FeatureMips32r5:
4054 selectArch("mips32r5");
4055 getTargetStreamer().emitDirectiveSetMips32R5();
4056 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004057 case Mips::FeatureMips32r6:
4058 selectArch("mips32r6");
4059 getTargetStreamer().emitDirectiveSetMips32R6();
4060 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004061 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004062 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00004063 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00004064 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004065 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004066 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004067 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00004068 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004069 case Mips::FeatureMips64r3:
4070 selectArch("mips64r3");
4071 getTargetStreamer().emitDirectiveSetMips64R3();
4072 break;
4073 case Mips::FeatureMips64r5:
4074 selectArch("mips64r5");
4075 getTargetStreamer().emitDirectiveSetMips64R5();
4076 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004077 case Mips::FeatureMips64r6:
4078 selectArch("mips64r6");
4079 getTargetStreamer().emitDirectiveSetMips64R6();
4080 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004081 }
4082 return false;
4083}
4084
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004085bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004086 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004087 if (getLexer().isNot(AsmToken::Comma)) {
4088 SMLoc Loc = getLexer().getLoc();
4089 Parser.eatToEndOfStatement();
4090 return Error(Loc, ErrorStr);
4091 }
4092
Matheus Almeida2852af82014-04-22 10:15:54 +00004093 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004094 return true;
4095}
4096
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004097bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00004098 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00004099 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004100
Toma Tabacudde4c462014-11-06 10:02:45 +00004101 if (inMips16Mode()) {
4102 reportParseError(".cpload is not supported in Mips16 mode");
4103 return false;
4104 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004105
David Blaikie960ea3f2014-06-08 16:18:35 +00004106 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00004107 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004108 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4109 reportParseError("expected register containing function address");
4110 return false;
4111 }
4112
David Blaikie960ea3f2014-06-08 16:18:35 +00004113 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
4114 if (!RegOpnd.isGPRAsmReg()) {
4115 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004116 return false;
4117 }
4118
Toma Tabacudde4c462014-11-06 10:02:45 +00004119 // If this is not the end of the statement, report an error.
4120 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4121 reportParseError("unexpected token, expected end of statement");
4122 return false;
4123 }
4124
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004125 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004126 return false;
4127}
4128
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004129bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004130 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004131 unsigned FuncReg;
4132 unsigned Save;
4133 bool SaveIsReg = true;
4134
Matheus Almeida7e815762014-06-18 13:08:59 +00004135 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004136 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00004137 if (ResTy == MatchOperand_NoMatch) {
4138 reportParseError("expected register containing function address");
4139 Parser.eatToEndOfStatement();
4140 return false;
4141 }
4142
4143 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4144 if (!FuncRegOpnd.isGPRAsmReg()) {
4145 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
4146 Parser.eatToEndOfStatement();
4147 return false;
4148 }
4149
4150 FuncReg = FuncRegOpnd.getGPR32Reg();
4151 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004152
Toma Tabacu65f10572014-09-16 15:00:52 +00004153 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004154 return true;
4155
Toma Tabacu13964452014-09-04 13:23:44 +00004156 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00004157 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004158 const AsmToken &Tok = Parser.getTok();
4159 if (Tok.is(AsmToken::Integer)) {
4160 Save = Tok.getIntVal();
4161 SaveIsReg = false;
4162 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00004163 } else {
4164 reportParseError("expected save register or stack offset");
4165 Parser.eatToEndOfStatement();
4166 return false;
4167 }
4168 } else {
4169 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4170 if (!SaveOpnd.isGPRAsmReg()) {
4171 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
4172 Parser.eatToEndOfStatement();
4173 return false;
4174 }
4175 Save = SaveOpnd.getGPR32Reg();
4176 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004177
Toma Tabacu65f10572014-09-16 15:00:52 +00004178 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004179 return true;
4180
Toma Tabacu8874eac2015-02-18 13:46:53 +00004181 const MCExpr *Expr;
4182 if (Parser.parseExpression(Expr)) {
4183 reportParseError("expected expression");
4184 return false;
4185 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004186
Toma Tabacu8874eac2015-02-18 13:46:53 +00004187 if (Expr->getKind() != MCExpr::SymbolRef) {
4188 reportParseError("expected symbol");
4189 return false;
4190 }
4191 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
4192
4193 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
4194 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004195 return false;
4196}
4197
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004198bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004199 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004200 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4201 const AsmToken &Tok = Parser.getTok();
4202
4203 if (Tok.getString() == "2008") {
4204 Parser.Lex();
4205 getTargetStreamer().emitDirectiveNaN2008();
4206 return false;
4207 } else if (Tok.getString() == "legacy") {
4208 Parser.Lex();
4209 getTargetStreamer().emitDirectiveNaNLegacy();
4210 return false;
4211 }
4212 }
4213 // If we don't recognize the option passed to the .nan
4214 // directive (e.g. no option or unknown option), emit an error.
4215 reportParseError("invalid option in .nan directive");
4216 return false;
4217}
4218
Jack Carter0b744b32012-10-04 02:29:46 +00004219bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004220 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004221 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00004222 const AsmToken &Tok = Parser.getTok();
4223
4224 if (Tok.getString() == "noat") {
4225 return parseSetNoAtDirective();
4226 } else if (Tok.getString() == "at") {
4227 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00004228 } else if (Tok.getString() == "arch") {
4229 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004230 } else if (Tok.getString() == "fp") {
4231 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004232 } else if (Tok.getString() == "pop") {
4233 return parseSetPopDirective();
4234 } else if (Tok.getString() == "push") {
4235 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00004236 } else if (Tok.getString() == "reorder") {
4237 return parseSetReorderDirective();
4238 } else if (Tok.getString() == "noreorder") {
4239 return parseSetNoReorderDirective();
4240 } else if (Tok.getString() == "macro") {
4241 return parseSetMacroDirective();
4242 } else if (Tok.getString() == "nomacro") {
4243 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00004244 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00004245 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00004246 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00004247 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00004248 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00004249 getTargetStreamer().emitDirectiveSetNoMicroMips();
4250 Parser.eatToEndOfStatement();
4251 return false;
4252 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004253 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00004254 } else if (Tok.getString() == "mips0") {
4255 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00004256 } else if (Tok.getString() == "mips1") {
4257 return parseSetFeature(Mips::FeatureMips1);
4258 } else if (Tok.getString() == "mips2") {
4259 return parseSetFeature(Mips::FeatureMips2);
4260 } else if (Tok.getString() == "mips3") {
4261 return parseSetFeature(Mips::FeatureMips3);
4262 } else if (Tok.getString() == "mips4") {
4263 return parseSetFeature(Mips::FeatureMips4);
4264 } else if (Tok.getString() == "mips5") {
4265 return parseSetFeature(Mips::FeatureMips5);
4266 } else if (Tok.getString() == "mips32") {
4267 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00004268 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004269 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00004270 } else if (Tok.getString() == "mips32r3") {
4271 return parseSetFeature(Mips::FeatureMips32r3);
4272 } else if (Tok.getString() == "mips32r5") {
4273 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00004274 } else if (Tok.getString() == "mips32r6") {
4275 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00004276 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004277 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00004278 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004279 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00004280 } else if (Tok.getString() == "mips64r3") {
4281 return parseSetFeature(Mips::FeatureMips64r3);
4282 } else if (Tok.getString() == "mips64r5") {
4283 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00004284 } else if (Tok.getString() == "mips64r6") {
4285 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00004286 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004287 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004288 } else if (Tok.getString() == "nodsp") {
4289 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00004290 } else if (Tok.getString() == "msa") {
4291 return parseSetMsaDirective();
4292 } else if (Tok.getString() == "nomsa") {
4293 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00004294 } else if (Tok.getString() == "softfloat") {
4295 return parseSetSoftFloatDirective();
4296 } else if (Tok.getString() == "hardfloat") {
4297 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00004298 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00004299 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00004300 parseSetAssignment();
4301 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004302 }
Jack Carter07c818d2013-01-25 01:31:34 +00004303
Jack Carter0b744b32012-10-04 02:29:46 +00004304 return true;
4305}
4306
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004307/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00004308/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004309bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004310 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004311 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4312 for (;;) {
4313 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004314 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00004315 return true;
4316
4317 getParser().getStreamer().EmitValue(Value, Size);
4318
4319 if (getLexer().is(AsmToken::EndOfStatement))
4320 break;
4321
Jack Carter07c818d2013-01-25 01:31:34 +00004322 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004323 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00004324 Parser.Lex();
4325 }
4326 }
4327
4328 Parser.Lex();
4329 return false;
4330}
4331
Vladimir Medic4c299852013-11-06 11:27:05 +00004332/// parseDirectiveGpWord
4333/// ::= .gpword local_sym
4334bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004335 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004336 const MCExpr *Value;
4337 // EmitGPRel32Value requires an expression, so we are using base class
4338 // method to evaluate the expression.
4339 if (getParser().parseExpression(Value))
4340 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00004341 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00004342
Vladimir Medice10c1122013-11-13 13:18:04 +00004343 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004344 return Error(getLexer().getLoc(),
4345 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00004346 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00004347 return false;
4348}
4349
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004350/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00004351/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004352bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004353 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004354 const MCExpr *Value;
4355 // EmitGPRel64Value requires an expression, so we are using base class
4356 // method to evaluate the expression.
4357 if (getParser().parseExpression(Value))
4358 return true;
4359 getParser().getStreamer().EmitGPRel64Value(Value);
4360
4361 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004362 return Error(getLexer().getLoc(),
4363 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00004364 Parser.Lex(); // Eat EndOfStatement token.
4365 return false;
4366}
4367
Jack Carter0cd3c192014-01-06 23:27:31 +00004368bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004369 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00004370 // Get the option token.
4371 AsmToken Tok = Parser.getTok();
4372 // At the moment only identifiers are supported.
4373 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004374 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00004375 Parser.eatToEndOfStatement();
4376 return false;
4377 }
4378
4379 StringRef Option = Tok.getIdentifier();
4380
4381 if (Option == "pic0") {
4382 getTargetStreamer().emitDirectiveOptionPic0();
4383 Parser.Lex();
4384 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4385 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004386 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004387 Parser.eatToEndOfStatement();
4388 }
4389 return false;
4390 }
4391
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004392 if (Option == "pic2") {
4393 getTargetStreamer().emitDirectiveOptionPic2();
4394 Parser.Lex();
4395 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4396 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004397 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004398 Parser.eatToEndOfStatement();
4399 }
4400 return false;
4401 }
4402
Jack Carter0cd3c192014-01-06 23:27:31 +00004403 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00004404 Warning(Parser.getTok().getLoc(),
4405 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00004406 Parser.eatToEndOfStatement();
4407 return false;
4408}
4409
Toma Tabacu9ca50962015-04-16 09:53:47 +00004410/// parseInsnDirective
4411/// ::= .insn
4412bool MipsAsmParser::parseInsnDirective() {
4413 // If this is not the end of the statement, report an error.
4414 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4415 reportParseError("unexpected token, expected end of statement");
4416 return false;
4417 }
4418
4419 // The actual label marking happens in
4420 // MipsELFStreamer::createPendingLabelRelocs().
4421 getTargetStreamer().emitDirectiveInsn();
4422
4423 getParser().Lex(); // Eat EndOfStatement token.
4424 return false;
4425}
4426
Daniel Sanders7e527422014-07-10 13:38:23 +00004427/// parseDirectiveModule
4428/// ::= .module oddspreg
4429/// ::= .module nooddspreg
4430/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004431bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004432 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004433 MCAsmLexer &Lexer = getLexer();
4434 SMLoc L = Lexer.getLoc();
4435
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004436 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004437 // TODO : get a better message.
4438 reportParseError(".module directive must appear before any code");
4439 return false;
4440 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004441
Toma Tabacuc405c822015-01-23 10:40:19 +00004442 StringRef Option;
4443 if (Parser.parseIdentifier(Option)) {
4444 reportParseError("expected .module option identifier");
4445 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004446 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004447
Toma Tabacuc405c822015-01-23 10:40:19 +00004448 if (Option == "oddspreg") {
4449 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
4450 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4451
4452 // If this is not the end of the statement, report an error.
4453 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4454 reportParseError("unexpected token, expected end of statement");
4455 return false;
4456 }
4457
4458 return false; // parseDirectiveModule has finished successfully.
4459 } else if (Option == "nooddspreg") {
4460 if (!isABI_O32()) {
4461 Error(L, "'.module nooddspreg' requires the O32 ABI");
4462 return false;
4463 }
4464
4465 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
4466 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4467
4468 // If this is not the end of the statement, report an error.
4469 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4470 reportParseError("unexpected token, expected end of statement");
4471 return false;
4472 }
4473
4474 return false; // parseDirectiveModule has finished successfully.
4475 } else if (Option == "fp") {
4476 return parseDirectiveModuleFP();
4477 } else {
4478 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
4479 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004480}
4481
4482/// parseDirectiveModuleFP
4483/// ::= =32
4484/// ::= =xx
4485/// ::= =64
4486bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004487 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004488 MCAsmLexer &Lexer = getLexer();
4489
4490 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004491 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004492 return false;
4493 }
4494 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004495
Daniel Sanders7e527422014-07-10 13:38:23 +00004496 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004497 if (!parseFpABIValue(FpABI, ".module"))
4498 return false;
4499
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004500 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004501 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004502 return false;
4503 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004504
Daniel Sanders7201a3e2014-07-08 10:35:52 +00004505 // Emit appropriate flags.
4506 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00004507 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004508 return false;
4509}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004510
Daniel Sanders7e527422014-07-10 13:38:23 +00004511bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004512 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004513 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004514 MCAsmLexer &Lexer = getLexer();
4515
4516 if (Lexer.is(AsmToken::Identifier)) {
4517 StringRef Value = Parser.getTok().getString();
4518 Parser.Lex();
4519
4520 if (Value != "xx") {
4521 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4522 return false;
4523 }
4524
4525 if (!isABI_O32()) {
4526 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
4527 return false;
4528 }
4529
Daniel Sanders7e527422014-07-10 13:38:23 +00004530 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004531 return true;
4532 }
4533
4534 if (Lexer.is(AsmToken::Integer)) {
4535 unsigned Value = Parser.getTok().getIntVal();
4536 Parser.Lex();
4537
4538 if (Value != 32 && Value != 64) {
4539 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4540 return false;
4541 }
4542
4543 if (Value == 32) {
4544 if (!isABI_O32()) {
4545 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
4546 return false;
4547 }
4548
Daniel Sanders7e527422014-07-10 13:38:23 +00004549 FpABI = MipsABIFlagsSection::FpABIKind::S32;
4550 } else
4551 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004552
Daniel Sanders7e527422014-07-10 13:38:23 +00004553 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004554 }
4555
4556 return false;
4557}
4558
Jack Carter0b744b32012-10-04 02:29:46 +00004559bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004560 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004561 StringRef IDVal = DirectiveID.getString();
4562
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004563 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004564 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00004565 if (IDVal == ".dword") {
4566 parseDataDirective(8, DirectiveID.getLoc());
4567 return false;
4568 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004569 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004570 StringRef SymbolName;
4571
4572 if (Parser.parseIdentifier(SymbolName)) {
4573 reportParseError("expected identifier after .ent");
4574 return false;
4575 }
4576
4577 // There's an undocumented extension that allows an integer to
4578 // follow the name of the procedure which AFAICS is ignored by GAS.
4579 // Example: .ent foo,2
4580 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4581 if (getLexer().isNot(AsmToken::Comma)) {
4582 // Even though we accept this undocumented extension for compatibility
4583 // reasons, the additional integer argument does not actually change
4584 // the behaviour of the '.ent' directive, so we would like to discourage
4585 // its use. We do this by not referring to the extended version in
4586 // error messages which are not directly related to its use.
4587 reportParseError("unexpected token, expected end of statement");
4588 return false;
4589 }
4590 Parser.Lex(); // Eat the comma.
4591 const MCExpr *DummyNumber;
4592 int64_t DummyNumberVal;
4593 // If the user was explicitly trying to use the extended version,
4594 // we still give helpful extension-related error messages.
4595 if (Parser.parseExpression(DummyNumber)) {
4596 reportParseError("expected number after comma");
4597 return false;
4598 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00004599 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004600 reportParseError("expected an absolute expression after comma");
4601 return false;
4602 }
4603 }
4604
4605 // If this is not the end of the statement, report an error.
4606 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4607 reportParseError("unexpected token, expected end of statement");
4608 return false;
4609 }
4610
Jim Grosbach6f482002015-05-18 18:43:14 +00004611 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004612
4613 getTargetStreamer().emitDirectiveEnt(*Sym);
4614 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00004615 return false;
4616 }
4617
Jack Carter07c818d2013-01-25 01:31:34 +00004618 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004619 StringRef SymbolName;
4620
4621 if (Parser.parseIdentifier(SymbolName)) {
4622 reportParseError("expected identifier after .end");
4623 return false;
4624 }
4625
4626 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4627 reportParseError("unexpected token, expected end of statement");
4628 return false;
4629 }
4630
4631 if (CurrentFn == nullptr) {
4632 reportParseError(".end used without .ent");
4633 return false;
4634 }
4635
4636 if ((SymbolName != CurrentFn->getName())) {
4637 reportParseError(".end symbol does not match .ent symbol");
4638 return false;
4639 }
4640
4641 getTargetStreamer().emitDirectiveEnd(SymbolName);
4642 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00004643 return false;
4644 }
4645
Jack Carter07c818d2013-01-25 01:31:34 +00004646 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004647 // .frame $stack_reg, frame_size_in_bytes, $return_reg
4648 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004649 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004650 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4651 reportParseError("expected stack register");
4652 return false;
4653 }
4654
4655 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4656 if (!StackRegOpnd.isGPRAsmReg()) {
4657 reportParseError(StackRegOpnd.getStartLoc(),
4658 "expected general purpose register");
4659 return false;
4660 }
4661 unsigned StackReg = StackRegOpnd.getGPR32Reg();
4662
4663 if (Parser.getTok().is(AsmToken::Comma))
4664 Parser.Lex();
4665 else {
4666 reportParseError("unexpected token, expected comma");
4667 return false;
4668 }
4669
4670 // Parse the frame size.
4671 const MCExpr *FrameSize;
4672 int64_t FrameSizeVal;
4673
4674 if (Parser.parseExpression(FrameSize)) {
4675 reportParseError("expected frame size value");
4676 return false;
4677 }
4678
Jim Grosbach13760bd2015-05-30 01:25:56 +00004679 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004680 reportParseError("frame size not an absolute expression");
4681 return false;
4682 }
4683
4684 if (Parser.getTok().is(AsmToken::Comma))
4685 Parser.Lex();
4686 else {
4687 reportParseError("unexpected token, expected comma");
4688 return false;
4689 }
4690
4691 // Parse the return register.
4692 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00004693 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004694 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4695 reportParseError("expected return register");
4696 return false;
4697 }
4698
4699 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4700 if (!ReturnRegOpnd.isGPRAsmReg()) {
4701 reportParseError(ReturnRegOpnd.getStartLoc(),
4702 "expected general purpose register");
4703 return false;
4704 }
4705
4706 // If this is not the end of the statement, report an error.
4707 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4708 reportParseError("unexpected token, expected end of statement");
4709 return false;
4710 }
4711
4712 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
4713 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00004714 return false;
4715 }
4716
Jack Carter07c818d2013-01-25 01:31:34 +00004717 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00004718 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00004719 }
4720
Daniel Sandersd97a6342014-08-13 10:07:34 +00004721 if (IDVal == ".mask" || IDVal == ".fmask") {
4722 // .mask bitmask, frame_offset
4723 // bitmask: One bit for each register used.
4724 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
4725 // first register is expected to be saved.
4726 // Examples:
4727 // .mask 0x80000000, -4
4728 // .fmask 0x80000000, -4
4729 //
Jack Carterbe332172012-09-07 00:48:02 +00004730
Daniel Sandersd97a6342014-08-13 10:07:34 +00004731 // Parse the bitmask
4732 const MCExpr *BitMask;
4733 int64_t BitMaskVal;
4734
4735 if (Parser.parseExpression(BitMask)) {
4736 reportParseError("expected bitmask value");
4737 return false;
4738 }
4739
Jim Grosbach13760bd2015-05-30 01:25:56 +00004740 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004741 reportParseError("bitmask not an absolute expression");
4742 return false;
4743 }
4744
4745 if (Parser.getTok().is(AsmToken::Comma))
4746 Parser.Lex();
4747 else {
4748 reportParseError("unexpected token, expected comma");
4749 return false;
4750 }
4751
4752 // Parse the frame_offset
4753 const MCExpr *FrameOffset;
4754 int64_t FrameOffsetVal;
4755
4756 if (Parser.parseExpression(FrameOffset)) {
4757 reportParseError("expected frame offset value");
4758 return false;
4759 }
4760
Jim Grosbach13760bd2015-05-30 01:25:56 +00004761 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004762 reportParseError("frame offset not an absolute expression");
4763 return false;
4764 }
4765
4766 // If this is not the end of the statement, report an error.
4767 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4768 reportParseError("unexpected token, expected end of statement");
4769 return false;
4770 }
4771
4772 if (IDVal == ".mask")
4773 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
4774 else
4775 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00004776 return false;
4777 }
4778
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004779 if (IDVal == ".nan")
4780 return parseDirectiveNaN();
4781
Jack Carter07c818d2013-01-25 01:31:34 +00004782 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004783 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00004784 return false;
4785 }
4786
Rafael Espindolab59fb732014-03-28 18:50:26 +00004787 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004788 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004789 return false;
4790 }
4791
Jack Carter07c818d2013-01-25 01:31:34 +00004792 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004793 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00004794 return false;
4795 }
4796
Jack Carter0cd3c192014-01-06 23:27:31 +00004797 if (IDVal == ".option")
4798 return parseDirectiveOption();
4799
4800 if (IDVal == ".abicalls") {
4801 getTargetStreamer().emitDirectiveAbiCalls();
4802 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004803 Error(Parser.getTok().getLoc(),
4804 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004805 // Clear line
4806 Parser.eatToEndOfStatement();
4807 }
4808 return false;
4809 }
4810
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004811 if (IDVal == ".cpsetup")
4812 return parseDirectiveCPSetup();
4813
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004814 if (IDVal == ".module")
4815 return parseDirectiveModule();
4816
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004817 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
4818 return parseInternalDirectiveReallowModule();
4819
Toma Tabacu9ca50962015-04-16 09:53:47 +00004820 if (IDVal == ".insn")
4821 return parseInsnDirective();
4822
Rafael Espindola870c4e92012-01-11 03:56:41 +00004823 return true;
4824}
4825
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004826bool MipsAsmParser::parseInternalDirectiveReallowModule() {
4827 // If this is not the end of the statement, report an error.
4828 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4829 reportParseError("unexpected token, expected end of statement");
4830 return false;
4831 }
4832
4833 getTargetStreamer().reallowModuleDirective();
4834
4835 getParser().Lex(); // Eat EndOfStatement token.
4836 return false;
4837}
4838
Rafael Espindola870c4e92012-01-11 03:56:41 +00004839extern "C" void LLVMInitializeMipsAsmParser() {
4840 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
4841 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
4842 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
4843 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
4844}
Jack Carterb4dbc172012-09-05 23:34:03 +00004845
4846#define GET_REGISTER_MATCHER
4847#define GET_MATCHER_IMPLEMENTATION
4848#include "MipsGenAsmMatcher.inc"