blob: 47aeab4b79d21825b3c0346832cea7ab1fb8b1aa [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"
Daniel Sandersa6994442015-08-18 12:33:54 +000014#include "MipsTargetObjectFile.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000015#include "MipsTargetStreamer.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000016#include "llvm/ADT/APInt.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000017#include "llvm/ADT/SmallVector.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000018#include "llvm/ADT/StringSwitch.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000019#include "llvm/MC/MCContext.h"
20#include "llvm/MC/MCExpr.h"
21#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000022#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000023#include "llvm/MC/MCParser/MCAsmLexer.h"
24#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000025#include "llvm/MC/MCStreamer.h"
26#include "llvm/MC/MCSubtargetInfo.h"
27#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000028#include "llvm/MC/MCTargetAsmParser.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000029#include "llvm/Support/Debug.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000030#include "llvm/Support/MathExtras.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000031#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000032#include "llvm/Support/TargetRegistry.h"
Benjamin Kramer799003b2015-03-23 19:32:43 +000033#include "llvm/Support/raw_ostream.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000034#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000035
36using namespace llvm;
37
Chandler Carruthe96dd892014-04-21 22:55:11 +000038#define DEBUG_TYPE "mips-asm-parser"
39
Joey Gouly0e76fa72013-09-12 10:28:05 +000040namespace llvm {
41class MCInstrInfo;
42}
43
Rafael Espindola870c4e92012-01-11 03:56:41 +000044namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000045class MipsAssemblerOptions {
46public:
Toma Tabacu465acfd2015-06-09 13:33:26 +000047 MipsAssemblerOptions(const FeatureBitset &Features_) :
Toma Tabacu9db22db2014-09-09 10:15:38 +000048 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000049
Toma Tabacu9db22db2014-09-09 10:15:38 +000050 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000051 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000052 Reorder = Opts->isReorder();
53 Macro = Opts->isMacro();
54 Features = Opts->getFeatures();
55 }
56
Toma Tabacub19cf202015-04-27 13:12:59 +000057 unsigned getATRegIndex() const { return ATReg; }
58 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000059 if (Reg > 31)
60 return false;
61
62 ATReg = Reg;
63 return true;
64 }
Jack Carter0b744b32012-10-04 02:29:46 +000065
Toma Tabacu9db22db2014-09-09 10:15:38 +000066 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000067 void setReorder() { Reorder = true; }
68 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000069
Toma Tabacu9db22db2014-09-09 10:15:38 +000070 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000071 void setMacro() { Macro = true; }
72 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000073
Toma Tabacu465acfd2015-06-09 13:33:26 +000074 const FeatureBitset &getFeatures() const { return Features; }
75 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000076
Daniel Sandersf0df2212014-08-04 12:20:00 +000077 // Set of features that are either architecture features or referenced
78 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
79 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
80 // The reason we need this mask is explained in the selectArch function.
81 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +000082 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +000083
Jack Carter0b744b32012-10-04 02:29:46 +000084private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000085 unsigned ATReg;
86 bool Reorder;
87 bool Macro;
Toma Tabacu465acfd2015-06-09 13:33:26 +000088 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +000089};
90}
91
Michael Kupersteindb0712f2015-05-26 10:47:10 +000092const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
93 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
94 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
95 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
96 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
97 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
98 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
99 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
100 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
101};
102
Jack Carter0b744b32012-10-04 02:29:46 +0000103namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +0000104class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000105 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000106 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000107 return static_cast<MipsTargetStreamer &>(TS);
108 }
109
Jack Carterb4dbc172012-09-05 23:34:03 +0000110 MCSubtargetInfo &STI;
Eric Christophera5762812015-01-26 17:33:46 +0000111 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000112 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000113 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
114 // nullptr, which indicates that no function is currently
115 // selected. This usually happens after an '.end func'
116 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000117 bool IsLittleEndian;
Daniel Sandersa6994442015-08-18 12:33:54 +0000118 bool IsPicEnabled;
Jack Carter0b744b32012-10-04 02:29:46 +0000119
Daniel Sandersef638fe2014-10-03 15:37:37 +0000120 // Print a warning along with its fix-it message at the given range.
121 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
122 SMRange Range, bool ShowColors = true);
123
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000124#define GET_ASSEMBLER_HEADER
125#include "MipsGenAsmMatcher.inc"
126
Matheus Almeida595fcab2014-06-11 15:05:56 +0000127 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
128
Chad Rosier49963552012-10-13 00:26:04 +0000129 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000130 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000131 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000132 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000133
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000134 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000135 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000136
Toma Tabacu13964452014-09-04 13:23:44 +0000137 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000138
Toma Tabacu13964452014-09-04 13:23:44 +0000139 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000140
David Blaikie960ea3f2014-06-08 16:18:35 +0000141 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
142 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000143
Craig Topper56c590a2014-04-29 07:58:02 +0000144 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000145
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000146 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
147 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000148 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000149 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000150 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
151 SMLoc S);
152 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
153 OperandMatchResultTy parseImm(OperandVector &Operands);
154 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
155 OperandMatchResultTy parseInvNum(OperandVector &Operands);
156 OperandMatchResultTy parseLSAImm(OperandVector &Operands);
157 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
158 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
159 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000160
David Blaikie960ea3f2014-06-08 16:18:35 +0000161 bool searchSymbolAlias(OperandVector &Operands);
162
Toma Tabacu13964452014-09-04 13:23:44 +0000163 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000164
Jack Carter30a59822012-10-04 04:03:53 +0000165 bool needsExpansion(MCInst &Inst);
166
Matheus Almeida3813d572014-06-19 14:39:14 +0000167 // Expands assembly pseudo instructions.
168 // Returns false on success, true otherwise.
169 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000170 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000171
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000172 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
173 SmallVectorImpl<MCInst> &Instructions);
174
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000175 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000176 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000177 SmallVectorImpl<MCInst> &Instructions);
178
Toma Tabacuf712ede2015-06-17 14:31:51 +0000179 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
180 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
181 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacu674825c2015-06-16 12:16:24 +0000182
Toma Tabacu00e98672015-05-01 12:19:27 +0000183 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000184 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000185
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000186 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
187 const MCOperand &Offset, bool Is32BitAddress,
188 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000189
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000190 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
191 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000192
Jack Carter9e65aa32013-03-22 00:05:30 +0000193 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000194 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
195 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000196
197 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
198 SmallVectorImpl<MCInst> &Instructions);
199
Toma Tabacue1e460d2015-06-11 10:36:10 +0000200 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc,
201 SmallVectorImpl<MCInst> &Instructions);
202
Toma Tabacu1a108322015-06-17 13:20:24 +0000203 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc,
204 SmallVectorImpl<MCInst> &Instructions);
205
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000206 bool expandDiv(MCInst &Inst, SMLoc IDLoc,
207 SmallVectorImpl<MCInst> &Instructions, const bool IsMips64,
208 const bool Signed);
209
Toma Tabacud88d79c2015-06-23 14:39:42 +0000210 bool expandUlhu(MCInst &Inst, SMLoc IDLoc,
211 SmallVectorImpl<MCInst> &Instructions);
212
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000213 bool expandUlw(MCInst &Inst, SMLoc IDLoc,
214 SmallVectorImpl<MCInst> &Instructions);
215
Toma Tabacu234482a2015-03-16 12:03:39 +0000216 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
217 SmallVectorImpl<MCInst> &Instructions);
218
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000219 void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +0000220 bool Is64Bit, SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000221
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000222 bool reportParseError(Twine ErrorMsg);
223 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000224
Jack Carterb5cf5902013-04-17 00:18:04 +0000225 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000226 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000227
Vladimir Medic4c299852013-11-06 11:27:05 +0000228 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000229
230 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000231 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000232 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000233 bool parseSetFeature(uint64_t Feature);
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000234 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000235 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000236 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000237 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000238 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000239 bool parseInsnDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000240
241 bool parseSetAtDirective();
242 bool parseSetNoAtDirective();
243 bool parseSetMacroDirective();
244 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000245 bool parseSetMsaDirective();
246 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000247 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000248 bool parseSetReorderDirective();
249 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000250 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000251 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000252 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000253 bool parseSetOddSPRegDirective();
254 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000255 bool parseSetPopDirective();
256 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000257 bool parseSetSoftFloatDirective();
258 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000259
Jack Carterd76b2372013-03-21 21:44:16 +0000260 bool parseSetAssignment();
261
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000262 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000263 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000264 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000265 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000266 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000267 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
268 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000269
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000270 bool parseInternalDirectiveReallowModule();
271
Jack Carterdc1e35d2012-09-06 20:00:02 +0000272 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000273
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000274 bool eatComma(StringRef ErrorStr);
275
Jack Carter1ac53222013-02-20 23:11:17 +0000276 int matchCPURegisterName(StringRef Symbol);
277
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000278 int matchHWRegsRegisterName(StringRef Symbol);
279
Jack Carter873c7242013-01-12 01:03:14 +0000280 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000281
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000282 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000283
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000284 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000285
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000286 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000287
Jack Carter5dc8ac92013-09-25 23:50:44 +0000288 int matchMSA128RegisterName(StringRef Name);
289
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000290 int matchMSA128CtrlRegisterName(StringRef Name);
291
Jack Carterd0bd6422013-04-18 00:41:53 +0000292 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000293
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000294 unsigned getGPR(int RegNo);
295
Toma Tabacu89a712b2015-04-15 10:48:56 +0000296 /// Returns the internal register number for the current AT. Also checks if
297 /// the current AT is unavailable (set to $0) and gives an error if it is.
298 /// This should be used in pseudo-instruction expansions which need AT.
299 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000300
301 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000302 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000303
304 // Helper function that checks if the value of a vector index is within the
305 // boundaries of accepted values for each RegisterKind
306 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
307 bool validateMSAIndex(int Val, int RegKind);
308
Daniel Sandersf0df2212014-08-04 12:20:00 +0000309 // Selects a new architecture by updating the FeatureBits with the necessary
310 // info including implied dependencies.
311 // Internally, it clears all the feature bits related to *any* architecture
312 // and selects the new one using the ToggleFeature functionality of the
313 // MCSubtargetInfo object that handles implied dependencies. The reason we
314 // clear all the arch related bits manually is because ToggleFeature only
315 // clears the features that imply the feature being cleared and not the
316 // features implied by the feature being cleared. This is easier to see
317 // with an example:
318 // --------------------------------------------------
319 // | Feature | Implies |
320 // | -------------------------------------------------|
321 // | FeatureMips1 | None |
322 // | FeatureMips2 | FeatureMips1 |
323 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
324 // | FeatureMips4 | FeatureMips3 |
325 // | ... | |
326 // --------------------------------------------------
327 //
328 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
329 // FeatureMipsGP64 | FeatureMips1)
330 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
331 void selectArch(StringRef ArchFeature) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000332 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000333 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
334 STI.setFeatureBits(FeatureBits);
335 setAvailableFeatures(
336 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000337 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000338 }
339
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000340 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000341 if (!(STI.getFeatureBits()[Feature])) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000342 setAvailableFeatures(
343 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000344 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000345 }
346 }
347
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000348 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000349 if (STI.getFeatureBits()[Feature]) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000350 setAvailableFeatures(
351 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000352 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000353 }
354 }
355
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000356 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
357 setFeatureBits(Feature, FeatureString);
358 AssemblerOptions.front()->setFeatures(STI.getFeatureBits());
359 }
360
361 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
362 clearFeatureBits(Feature, FeatureString);
363 AssemblerOptions.front()->setFeatures(STI.getFeatureBits());
364 }
365
Rafael Espindola870c4e92012-01-11 03:56:41 +0000366public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000367 enum MipsMatchResultTy {
368 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
369#define GET_OPERAND_DIAGNOSTIC_TYPES
370#include "MipsGenAsmMatcher.inc"
371#undef GET_OPERAND_DIAGNOSTIC_TYPES
372
373 };
374
Joey Gouly0e76fa72013-09-12 10:28:05 +0000375 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000376 const MCInstrInfo &MII, const MCTargetOptions &Options)
Colin LeMahieufe2c8b82015-07-27 21:56:53 +0000377 : MCTargetAsmParser(Options), STI(sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000378 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
379 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000380 MCAsmParserExtension::Initialize(parser);
381
Toma Tabacu11e14a92015-04-21 11:50:52 +0000382 parser.addAliasForDirective(".asciiz", ".asciz");
383
Jack Carterb4dbc172012-09-05 23:34:03 +0000384 // Initialize the set of available features.
385 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000386
Toma Tabacu9db22db2014-09-09 10:15:38 +0000387 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000388 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000389 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000390
Toma Tabacu9db22db2014-09-09 10:15:38 +0000391 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000392 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000393 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000394
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000395 getTargetStreamer().updateABIInfo(*this);
396
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000397 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000398 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000399
400 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000401
Daniel Sandersa6994442015-08-18 12:33:54 +0000402 IsPicEnabled =
403 (getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_);
404
Daniel Sanders50f17232015-09-15 16:17:27 +0000405 Triple TheTriple(sti.getTargetTriple());
406 if ((TheTriple.getArch() == Triple::mips) ||
407 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000408 IsLittleEndian = false;
409 else
410 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000411 }
412
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000413 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
414 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
415
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000416 bool isGP64bit() const { return STI.getFeatureBits()[Mips::FeatureGP64Bit]; }
417 bool isFP64bit() const { return STI.getFeatureBits()[Mips::FeatureFP64Bit]; }
Eric Christophera5762812015-01-26 17:33:46 +0000418 const MipsABIInfo &getABI() const { return ABI; }
419 bool isABI_N32() const { return ABI.IsN32(); }
420 bool isABI_N64() const { return ABI.IsN64(); }
421 bool isABI_O32() const { return ABI.IsO32(); }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000422 bool isABI_FPXX() const { return STI.getFeatureBits()[Mips::FeatureFPXX]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000423
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000424 bool useOddSPReg() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000425 return !(STI.getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000426 }
427
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000428 bool inMicroMipsMode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000429 return STI.getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000430 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000431 bool hasMips1() const { return STI.getFeatureBits()[Mips::FeatureMips1]; }
432 bool hasMips2() const { return STI.getFeatureBits()[Mips::FeatureMips2]; }
433 bool hasMips3() const { return STI.getFeatureBits()[Mips::FeatureMips3]; }
434 bool hasMips4() const { return STI.getFeatureBits()[Mips::FeatureMips4]; }
435 bool hasMips5() const { return STI.getFeatureBits()[Mips::FeatureMips5]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000436 bool hasMips32() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000437 return STI.getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000438 }
439 bool hasMips64() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000440 return STI.getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000441 }
442 bool hasMips32r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000443 return STI.getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000444 }
445 bool hasMips64r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000446 return STI.getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000447 }
Daniel Sanders17793142015-02-18 16:24:50 +0000448 bool hasMips32r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000449 return (STI.getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000450 }
451 bool hasMips64r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000452 return (STI.getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000453 }
454 bool hasMips32r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000455 return (STI.getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000456 }
457 bool hasMips64r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000458 return (STI.getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000459 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000460 bool hasMips32r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000461 return STI.getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000462 }
463 bool hasMips64r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000464 return STI.getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000465 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000466
467 bool hasDSP() const { return STI.getFeatureBits()[Mips::FeatureDSP]; }
468 bool hasDSPR2() const { return STI.getFeatureBits()[Mips::FeatureDSPR2]; }
469 bool hasMSA() const { return STI.getFeatureBits()[Mips::FeatureMSA]; }
Kai Nackee0245392015-01-27 19:11:28 +0000470 bool hasCnMips() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000471 return (STI.getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000472 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000473
Daniel Sandersa6994442015-08-18 12:33:54 +0000474 bool inPicMode() {
475 return IsPicEnabled;
476 }
477
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000478 bool inMips16Mode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000479 return STI.getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000480 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000481
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000482 bool useTraps() const {
483 return STI.getFeatureBits()[Mips::FeatureUseTCCInDIV];
484 }
485
Eric Christophere8ae3e32015-05-07 23:10:21 +0000486 bool useSoftFloat() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000487 return STI.getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000488 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000489
Toma Tabacud9d344b2015-04-27 14:05:04 +0000490 /// Warn if RegIndex is the same as the current AT.
491 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000492
493 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000494
495 bool isLittle() const { return IsLittleEndian; }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000496};
497}
498
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000499namespace {
500
501/// MipsOperand - Instances of this class represent a parsed Mips machine
502/// instruction.
503class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000504public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000505 /// Broad categories of register classes
506 /// The exact class is finalized by the render method.
507 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000508 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000509 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000510 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000511 RegKind_FCC = 4, /// FCC
512 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
513 RegKind_MSACtrl = 16, /// MSA control registers
514 RegKind_COP2 = 32, /// COP2
515 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
516 /// context).
517 RegKind_CCR = 128, /// CCR
518 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000519 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000520 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000521 /// Potentially any (e.g. $1)
522 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
523 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000524 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000525 };
526
527private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000528 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000529 k_Immediate, /// An immediate (possibly involving symbol references)
530 k_Memory, /// Base + Offset Memory Address
531 k_PhysRegister, /// A physical register from the Mips namespace
532 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000533 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000534 k_RegList, /// A physical register list
535 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000536 } Kind;
537
David Blaikie960ea3f2014-06-08 16:18:35 +0000538public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000539 MipsOperand(KindTy K, MipsAsmParser &Parser)
540 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
541
David Blaikie960ea3f2014-06-08 16:18:35 +0000542private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000543 /// For diagnostics, and checking the assembler temporary
544 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000545
Eric Christopher8996c5d2013-03-15 00:42:55 +0000546 struct Token {
547 const char *Data;
548 unsigned Length;
549 };
550
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000551 struct PhysRegOp {
552 unsigned Num; /// Register Number
553 };
554
555 struct RegIdxOp {
556 unsigned Index; /// Index into the register class
557 RegKind Kind; /// Bitfield of the kinds it could possibly be
558 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000559 };
560
561 struct ImmOp {
562 const MCExpr *Val;
563 };
564
565 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000566 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000567 const MCExpr *Off;
568 };
569
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000570 struct RegListOp {
571 SmallVector<unsigned, 10> *List;
572 };
573
Jack Carterb4dbc172012-09-05 23:34:03 +0000574 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000575 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000576 struct PhysRegOp PhysReg;
577 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000578 struct ImmOp Imm;
579 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000580 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000581 };
582
583 SMLoc StartLoc, EndLoc;
584
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000585 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000586 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
587 const MCRegisterInfo *RegInfo,
588 SMLoc S, SMLoc E,
589 MipsAsmParser &Parser) {
590 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000591 Op->RegIdx.Index = Index;
592 Op->RegIdx.RegInfo = RegInfo;
593 Op->RegIdx.Kind = RegKind;
594 Op->StartLoc = S;
595 Op->EndLoc = E;
596 return Op;
597 }
598
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000599public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000600 /// Coerce the register to GPR32 and return the real register for the current
601 /// target.
602 unsigned getGPR32Reg() const {
603 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000604 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000605 unsigned ClassID = Mips::GPR32RegClassID;
606 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000607 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000608
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000609 /// Coerce the register to GPR32 and return the real register for the current
610 /// target.
611 unsigned getGPRMM16Reg() const {
612 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
613 unsigned ClassID = Mips::GPR32RegClassID;
614 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
615 }
616
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000617 /// Coerce the register to GPR64 and return the real register for the current
618 /// target.
619 unsigned getGPR64Reg() const {
620 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
621 unsigned ClassID = Mips::GPR64RegClassID;
622 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000623 }
624
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000625private:
626 /// Coerce the register to AFGR64 and return the real register for the current
627 /// target.
628 unsigned getAFGR64Reg() const {
629 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
630 if (RegIdx.Index % 2 != 0)
631 AsmParser.Warning(StartLoc, "Float register should be even.");
632 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
633 .getRegister(RegIdx.Index / 2);
634 }
635
636 /// Coerce the register to FGR64 and return the real register for the current
637 /// target.
638 unsigned getFGR64Reg() const {
639 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
640 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
641 .getRegister(RegIdx.Index);
642 }
643
644 /// Coerce the register to FGR32 and return the real register for the current
645 /// target.
646 unsigned getFGR32Reg() const {
647 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
648 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
649 .getRegister(RegIdx.Index);
650 }
651
652 /// Coerce the register to FGRH32 and return the real register for the current
653 /// target.
654 unsigned getFGRH32Reg() const {
655 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
656 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
657 .getRegister(RegIdx.Index);
658 }
659
660 /// Coerce the register to FCC and return the real register for the current
661 /// target.
662 unsigned getFCCReg() const {
663 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
664 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
665 .getRegister(RegIdx.Index);
666 }
667
668 /// Coerce the register to MSA128 and return the real register for the current
669 /// target.
670 unsigned getMSA128Reg() const {
671 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
672 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
673 // identical
674 unsigned ClassID = Mips::MSA128BRegClassID;
675 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
676 }
677
678 /// Coerce the register to MSACtrl and return the real register for the
679 /// current target.
680 unsigned getMSACtrlReg() const {
681 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
682 unsigned ClassID = Mips::MSACtrlRegClassID;
683 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
684 }
685
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000686 /// Coerce the register to COP0 and return the real register for the
687 /// current target.
688 unsigned getCOP0Reg() const {
689 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
690 unsigned ClassID = Mips::COP0RegClassID;
691 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
692 }
693
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000694 /// Coerce the register to COP2 and return the real register for the
695 /// current target.
696 unsigned getCOP2Reg() const {
697 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
698 unsigned ClassID = Mips::COP2RegClassID;
699 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
700 }
701
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000702 /// Coerce the register to COP3 and return the real register for the
703 /// current target.
704 unsigned getCOP3Reg() const {
705 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
706 unsigned ClassID = Mips::COP3RegClassID;
707 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
708 }
709
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000710 /// Coerce the register to ACC64DSP and return the real register for the
711 /// current target.
712 unsigned getACC64DSPReg() const {
713 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
714 unsigned ClassID = Mips::ACC64DSPRegClassID;
715 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
716 }
717
718 /// Coerce the register to HI32DSP and return the real register for the
719 /// current target.
720 unsigned getHI32DSPReg() const {
721 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
722 unsigned ClassID = Mips::HI32DSPRegClassID;
723 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
724 }
725
726 /// Coerce the register to LO32DSP and return the real register for the
727 /// current target.
728 unsigned getLO32DSPReg() const {
729 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
730 unsigned ClassID = Mips::LO32DSPRegClassID;
731 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
732 }
733
734 /// Coerce the register to CCR and return the real register for the
735 /// current target.
736 unsigned getCCRReg() const {
737 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
738 unsigned ClassID = Mips::CCRRegClassID;
739 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
740 }
741
742 /// Coerce the register to HWRegs and return the real register for the
743 /// current target.
744 unsigned getHWRegsReg() const {
745 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
746 unsigned ClassID = Mips::HWRegsRegClassID;
747 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
748 }
749
750public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000751 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000752 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000753 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000754 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000755 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000756 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000757 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000758 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000759 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000760
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000761 void addRegOperands(MCInst &Inst, unsigned N) const {
762 llvm_unreachable("Use a custom parser instead");
763 }
764
Daniel Sanders21bce302014-04-01 12:35:23 +0000765 /// Render the operand to an MCInst as a GPR32
766 /// Asserts if the wrong number of operands are requested, or the operand
767 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000768 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
769 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000770 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000771 }
772
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000773 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
774 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000775 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000776 }
777
Jozef Kolek1904fa22014-11-24 14:25:53 +0000778 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
779 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000780 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000781 }
782
Zoran Jovanovic41688672015-02-10 16:36:20 +0000783 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
784 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000785 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000786 }
787
Daniel Sanders21bce302014-04-01 12:35:23 +0000788 /// Render the operand to an MCInst as a GPR64
789 /// Asserts if the wrong number of operands are requested, or the operand
790 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000791 void addGPR64AsmRegOperands(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(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000794 }
795
796 void addAFGR64AsmRegOperands(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(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000799 }
800
801 void addFGR64AsmRegOperands(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(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000804 }
805
806 void addFGR32AsmRegOperands(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(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000809 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000810 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000811 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
812 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000813 }
814
815 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
816 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000817 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000818 }
819
820 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
821 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000822 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000823 }
824
825 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
826 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000827 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000828 }
829
830 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
831 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000832 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000833 }
834
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000835 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
836 assert(N == 1 && "Invalid number of operands!");
837 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
838 }
839
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000840 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
841 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000842 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000843 }
844
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000845 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
846 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000847 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000848 }
849
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000850 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
851 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000852 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000853 }
854
855 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
856 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000857 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000858 }
859
860 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
861 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000862 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000863 }
864
865 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
866 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000867 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000868 }
869
870 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
871 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000872 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000873 }
874
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000875 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000876 assert(N == 1 && "Invalid number of operands!");
877 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000878 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000879 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000880
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000881 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000882 assert(N == 2 && "Invalid number of operands!");
883
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000884 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
885 ? getMemBase()->getGPR64Reg()
886 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000887
888 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000889 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000890 }
891
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000892 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
893 assert(N == 2 && "Invalid number of operands!");
894
Jim Grosbache9119e42015-05-13 18:37:00 +0000895 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000896
897 const MCExpr *Expr = getMemOff();
898 addExpr(Inst, Expr);
899 }
900
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000901 void addRegListOperands(MCInst &Inst, unsigned N) const {
902 assert(N == 1 && "Invalid number of operands!");
903
904 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000905 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000906 }
907
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000908 void addRegPairOperands(MCInst &Inst, unsigned N) const {
909 assert(N == 2 && "Invalid number of operands!");
910 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +0000911 Inst.addOperand(MCOperand::createReg(RegNo++));
912 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000913 }
914
Zoran Jovanovic41688672015-02-10 16:36:20 +0000915 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
916 assert(N == 2 && "Invalid number of operands!");
917 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000918 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000919 }
920
Craig Topper56c590a2014-04-29 07:58:02 +0000921 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000922 // As a special case until we sort out the definition of div/divu, pretend
923 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
924 if (isGPRAsmReg() && RegIdx.Index == 0)
925 return true;
926
927 return Kind == k_PhysRegister;
928 }
929 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000930 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000931 bool isConstantImm() const {
932 return isImm() && dyn_cast<MCConstantExpr>(getImm());
933 }
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +0000934 template <unsigned Bits> bool isUImm() const {
935 return isImm() && isConstantImm() && isUInt<Bits>(getConstantImm());
936 }
Craig Topper56c590a2014-04-29 07:58:02 +0000937 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000938 // Note: It's not possible to pretend that other operand kinds are tokens.
939 // The matcher emitter checks tokens first.
940 return Kind == k_Token;
941 }
Craig Topper56c590a2014-04-29 07:58:02 +0000942 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000943 bool isConstantMemOff() const {
944 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
945 }
946 template <unsigned Bits> bool isMemWithSimmOffset() const {
Zoran Jovanovica6593ff2015-08-18 12:53:08 +0000947 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
948 && getMemBase()->isGPRAsmReg();
949 }
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +0000950 template <unsigned Bits> bool isMemWithSimmOffsetGPR() const {
951 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) &&
952 getMemBase()->isGPRAsmReg();
953 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000954 bool isMemWithGRPMM16Base() const {
955 return isMem() && getMemBase()->isMM16AsmReg();
956 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000957 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
958 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
959 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
960 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000961 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
962 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
963 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
964 && (getMemBase()->getGPR32Reg() == Mips::SP);
965 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000966 bool isRegList16() const {
967 if (!isRegList())
968 return false;
969
970 int Size = RegList.List->size();
971 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
972 RegList.List->back() != Mips::RA)
973 return false;
974
975 int PrevReg = *RegList.List->begin();
976 for (int i = 1; i < Size - 1; i++) {
977 int Reg = (*(RegList.List))[i];
978 if ( Reg != PrevReg + 1)
979 return false;
980 PrevReg = Reg;
981 }
982
983 return true;
984 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000985 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000986 bool isLSAImm() const {
987 if (!isConstantImm())
988 return false;
989 int64_t Val = getConstantImm();
990 return 1 <= Val && Val <= 4;
991 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000992 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +0000993 bool isMovePRegPair() const {
994 if (Kind != k_RegList || RegList.List->size() != 2)
995 return false;
996
997 unsigned R0 = RegList.List->front();
998 unsigned R1 = RegList.List->back();
999
1000 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1001 (R0 == Mips::A1 && R1 == Mips::A3) ||
1002 (R0 == Mips::A2 && R1 == Mips::A3) ||
1003 (R0 == Mips::A0 && R1 == Mips::S5) ||
1004 (R0 == Mips::A0 && R1 == Mips::S6) ||
1005 (R0 == Mips::A0 && R1 == Mips::A1) ||
1006 (R0 == Mips::A0 && R1 == Mips::A2) ||
1007 (R0 == Mips::A0 && R1 == Mips::A3))
1008 return true;
1009
1010 return false;
1011 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001012
1013 StringRef getToken() const {
1014 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001015 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001016 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001017 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001018
Craig Topper56c590a2014-04-29 07:58:02 +00001019 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001020 // As a special case until we sort out the definition of div/divu, pretend
1021 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1022 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1023 RegIdx.Kind & RegKind_GPR)
1024 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001025
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001026 assert(Kind == k_PhysRegister && "Invalid access!");
1027 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001028 }
1029
Jack Carterb4dbc172012-09-05 23:34:03 +00001030 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001031 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001032 return Imm.Val;
1033 }
1034
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001035 int64_t getConstantImm() const {
1036 const MCExpr *Val = getImm();
1037 return static_cast<const MCConstantExpr *>(Val)->getValue();
1038 }
1039
1040 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001041 assert((Kind == k_Memory) && "Invalid access!");
1042 return Mem.Base;
1043 }
1044
1045 const MCExpr *getMemOff() const {
1046 assert((Kind == k_Memory) && "Invalid access!");
1047 return Mem.Off;
1048 }
1049
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001050 int64_t getConstantMemOff() const {
1051 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1052 }
1053
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001054 const SmallVectorImpl<unsigned> &getRegList() const {
1055 assert((Kind == k_RegList) && "Invalid access!");
1056 return *(RegList.List);
1057 }
1058
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001059 unsigned getRegPair() const {
1060 assert((Kind == k_RegPair) && "Invalid access!");
1061 return RegIdx.Index;
1062 }
1063
David Blaikie960ea3f2014-06-08 16:18:35 +00001064 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1065 MipsAsmParser &Parser) {
1066 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001067 Op->Tok.Data = Str.data();
1068 Op->Tok.Length = Str.size();
1069 Op->StartLoc = S;
1070 Op->EndLoc = S;
1071 return Op;
1072 }
1073
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001074 /// Create a numeric register (e.g. $1). The exact register remains
1075 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001076 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001077 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001078 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001079 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001080 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001081 }
1082
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001083 /// Create a register that is definitely a GPR.
1084 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001085 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001086 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001087 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001088 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001089 }
1090
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001091 /// Create a register that is definitely a FGR.
1092 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001093 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001094 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001095 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001096 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1097 }
1098
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001099 /// Create a register that is definitely a HWReg.
1100 /// This is typically only used for named registers such as $hwr_cpunum.
1101 static std::unique_ptr<MipsOperand>
1102 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1103 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1104 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1105 }
1106
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001107 /// Create a register that is definitely an FCC.
1108 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001109 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001110 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001111 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001112 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1113 }
1114
1115 /// Create a register that is definitely an ACC.
1116 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001117 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001118 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001119 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001120 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1121 }
1122
1123 /// Create a register that is definitely an MSA128.
1124 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001125 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001126 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001127 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001128 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1129 }
1130
1131 /// Create a register that is definitely an MSACtrl.
1132 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001133 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001134 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001135 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001136 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1137 }
1138
David Blaikie960ea3f2014-06-08 16:18:35 +00001139 static std::unique_ptr<MipsOperand>
1140 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1141 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001142 Op->Imm.Val = Val;
1143 Op->StartLoc = S;
1144 Op->EndLoc = E;
1145 return Op;
1146 }
1147
David Blaikie960ea3f2014-06-08 16:18:35 +00001148 static std::unique_ptr<MipsOperand>
1149 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1150 SMLoc E, MipsAsmParser &Parser) {
1151 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1152 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001153 Op->Mem.Off = Off;
1154 Op->StartLoc = S;
1155 Op->EndLoc = E;
1156 return Op;
1157 }
1158
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001159 static std::unique_ptr<MipsOperand>
1160 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1161 MipsAsmParser &Parser) {
1162 assert (Regs.size() > 0 && "Empty list not allowed");
1163
1164 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001165 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001166 Op->StartLoc = StartLoc;
1167 Op->EndLoc = EndLoc;
1168 return Op;
1169 }
1170
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001171 static std::unique_ptr<MipsOperand>
1172 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1173 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1174 Op->RegIdx.Index = RegNo;
1175 Op->StartLoc = S;
1176 Op->EndLoc = E;
1177 return Op;
1178 }
1179
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001180 bool isGPRAsmReg() const {
1181 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001182 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001183 bool isMM16AsmReg() const {
1184 if (!(isRegIdx() && RegIdx.Kind))
1185 return false;
1186 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1187 || RegIdx.Index == 16 || RegIdx.Index == 17);
1188 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001189 bool isMM16AsmRegZero() const {
1190 if (!(isRegIdx() && RegIdx.Kind))
1191 return false;
1192 return (RegIdx.Index == 0 ||
1193 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1194 RegIdx.Index == 17);
1195 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001196 bool isMM16AsmRegMoveP() const {
1197 if (!(isRegIdx() && RegIdx.Kind))
1198 return false;
1199 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1200 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1201 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001202 bool isFGRAsmReg() const {
1203 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1204 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001205 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001206 bool isHWRegsAsmReg() const {
1207 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001208 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001209 bool isCCRAsmReg() const {
1210 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001211 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001212 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001213 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1214 return false;
1215 if (!AsmParser.hasEightFccRegisters())
1216 return RegIdx.Index == 0;
1217 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001218 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001219 bool isACCAsmReg() const {
1220 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001221 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001222 bool isCOP0AsmReg() const {
1223 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1224 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001225 bool isCOP2AsmReg() const {
1226 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001227 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001228 bool isCOP3AsmReg() const {
1229 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1230 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001231 bool isMSA128AsmReg() const {
1232 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001233 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001234 bool isMSACtrlAsmReg() const {
1235 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001236 }
1237
Jack Carterb4dbc172012-09-05 23:34:03 +00001238 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001239 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001240 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001241 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001242
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001243 virtual ~MipsOperand() {
1244 switch (Kind) {
1245 case k_Immediate:
1246 break;
1247 case k_Memory:
1248 delete Mem.Base;
1249 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001250 case k_RegList:
1251 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001252 case k_PhysRegister:
1253 case k_RegisterIndex:
1254 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001255 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001256 break;
1257 }
1258 }
1259
Craig Topper56c590a2014-04-29 07:58:02 +00001260 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001261 switch (Kind) {
1262 case k_Immediate:
1263 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001264 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001265 OS << ">";
1266 break;
1267 case k_Memory:
1268 OS << "Mem<";
1269 Mem.Base->print(OS);
1270 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001271 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001272 OS << ">";
1273 break;
1274 case k_PhysRegister:
1275 OS << "PhysReg<" << PhysReg.Num << ">";
1276 break;
1277 case k_RegisterIndex:
1278 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1279 break;
1280 case k_Token:
1281 OS << Tok.Data;
1282 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001283 case k_RegList:
1284 OS << "RegList< ";
1285 for (auto Reg : (*RegList.List))
1286 OS << Reg << " ";
1287 OS << ">";
1288 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001289 case k_RegPair:
1290 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1291 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001292 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001293 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001294}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001295} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001296
Jack Carter9e65aa32013-03-22 00:05:30 +00001297namespace llvm {
1298extern const MCInstrDesc MipsInsts[];
1299}
1300static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1301 return MipsInsts[Opcode];
1302}
1303
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001304static bool hasShortDelaySlot(unsigned Opcode) {
1305 switch (Opcode) {
1306 case Mips::JALS_MM:
1307 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001308 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001309 case Mips::BGEZALS_MM:
1310 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001311 return true;
1312 default:
1313 return false;
1314 }
1315}
1316
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001317static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1318 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1319 return &SRExpr->getSymbol();
1320 }
1321
1322 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1323 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1324 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1325
1326 if (LHSSym)
1327 return LHSSym;
1328
1329 if (RHSSym)
1330 return RHSSym;
1331
1332 return nullptr;
1333 }
1334
1335 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1336 return getSingleMCSymbol(UExpr->getSubExpr());
1337
1338 return nullptr;
1339}
1340
1341static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1342 if (isa<MCSymbolRefExpr>(Expr))
1343 return 1;
1344
1345 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1346 return countMCSymbolRefExpr(BExpr->getLHS()) +
1347 countMCSymbolRefExpr(BExpr->getRHS());
1348
1349 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1350 return countMCSymbolRefExpr(UExpr->getSubExpr());
1351
1352 return 0;
1353}
1354
Jack Carter9e65aa32013-03-22 00:05:30 +00001355bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001356 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001357 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001358
Jack Carter9e65aa32013-03-22 00:05:30 +00001359 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001360
1361 if (MCID.isBranch() || MCID.isCall()) {
1362 const unsigned Opcode = Inst.getOpcode();
1363 MCOperand Offset;
1364
1365 switch (Opcode) {
1366 default:
1367 break;
Kai Nackee0245392015-01-27 19:11:28 +00001368 case Mips::BBIT0:
1369 case Mips::BBIT032:
1370 case Mips::BBIT1:
1371 case Mips::BBIT132:
1372 assert(hasCnMips() && "instruction only valid for octeon cpus");
1373 // Fall through
1374
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001375 case Mips::BEQ:
1376 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001377 case Mips::BEQ_MM:
1378 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001379 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001380 Offset = Inst.getOperand(2);
1381 if (!Offset.isImm())
1382 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001383 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001384 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001385 if (OffsetToAlignment(Offset.getImm(),
1386 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001387 return Error(IDLoc, "branch to misaligned address");
1388 break;
1389 case Mips::BGEZ:
1390 case Mips::BGTZ:
1391 case Mips::BLEZ:
1392 case Mips::BLTZ:
1393 case Mips::BGEZAL:
1394 case Mips::BLTZAL:
1395 case Mips::BC1F:
1396 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001397 case Mips::BGEZ_MM:
1398 case Mips::BGTZ_MM:
1399 case Mips::BLEZ_MM:
1400 case Mips::BLTZ_MM:
1401 case Mips::BGEZAL_MM:
1402 case Mips::BLTZAL_MM:
1403 case Mips::BC1F_MM:
1404 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001405 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001406 Offset = Inst.getOperand(1);
1407 if (!Offset.isImm())
1408 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001409 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001410 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001411 if (OffsetToAlignment(Offset.getImm(),
1412 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001413 return Error(IDLoc, "branch to misaligned address");
1414 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001415 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001416 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001417 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001418 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001419 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1420 Offset = Inst.getOperand(1);
1421 if (!Offset.isImm())
1422 break; // We'll deal with this situation later on when applying fixups.
1423 if (!isIntN(8, Offset.getImm()))
1424 return Error(IDLoc, "branch target out of range");
1425 if (OffsetToAlignment(Offset.getImm(), 2LL))
1426 return Error(IDLoc, "branch to misaligned address");
1427 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001428 }
1429 }
1430
Daniel Sandersa84989a2014-06-16 13:25:35 +00001431 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1432 // We still accept it but it is a normal nop.
1433 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1434 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1435 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1436 "nop instruction");
1437 }
1438
Kai Nackee0245392015-01-27 19:11:28 +00001439 if (hasCnMips()) {
1440 const unsigned Opcode = Inst.getOpcode();
1441 MCOperand Opnd;
1442 int Imm;
1443
1444 switch (Opcode) {
1445 default:
1446 break;
1447
1448 case Mips::BBIT0:
1449 case Mips::BBIT032:
1450 case Mips::BBIT1:
1451 case Mips::BBIT132:
1452 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1453 // The offset is handled above
1454 Opnd = Inst.getOperand(1);
1455 if (!Opnd.isImm())
1456 return Error(IDLoc, "expected immediate operand kind");
1457 Imm = Opnd.getImm();
1458 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1459 Opcode == Mips::BBIT1 ? 63 : 31))
1460 return Error(IDLoc, "immediate operand value out of range");
1461 if (Imm > 31) {
1462 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1463 : Mips::BBIT132);
1464 Inst.getOperand(1).setImm(Imm - 32);
1465 }
1466 break;
1467
1468 case Mips::CINS:
1469 case Mips::CINS32:
1470 case Mips::EXTS:
1471 case Mips::EXTS32:
1472 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1473 // Check length
1474 Opnd = Inst.getOperand(3);
1475 if (!Opnd.isImm())
1476 return Error(IDLoc, "expected immediate operand kind");
1477 Imm = Opnd.getImm();
1478 if (Imm < 0 || Imm > 31)
1479 return Error(IDLoc, "immediate operand value out of range");
1480 // Check position
1481 Opnd = Inst.getOperand(2);
1482 if (!Opnd.isImm())
1483 return Error(IDLoc, "expected immediate operand kind");
1484 Imm = Opnd.getImm();
1485 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1486 Opcode == Mips::EXTS ? 63 : 31))
1487 return Error(IDLoc, "immediate operand value out of range");
1488 if (Imm > 31) {
1489 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1490 Inst.getOperand(2).setImm(Imm - 32);
1491 }
1492 break;
1493
1494 case Mips::SEQi:
1495 case Mips::SNEi:
1496 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1497 Opnd = Inst.getOperand(2);
1498 if (!Opnd.isImm())
1499 return Error(IDLoc, "expected immediate operand kind");
1500 Imm = Opnd.getImm();
1501 if (!isInt<10>(Imm))
1502 return Error(IDLoc, "immediate operand value out of range");
1503 break;
1504 }
1505 }
1506
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001507 // This expansion is not in a function called by expandInstruction() because
1508 // the pseudo-instruction doesn't have a distinct opcode.
1509 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1510 inPicMode()) {
1511 warnIfNoMacro(IDLoc);
1512
1513 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1514
1515 // We can do this expansion if there's only 1 symbol in the argument
1516 // expression.
1517 if (countMCSymbolRefExpr(JalExpr) > 1)
1518 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1519
1520 // FIXME: This is checking the expression can be handled by the later stages
1521 // of the assembler. We ought to leave it to those later stages but
1522 // we can't do that until we stop evaluateRelocExpr() rewriting the
1523 // expressions into non-equivalent forms.
1524 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1525
1526 // FIXME: Add support for label+offset operands (currently causes an error).
1527 // FIXME: Add support for forward-declared local symbols.
1528 // FIXME: Add expansion for when the LargeGOT option is enabled.
1529 if (JalSym->isInSection() || JalSym->isTemporary()) {
1530 if (isABI_O32()) {
1531 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001532 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001533 // R_(MICRO)MIPS_GOT16 label
1534 // addiu $25, $25, 0
1535 // R_(MICRO)MIPS_LO16 label
1536 // jalr $25
1537 const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
1538 const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
1539
1540 MCInst LwInst;
1541 LwInst.setOpcode(Mips::LW);
1542 LwInst.addOperand(MCOperand::createReg(Mips::T9));
1543 LwInst.addOperand(MCOperand::createReg(Mips::GP));
1544 LwInst.addOperand(MCOperand::createExpr(Got16RelocExpr));
1545 Instructions.push_back(LwInst);
1546
1547 MCInst AddiuInst;
1548 AddiuInst.setOpcode(Mips::ADDiu);
1549 AddiuInst.addOperand(MCOperand::createReg(Mips::T9));
1550 AddiuInst.addOperand(MCOperand::createReg(Mips::T9));
1551 AddiuInst.addOperand(MCOperand::createExpr(Lo16RelocExpr));
1552 Instructions.push_back(AddiuInst);
1553 } else if (isABI_N32() || isABI_N64()) {
1554 // If it's a local symbol and the N32/N64 ABIs are being used,
1555 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001556 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001557 // R_(MICRO)MIPS_GOT_DISP label
1558 // jalr $25
1559 const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
1560
1561 MCInst LoadInst;
1562 LoadInst.setOpcode(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW);
1563 LoadInst.addOperand(MCOperand::createReg(Mips::T9));
1564 LoadInst.addOperand(MCOperand::createReg(Mips::GP));
1565 LoadInst.addOperand(MCOperand::createExpr(GotDispRelocExpr));
1566 Instructions.push_back(LoadInst);
1567 }
1568 } else {
1569 // If it's an external/weak symbol, we expand to:
1570 // lw/ld $25, 0($gp)
1571 // R_(MICRO)MIPS_CALL16 label
1572 // jalr $25
1573 const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
1574
1575 MCInst LoadInst;
1576 LoadInst.setOpcode(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW);
1577 LoadInst.addOperand(MCOperand::createReg(Mips::T9));
1578 LoadInst.addOperand(MCOperand::createReg(Mips::GP));
1579 LoadInst.addOperand(MCOperand::createExpr(Call16RelocExpr));
1580 Instructions.push_back(LoadInst);
1581 }
1582
1583 MCInst JalrInst;
1584 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
1585 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1586 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1587
1588 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1589 // This relocation is supposed to be an optimization hint for the linker
1590 // and is not necessary for correctness.
1591
1592 Inst = JalrInst;
1593 }
1594
Jack Carter9e65aa32013-03-22 00:05:30 +00001595 if (MCID.mayLoad() || MCID.mayStore()) {
1596 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001597 // reference or immediate we may have to expand instructions.
1598 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001599 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001600 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1601 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001602 MCOperand &Op = Inst.getOperand(i);
1603 if (Op.isImm()) {
1604 int MemOffset = Op.getImm();
1605 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001606 // Offset can't exceed 16bit value.
1607 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001608 return false;
1609 }
1610 } else if (Op.isExpr()) {
1611 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001612 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001613 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001614 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001615 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001616 // Expand symbol.
1617 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001618 return false;
1619 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001620 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001621 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001622 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001623 }
1624 }
1625 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001626 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001627 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001628
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001629 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001630 if (MCID.mayLoad()) {
1631 // Try to create 16-bit GP relative load instruction.
1632 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1633 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1634 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1635 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1636 MCOperand &Op = Inst.getOperand(i);
1637 if (Op.isImm()) {
1638 int MemOffset = Op.getImm();
1639 MCOperand &DstReg = Inst.getOperand(0);
1640 MCOperand &BaseReg = Inst.getOperand(1);
1641 if (isIntN(9, MemOffset) && (MemOffset % 4 == 0) &&
1642 getContext().getRegisterInfo()->getRegClass(
1643 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001644 (BaseReg.getReg() == Mips::GP ||
1645 BaseReg.getReg() == Mips::GP_64)) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001646 MCInst TmpInst;
1647 TmpInst.setLoc(IDLoc);
1648 TmpInst.setOpcode(Mips::LWGP_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00001649 TmpInst.addOperand(MCOperand::createReg(DstReg.getReg()));
1650 TmpInst.addOperand(MCOperand::createReg(Mips::GP));
1651 TmpInst.addOperand(MCOperand::createImm(MemOffset));
Jozef Koleke10a02e2015-01-28 17:27:26 +00001652 Instructions.push_back(TmpInst);
1653 return false;
1654 }
1655 }
1656 }
1657 } // for
1658 } // if load
1659
1660 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1661
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001662 MCOperand Opnd;
1663 int Imm;
1664
1665 switch (Inst.getOpcode()) {
1666 default:
1667 break;
1668 case Mips::ADDIUS5_MM:
1669 Opnd = Inst.getOperand(2);
1670 if (!Opnd.isImm())
1671 return Error(IDLoc, "expected immediate operand kind");
1672 Imm = Opnd.getImm();
1673 if (Imm < -8 || Imm > 7)
1674 return Error(IDLoc, "immediate operand value out of range");
1675 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001676 case Mips::ADDIUSP_MM:
1677 Opnd = Inst.getOperand(0);
1678 if (!Opnd.isImm())
1679 return Error(IDLoc, "expected immediate operand kind");
1680 Imm = Opnd.getImm();
1681 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1682 Imm % 4 != 0)
1683 return Error(IDLoc, "immediate operand value out of range");
1684 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001685 case Mips::SLL16_MM:
1686 case Mips::SRL16_MM:
1687 Opnd = Inst.getOperand(2);
1688 if (!Opnd.isImm())
1689 return Error(IDLoc, "expected immediate operand kind");
1690 Imm = Opnd.getImm();
1691 if (Imm < 1 || Imm > 8)
1692 return Error(IDLoc, "immediate operand value out of range");
1693 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001694 case Mips::LI16_MM:
1695 Opnd = Inst.getOperand(1);
1696 if (!Opnd.isImm())
1697 return Error(IDLoc, "expected immediate operand kind");
1698 Imm = Opnd.getImm();
1699 if (Imm < -1 || Imm > 126)
1700 return Error(IDLoc, "immediate operand value out of range");
1701 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001702 case Mips::ADDIUR2_MM:
1703 Opnd = Inst.getOperand(2);
1704 if (!Opnd.isImm())
1705 return Error(IDLoc, "expected immediate operand kind");
1706 Imm = Opnd.getImm();
1707 if (!(Imm == 1 || Imm == -1 ||
1708 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1709 return Error(IDLoc, "immediate operand value out of range");
1710 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001711 case Mips::ADDIUR1SP_MM:
1712 Opnd = Inst.getOperand(1);
1713 if (!Opnd.isImm())
1714 return Error(IDLoc, "expected immediate operand kind");
1715 Imm = Opnd.getImm();
1716 if (OffsetToAlignment(Imm, 4LL))
1717 return Error(IDLoc, "misaligned immediate operand value");
1718 if (Imm < 0 || Imm > 255)
1719 return Error(IDLoc, "immediate operand value out of range");
1720 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001721 case Mips::ANDI16_MM:
1722 Opnd = Inst.getOperand(2);
1723 if (!Opnd.isImm())
1724 return Error(IDLoc, "expected immediate operand kind");
1725 Imm = Opnd.getImm();
1726 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1727 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1728 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1729 return Error(IDLoc, "immediate operand value out of range");
1730 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001731 case Mips::LBU16_MM:
1732 Opnd = Inst.getOperand(2);
1733 if (!Opnd.isImm())
1734 return Error(IDLoc, "expected immediate operand kind");
1735 Imm = Opnd.getImm();
1736 if (Imm < -1 || Imm > 14)
1737 return Error(IDLoc, "immediate operand value out of range");
1738 break;
Zoran Jovanovic7ba636c2015-09-17 10:14:09 +00001739 case Mips::TEQ_MM:
1740 case Mips::TGE_MM:
1741 case Mips::TGEU_MM:
1742 case Mips::TLT_MM:
1743 case Mips::TLTU_MM:
1744 case Mips::TNE_MM:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001745 case Mips::SB16_MM:
1746 Opnd = Inst.getOperand(2);
1747 if (!Opnd.isImm())
1748 return Error(IDLoc, "expected immediate operand kind");
1749 Imm = Opnd.getImm();
1750 if (Imm < 0 || Imm > 15)
1751 return Error(IDLoc, "immediate operand value out of range");
1752 break;
1753 case Mips::LHU16_MM:
1754 case Mips::SH16_MM:
1755 Opnd = Inst.getOperand(2);
1756 if (!Opnd.isImm())
1757 return Error(IDLoc, "expected immediate operand kind");
1758 Imm = Opnd.getImm();
1759 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1760 return Error(IDLoc, "immediate operand value out of range");
1761 break;
1762 case Mips::LW16_MM:
1763 case Mips::SW16_MM:
1764 Opnd = Inst.getOperand(2);
1765 if (!Opnd.isImm())
1766 return Error(IDLoc, "expected immediate operand kind");
1767 Imm = Opnd.getImm();
1768 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1769 return Error(IDLoc, "immediate operand value out of range");
1770 break;
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +00001771 case Mips::PREFX_MM:
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001772 case Mips::CACHE:
1773 case Mips::PREF:
1774 Opnd = Inst.getOperand(2);
1775 if (!Opnd.isImm())
1776 return Error(IDLoc, "expected immediate operand kind");
1777 Imm = Opnd.getImm();
1778 if (!isUInt<5>(Imm))
1779 return Error(IDLoc, "immediate operand value out of range");
1780 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001781 case Mips::ADDIUPC_MM:
1782 MCOperand Opnd = Inst.getOperand(1);
1783 if (!Opnd.isImm())
1784 return Error(IDLoc, "expected immediate operand kind");
1785 int Imm = Opnd.getImm();
1786 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1787 return Error(IDLoc, "immediate operand value out of range");
1788 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001789 }
1790 }
1791
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001792 if (needsExpansion(Inst)) {
1793 if (expandInstruction(Inst, IDLoc, Instructions))
1794 return true;
1795 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001796 Instructions.push_back(Inst);
1797
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001798 // If this instruction has a delay slot and .set reorder is active,
1799 // emit a NOP after it.
1800 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1801 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1802
Jack Carter9e65aa32013-03-22 00:05:30 +00001803 return false;
1804}
1805
Jack Carter30a59822012-10-04 04:03:53 +00001806bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1807
Jack Carterd0bd6422013-04-18 00:41:53 +00001808 switch (Inst.getOpcode()) {
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001809 case Mips::LoadImm32:
1810 case Mips::LoadImm64:
1811 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001812 case Mips::LoadAddrImm64:
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001813 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001814 case Mips::LoadAddrReg64:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001815 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001816 case Mips::B_MMR6_Pseudo:
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001817 case Mips::LWM_MM:
1818 case Mips::SWM_MM:
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001819 case Mips::JalOneReg:
1820 case Mips::JalTwoReg:
Toma Tabacue1e460d2015-06-11 10:36:10 +00001821 case Mips::BneImm:
1822 case Mips::BeqImm:
Toma Tabacu1a108322015-06-17 13:20:24 +00001823 case Mips::BLT:
1824 case Mips::BLE:
1825 case Mips::BGE:
1826 case Mips::BGT:
1827 case Mips::BLTU:
1828 case Mips::BLEU:
1829 case Mips::BGEU:
1830 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00001831 case Mips::BLTL:
1832 case Mips::BLEL:
1833 case Mips::BGEL:
1834 case Mips::BGTL:
1835 case Mips::BLTUL:
1836 case Mips::BLEUL:
1837 case Mips::BGEUL:
1838 case Mips::BGTUL:
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00001839 case Mips::SDivMacro:
1840 case Mips::UDivMacro:
1841 case Mips::DSDivMacro:
1842 case Mips::DUDivMacro:
Toma Tabacud88d79c2015-06-23 14:39:42 +00001843 case Mips::Ulhu:
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00001844 case Mips::Ulw:
Jack Carterd0bd6422013-04-18 00:41:53 +00001845 return true;
1846 default:
1847 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001848 }
1849}
Jack Carter92995f12012-10-06 00:53:28 +00001850
Matheus Almeida3813d572014-06-19 14:39:14 +00001851bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001852 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001853 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001854 default: llvm_unreachable("unimplemented expansion");
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001855 case Mips::LoadImm32:
Toma Tabacu00e98672015-05-01 12:19:27 +00001856 return expandLoadImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001857 case Mips::LoadImm64:
Toma Tabacu00e98672015-05-01 12:19:27 +00001858 return expandLoadImm(Inst, false, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001859 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001860 case Mips::LoadAddrImm64:
1861 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1862 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1863 "expected immediate operand kind");
1864
1865 return expandLoadAddress(
1866 Inst.getOperand(0).getReg(), Mips::NoRegister, Inst.getOperand(1),
1867 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001868 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001869 case Mips::LoadAddrReg64:
1870 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1871 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1872 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
1873 "expected immediate operand kind");
1874
1875 return expandLoadAddress(
1876 Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(), Inst.getOperand(2),
1877 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001878 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001879 case Mips::B_MMR6_Pseudo:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001880 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001881 case Mips::SWM_MM:
1882 case Mips::LWM_MM:
1883 return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001884 case Mips::JalOneReg:
1885 case Mips::JalTwoReg:
1886 return expandJalWithRegs(Inst, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00001887 case Mips::BneImm:
1888 case Mips::BeqImm:
1889 return expandBranchImm(Inst, IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00001890 case Mips::BLT:
1891 case Mips::BLE:
1892 case Mips::BGE:
1893 case Mips::BGT:
1894 case Mips::BLTU:
1895 case Mips::BLEU:
1896 case Mips::BGEU:
1897 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00001898 case Mips::BLTL:
1899 case Mips::BLEL:
1900 case Mips::BGEL:
1901 case Mips::BGTL:
1902 case Mips::BLTUL:
1903 case Mips::BLEUL:
1904 case Mips::BGEUL:
1905 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00001906 return expandCondBranches(Inst, IDLoc, Instructions);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00001907 case Mips::SDivMacro:
1908 return expandDiv(Inst, IDLoc, Instructions, false, true);
1909 case Mips::DSDivMacro:
1910 return expandDiv(Inst, IDLoc, Instructions, true, true);
1911 case Mips::UDivMacro:
1912 return expandDiv(Inst, IDLoc, Instructions, false, false);
1913 case Mips::DUDivMacro:
1914 return expandDiv(Inst, IDLoc, Instructions, true, false);
Toma Tabacud88d79c2015-06-23 14:39:42 +00001915 case Mips::Ulhu:
1916 return expandUlhu(Inst, IDLoc, Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00001917 case Mips::Ulw:
1918 return expandUlw(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001919 }
Jack Carter30a59822012-10-04 04:03:53 +00001920}
Jack Carter92995f12012-10-06 00:53:28 +00001921
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001922namespace {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001923void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc,
Daniel Sanders03f9c012015-07-14 12:24:22 +00001924 SmallVectorImpl<MCInst> &Instructions) {
1925 MCInst tmpInst;
1926 tmpInst.setOpcode(Opcode);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001927 tmpInst.addOperand(MCOperand::createReg(Reg0));
1928 tmpInst.addOperand(Op1);
Daniel Sanders03f9c012015-07-14 12:24:22 +00001929 tmpInst.setLoc(IDLoc);
1930 Instructions.push_back(tmpInst);
1931}
1932
Daniel Sandersf1ae3672015-08-18 09:55:57 +00001933void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc,
Daniel Sanders03f9c012015-07-14 12:24:22 +00001934 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001935 emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00001936}
1937
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00001938void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc,
1939 SmallVectorImpl<MCInst> &Instructions) {
1940 emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, Instructions);
1941}
1942
1943void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc,
1944 SmallVectorImpl<MCInst> &Instructions) {
1945 MCInst tmpInst;
1946 tmpInst.setOpcode(Opcode);
1947 tmpInst.addOperand(MCOperand::createImm(Imm1));
1948 tmpInst.addOperand(MCOperand::createImm(Imm2));
1949 tmpInst.setLoc(IDLoc);
1950 Instructions.push_back(tmpInst);
1951}
1952
1953void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
1954 SmallVectorImpl<MCInst> &Instructions) {
1955 MCInst tmpInst;
1956 tmpInst.setOpcode(Opcode);
1957 tmpInst.addOperand(MCOperand::createReg(Reg0));
1958 tmpInst.setLoc(IDLoc);
1959 Instructions.push_back(tmpInst);
1960}
1961
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001962void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2,
Daniel Sanders03f9c012015-07-14 12:24:22 +00001963 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1964 MCInst tmpInst;
1965 tmpInst.setOpcode(Opcode);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001966 tmpInst.addOperand(MCOperand::createReg(Reg0));
1967 tmpInst.addOperand(MCOperand::createReg(Reg1));
1968 tmpInst.addOperand(Op2);
Daniel Sanders03f9c012015-07-14 12:24:22 +00001969 tmpInst.setLoc(IDLoc);
1970 Instructions.push_back(tmpInst);
1971}
1972
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001973void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
Daniel Sanders03f9c012015-07-14 12:24:22 +00001974 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001975 emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc,
Daniel Sanders03f9c012015-07-14 12:24:22 +00001976 Instructions);
1977}
1978
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001979void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
1980 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1981 emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc,
1982 Instructions);
1983}
Daniel Sanders03f9c012015-07-14 12:24:22 +00001984
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001985void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount,
1986 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1987 if (ShiftAmount >= 32) {
1988 emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc,
1989 Instructions);
Toma Tabacu7dea2e32015-04-28 14:06:35 +00001990 return;
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001991 }
Toma Tabacu7dea2e32015-04-28 14:06:35 +00001992
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001993 emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001994}
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001995} // end anonymous namespace.
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001996
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001997bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
1998 SmallVectorImpl<MCInst> &Instructions) {
1999 // Create a JALR instruction which is going to replace the pseudo-JAL.
2000 MCInst JalrInst;
2001 JalrInst.setLoc(IDLoc);
2002 const MCOperand FirstRegOp = Inst.getOperand(0);
2003 const unsigned Opcode = Inst.getOpcode();
2004
2005 if (Opcode == Mips::JalOneReg) {
2006 // jal $rs => jalr $rs
2007 if (inMicroMipsMode()) {
2008 JalrInst.setOpcode(Mips::JALR16_MM);
2009 JalrInst.addOperand(FirstRegOp);
2010 } else {
2011 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002012 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002013 JalrInst.addOperand(FirstRegOp);
2014 }
2015 } else if (Opcode == Mips::JalTwoReg) {
2016 // jal $rd, $rs => jalr $rd, $rs
2017 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
2018 JalrInst.addOperand(FirstRegOp);
2019 const MCOperand SecondRegOp = Inst.getOperand(1);
2020 JalrInst.addOperand(SecondRegOp);
2021 }
2022 Instructions.push_back(JalrInst);
2023
2024 // If .set reorder is active, emit a NOP after it.
2025 if (AssemblerOptions.back()->isReorder()) {
2026 // This is a 32-bit NOP because these 2 pseudo-instructions
2027 // do not have a short delay slot.
2028 MCInst NopInst;
2029 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00002030 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2031 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2032 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002033 Instructions.push_back(NopInst);
2034 }
2035
2036 return false;
2037}
2038
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002039/// Can the value be represented by a unsigned N-bit value and a shift left?
2040template<unsigned N>
2041bool isShiftedUIntAtAnyPosition(uint64_t x) {
2042 unsigned BitNum = findFirstSet(x);
2043
2044 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2045}
2046
2047/// Load (or add) an immediate into a register.
2048///
2049/// @param ImmValue The immediate to load.
2050/// @param DstReg The register that will hold the immediate.
2051/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2052/// for a simple initialization.
2053/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2054/// @param IsAddress True if the immediate represents an address. False if it
2055/// is an integer.
2056/// @param IDLoc Location of the immediate in the source file.
2057/// @param Instructions The instructions emitted by this expansion.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002058bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002059 unsigned SrcReg, bool Is32BitImm,
2060 bool IsAddress, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00002061 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00002062 if (!Is32BitImm && !isGP64bit()) {
2063 Error(IDLoc, "instruction requires a 64-bit architecture");
2064 return true;
2065 }
2066
Daniel Sanders03f9c012015-07-14 12:24:22 +00002067 if (Is32BitImm) {
2068 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2069 // Sign extend up to 64-bit so that the predicates match the hardware
2070 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2071 // true.
2072 ImmValue = SignExtend64<32>(ImmValue);
2073 } else {
2074 Error(IDLoc, "instruction requires a 32-bit immediate");
2075 return true;
2076 }
2077 }
2078
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002079 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2080 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2081
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002082 bool UseSrcReg = false;
2083 if (SrcReg != Mips::NoRegister)
2084 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002085
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002086 unsigned TmpReg = DstReg;
2087 if (UseSrcReg && (DstReg == SrcReg)) {
2088 // At this point we need AT to perform the expansions and we exit if it is
2089 // not available.
2090 unsigned ATReg = getATReg(IDLoc);
2091 if (!ATReg)
2092 return true;
2093 TmpReg = ATReg;
2094 }
2095
Daniel Sanders03f9c012015-07-14 12:24:22 +00002096 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002097 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002098 SrcReg = ZeroReg;
2099
2100 // This doesn't quite follow the usual ABI expectations for N32 but matches
2101 // traditional assembler behaviour. N32 would normally use addiu for both
2102 // integers and addresses.
2103 if (IsAddress && !Is32BitImm) {
2104 emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2105 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002106 }
2107
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002108 emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2109 return false;
2110 }
2111
2112 if (isUInt<16>(ImmValue)) {
2113 unsigned TmpReg = DstReg;
2114 if (SrcReg == DstReg) {
2115 TmpReg = getATReg(IDLoc);
2116 if (!TmpReg)
2117 return true;
2118 }
2119
2120 emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002121 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002122 emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2123 return false;
2124 }
2125
2126 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002127 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002128
Toma Tabacu79588102015-04-29 10:19:56 +00002129 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2130 uint16_t Bits15To0 = ImmValue & 0xffff;
2131
Toma Tabacua3d056f2015-05-15 09:42:11 +00002132 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002133 // Traditional behaviour seems to special case this particular value. It's
2134 // not clear why other masks are handled differently.
2135 if (ImmValue == 0xffffffff) {
Daniel Sandersf1ae3672015-08-18 09:55:57 +00002136 emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002137 emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, Instructions);
2138 if (UseSrcReg)
2139 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2140 return false;
2141 }
2142
2143 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002144 // upper 32 bits.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002145 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002146 emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002147 if (Bits15To0)
2148 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
2149 if (UseSrcReg)
2150 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2151 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002152 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002153
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002154 emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions);
2155 if (Bits15To0)
2156 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002157 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002158 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2159 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002160 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002161
2162 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2163 if (Is32BitImm) {
2164 Error(IDLoc, "instruction requires a 32-bit immediate");
2165 return true;
2166 }
2167
2168 // Traditionally, these immediates are shifted as little as possible and as
2169 // such we align the most significant bit to bit 15 of our temporary.
2170 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2171 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2172 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2173 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
2174 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, Instructions);
2175 emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, Instructions);
2176
2177 if (UseSrcReg)
2178 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2179
2180 return false;
2181 }
2182
2183 warnIfNoMacro(IDLoc);
2184
2185 // The remaining case is packed with a sequence of dsll and ori with zeros
2186 // being omitted and any neighbouring dsll's being coalesced.
2187 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2188
2189 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2190 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
2191 IDLoc, Instructions))
2192 return false;
2193
2194 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2195 // skip it and defer the shift to the next chunk.
2196 unsigned ShiftCarriedForwards = 16;
2197 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2198 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2199
2200 if (ImmChunk != 0) {
2201 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2202 Instructions);
2203 emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, Instructions);
2204 ShiftCarriedForwards = 0;
2205 }
2206
2207 ShiftCarriedForwards += 16;
2208 }
2209 ShiftCarriedForwards -= 16;
2210
2211 // Finish any remaining shifts left by trailing zeros.
2212 if (ShiftCarriedForwards)
2213 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2214 Instructions);
2215
2216 if (UseSrcReg)
2217 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2218
Matheus Almeida3813d572014-06-19 14:39:14 +00002219 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002220}
Jack Carter92995f12012-10-06 00:53:28 +00002221
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002222bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
2223 SmallVectorImpl<MCInst> &Instructions) {
2224 const MCOperand &ImmOp = Inst.getOperand(1);
2225 assert(ImmOp.isImm() && "expected immediate operand kind");
2226 const MCOperand &DstRegOp = Inst.getOperand(0);
2227 assert(DstRegOp.isReg() && "expected register operand kind");
2228
2229 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002230 Is32BitImm, false, IDLoc, Instructions))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002231 return true;
2232
2233 return false;
2234}
2235
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002236bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2237 const MCOperand &Offset,
2238 bool Is32BitAddress, SMLoc IDLoc,
2239 SmallVectorImpl<MCInst> &Instructions) {
2240 // la can't produce a usable address when addresses are 64-bit.
2241 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2242 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2243 // We currently can't do this because we depend on the equality
2244 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2245 Error(IDLoc, "la used to load 64-bit address");
2246 // Continue as if we had 'dla' instead.
2247 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002248 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002249
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002250 // dla requires 64-bit addresses.
2251 if (!Is32BitAddress && !ABI.ArePtrs64bit()) {
2252 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002253 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002254 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002255
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002256 if (!Offset.isImm())
2257 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
2258 Is32BitAddress, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002259
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002260 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
2261 IDLoc, Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +00002262}
2263
Toma Tabacuf712ede2015-06-17 14:31:51 +00002264bool MipsAsmParser::loadAndAddSymbolAddress(
2265 const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
2266 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002267 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002268
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002269 // FIXME: The way we're handling symbols right now prevents simple expressions
2270 // like foo+8. We'll be able to fix this once our unary operators (%hi
2271 // and similar) are treated as operators rather than as fixup types.
Toma Tabacu674825c2015-06-16 12:16:24 +00002272 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymExpr);
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002273 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::create(
2274 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
2275 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::create(
2276 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
2277
Toma Tabacufb9d1252015-06-22 12:08:39 +00002278 bool UseSrcReg = SrcReg != Mips::NoRegister;
2279
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002280 // This is the 64-bit symbol address expansion.
2281 if (ABI.ArePtrs64bit() && isGP64bit()) {
2282 // We always need AT for the 64-bit expansion.
2283 // If it is not available we exit.
2284 unsigned ATReg = getATReg(IDLoc);
2285 if (!ATReg)
2286 return true;
2287
2288 const MCSymbolRefExpr *HighestExpr = MCSymbolRefExpr::create(
2289 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
2290 const MCSymbolRefExpr *HigherExpr = MCSymbolRefExpr::create(
2291 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
2292
2293 if (UseSrcReg && (DstReg == SrcReg)) {
2294 // If $rs is the same as $rd:
2295 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2296 // daddiu $at, $at, %higher(sym)
2297 // dsll $at, $at, 16
2298 // daddiu $at, $at, %hi(sym)
2299 // dsll $at, $at, 16
2300 // daddiu $at, $at, %lo(sym)
2301 // daddu $rd, $at, $rd
2302 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2303 Instructions);
2304 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr),
2305 IDLoc, Instructions);
2306 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2307 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2308 Instructions);
2309 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2310 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2311 Instructions);
2312 emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions);
2313
2314 return false;
2315 }
2316
2317 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2318 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2319 // lui $at, %hi(sym)
2320 // daddiu $rd, $rd, %higher(sym)
2321 // daddiu $at, $at, %lo(sym)
2322 // dsll32 $rd, $rd, 0
2323 // daddu $rd, $rd, $at
2324 // (daddu $rd, $rd, $rs)
2325 emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2326 Instructions);
2327 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2328 Instructions);
2329 emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr),
2330 IDLoc, Instructions);
2331 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2332 Instructions);
2333 emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions);
2334 emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions);
2335 if (UseSrcReg)
2336 emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions);
2337
2338 return false;
2339 }
2340
2341 // And now, the 32-bit symbol address expansion:
2342 // If $rs is the same as $rd:
2343 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2344 // ori $at, $at, %lo(sym)
2345 // addu $rd, $at, $rd
2346 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2347 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2348 // ori $rd, $rd, %lo(sym)
2349 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002350 unsigned TmpReg = DstReg;
2351 if (UseSrcReg && (DstReg == SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002352 // If $rs is the same as $rd, we need to use AT.
2353 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002354 unsigned ATReg = getATReg(IDLoc);
2355 if (!ATReg)
2356 return true;
2357 TmpReg = ATReg;
2358 }
2359
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002360 emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions);
2361 emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc,
2362 Instructions);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002363
Toma Tabacufb9d1252015-06-22 12:08:39 +00002364 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002365 emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2366 else
2367 assert(DstReg == TmpReg);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002368
Toma Tabacu674825c2015-06-16 12:16:24 +00002369 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002370}
2371
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002372bool MipsAsmParser::expandUncondBranchMMPseudo(
2373 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002374 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2375 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002376
2377 MCOperand Offset = Inst.getOperand(0);
2378 if (Offset.isExpr()) {
2379 Inst.clear();
2380 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002381 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2382 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2383 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002384 } else {
2385 assert(Offset.isImm() && "expected immediate operand kind");
2386 if (isIntN(11, Offset.getImm())) {
2387 // If offset fits into 11 bits then this instruction becomes microMIPS
2388 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002389 if (inMicroMipsMode())
2390 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002391 } else {
2392 if (!isIntN(17, Offset.getImm()))
2393 Error(IDLoc, "branch target out of range");
2394 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2395 Error(IDLoc, "branch to misaligned address");
2396 Inst.clear();
2397 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002398 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2399 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2400 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002401 }
2402 }
2403 Instructions.push_back(Inst);
2404
Zoran Jovanovicada70912015-09-07 11:56:37 +00002405 // If .set reorder is active and branch instruction has a delay slot,
2406 // emit a NOP after it.
2407 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2408 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Toma Tabacu234482a2015-03-16 12:03:39 +00002409 createNop(true, IDLoc, Instructions);
2410
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002411 return false;
2412}
2413
Toma Tabacue1e460d2015-06-11 10:36:10 +00002414bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2415 SmallVectorImpl<MCInst> &Instructions) {
2416 const MCOperand &DstRegOp = Inst.getOperand(0);
2417 assert(DstRegOp.isReg() && "expected register operand kind");
2418
2419 const MCOperand &ImmOp = Inst.getOperand(1);
2420 assert(ImmOp.isImm() && "expected immediate operand kind");
2421
2422 const MCOperand &MemOffsetOp = Inst.getOperand(2);
2423 assert(MemOffsetOp.isImm() && "expected immediate operand kind");
2424
2425 unsigned OpCode = 0;
2426 switch(Inst.getOpcode()) {
2427 case Mips::BneImm:
2428 OpCode = Mips::BNE;
2429 break;
2430 case Mips::BeqImm:
2431 OpCode = Mips::BEQ;
2432 break;
2433 default:
2434 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2435 break;
2436 }
2437
2438 int64_t ImmValue = ImmOp.getImm();
2439 if (ImmValue == 0) {
2440 MCInst BranchInst;
2441 BranchInst.setOpcode(OpCode);
2442 BranchInst.addOperand(DstRegOp);
2443 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2444 BranchInst.addOperand(MemOffsetOp);
2445 Instructions.push_back(BranchInst);
2446 } else {
2447 warnIfNoMacro(IDLoc);
2448
2449 unsigned ATReg = getATReg(IDLoc);
2450 if (!ATReg)
2451 return true;
2452
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002453 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
2454 IDLoc, Instructions))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002455 return true;
2456
2457 MCInst BranchInst;
2458 BranchInst.setOpcode(OpCode);
2459 BranchInst.addOperand(DstRegOp);
2460 BranchInst.addOperand(MCOperand::createReg(ATReg));
2461 BranchInst.addOperand(MemOffsetOp);
2462 Instructions.push_back(BranchInst);
2463 }
2464 return false;
2465}
2466
Jack Carter9e65aa32013-03-22 00:05:30 +00002467void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002468 SmallVectorImpl<MCInst> &Instructions,
2469 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002470 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00002471 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002472 const MCExpr *ExprOffset;
2473 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002474 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002475 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2476 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002477 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002478 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2479 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002480 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002481 if (isImmOpnd) {
2482 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2483 ImmOffset = Inst.getOperand(2).getImm();
2484 LoOffset = ImmOffset & 0x0000ffff;
2485 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002486 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002487 if (LoOffset & 0x8000)
2488 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002489 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002490 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002491 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002492 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002493 // These are some of the types of expansions we perform here:
2494 // 1) lw $8, sym => lui $8, %hi(sym)
2495 // lw $8, %lo(sym)($8)
2496 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2497 // add $8, $8, $9
2498 // lw $8, %lo(offset)($9)
2499 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2500 // add $at, $at, $8
2501 // lw $8, %lo(offset)($at)
2502 // 4) sw $8, sym => lui $at, %hi(sym)
2503 // sw $8, %lo(sym)($at)
2504 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2505 // add $at, $at, $8
2506 // sw $8, %lo(offset)($at)
2507 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2508 // ldc1 $f0, %lo(sym)($at)
2509 //
2510 // For load instructions we can use the destination register as a temporary
2511 // if base and dst are different (examples 1 and 2) and if the base register
2512 // is general purpose otherwise we must use $at (example 6) and error if it's
2513 // not available. For stores we must use $at (examples 4 and 5) because we
2514 // must not clobber the source register setting up the offset.
2515 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2516 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2517 unsigned RegClassIDOp0 =
2518 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2519 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2520 (RegClassIDOp0 == Mips::GPR64RegClassID);
2521 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002522 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002523 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002524 // At this point we need AT to perform the expansions and we exit if it is
2525 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002526 TmpRegNum = getATReg(IDLoc);
2527 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002528 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002529 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002530
Jack Carter9e65aa32013-03-22 00:05:30 +00002531 TempInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00002532 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002533 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002534 TempInst.addOperand(MCOperand::createImm(HiOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002535 else {
Toma Tabacu07c97b32015-06-17 10:43:45 +00002536 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
2537 TempInst.addOperand(MCOperand::createExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002538 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002539 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002540 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002541 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002542 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002543 // Add temp register to base.
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002544 if (BaseRegNum != Mips::ZERO) {
2545 TempInst.setOpcode(Mips::ADDu);
Jim Grosbache9119e42015-05-13 18:37:00 +00002546 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2547 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2548 TempInst.addOperand(MCOperand::createReg(BaseRegNum));
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002549 Instructions.push_back(TempInst);
2550 TempInst.clear();
2551 }
Alp Tokercb402912014-01-24 17:20:08 +00002552 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002553 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002554 TempInst.setOpcode(Inst.getOpcode());
Jim Grosbache9119e42015-05-13 18:37:00 +00002555 TempInst.addOperand(MCOperand::createReg(RegOpNum));
2556 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002557 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002558 TempInst.addOperand(MCOperand::createImm(LoOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002559 else {
Toma Tabacu07c97b32015-06-17 10:43:45 +00002560 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
2561 TempInst.addOperand(MCOperand::createExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002562 }
2563 Instructions.push_back(TempInst);
2564 TempInst.clear();
2565}
2566
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002567bool
2568MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2569 SmallVectorImpl<MCInst> &Instructions) {
2570 unsigned OpNum = Inst.getNumOperands();
2571 unsigned Opcode = Inst.getOpcode();
2572 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2573
2574 assert (Inst.getOperand(OpNum - 1).isImm() &&
2575 Inst.getOperand(OpNum - 2).isReg() &&
2576 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2577
2578 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2579 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2580 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2581 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2582 // It can be implemented as SWM16 or LWM16 instruction.
2583 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2584
2585 Inst.setOpcode(NewOpcode);
2586 Instructions.push_back(Inst);
2587 return false;
2588}
2589
Toma Tabacu1a108322015-06-17 13:20:24 +00002590bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2591 SmallVectorImpl<MCInst> &Instructions) {
2592 unsigned PseudoOpcode = Inst.getOpcode();
2593 unsigned SrcReg = Inst.getOperand(0).getReg();
2594 unsigned TrgReg = Inst.getOperand(1).getReg();
2595 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2596
2597 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002598 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002599
2600 switch (PseudoOpcode) {
2601 case Mips::BLT:
2602 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002603 case Mips::BLTL:
2604 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002605 AcceptsEquality = false;
2606 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002607 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2608 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002609 ZeroSrcOpcode = Mips::BGTZ;
2610 ZeroTrgOpcode = Mips::BLTZ;
2611 break;
2612 case Mips::BLE:
2613 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002614 case Mips::BLEL:
2615 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002616 AcceptsEquality = true;
2617 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002618 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2619 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002620 ZeroSrcOpcode = Mips::BGEZ;
2621 ZeroTrgOpcode = Mips::BLEZ;
2622 break;
2623 case Mips::BGE:
2624 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002625 case Mips::BGEL:
2626 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002627 AcceptsEquality = true;
2628 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002629 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2630 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002631 ZeroSrcOpcode = Mips::BLEZ;
2632 ZeroTrgOpcode = Mips::BGEZ;
2633 break;
2634 case Mips::BGT:
2635 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002636 case Mips::BGTL:
2637 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002638 AcceptsEquality = false;
2639 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002640 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2641 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002642 ZeroSrcOpcode = Mips::BLTZ;
2643 ZeroTrgOpcode = Mips::BGTZ;
2644 break;
2645 default:
2646 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2647 }
2648
2649 MCInst BranchInst;
2650 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2651 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2652 if (IsSrcRegZero && IsTrgRegZero) {
2653 // FIXME: All of these Opcode-specific if's are needed for compatibility
2654 // with GAS' behaviour. However, they may not generate the most efficient
2655 // code in some circumstances.
2656 if (PseudoOpcode == Mips::BLT) {
2657 BranchInst.setOpcode(Mips::BLTZ);
2658 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2659 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2660 Instructions.push_back(BranchInst);
2661 return false;
2662 }
2663 if (PseudoOpcode == Mips::BLE) {
2664 BranchInst.setOpcode(Mips::BLEZ);
2665 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2666 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2667 Instructions.push_back(BranchInst);
2668 Warning(IDLoc, "branch is always taken");
2669 return false;
2670 }
2671 if (PseudoOpcode == Mips::BGE) {
2672 BranchInst.setOpcode(Mips::BGEZ);
2673 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2674 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2675 Instructions.push_back(BranchInst);
2676 Warning(IDLoc, "branch is always taken");
2677 return false;
2678 }
2679 if (PseudoOpcode == Mips::BGT) {
2680 BranchInst.setOpcode(Mips::BGTZ);
2681 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2682 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2683 Instructions.push_back(BranchInst);
2684 return false;
2685 }
2686 if (PseudoOpcode == Mips::BGTU) {
2687 BranchInst.setOpcode(Mips::BNE);
2688 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2689 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2690 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2691 Instructions.push_back(BranchInst);
2692 return false;
2693 }
2694 if (AcceptsEquality) {
2695 // If both registers are $0 and the pseudo-branch accepts equality, it
2696 // will always be taken, so we emit an unconditional branch.
2697 BranchInst.setOpcode(Mips::BEQ);
2698 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2699 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2700 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2701 Instructions.push_back(BranchInst);
2702 Warning(IDLoc, "branch is always taken");
2703 return false;
2704 }
2705 // If both registers are $0 and the pseudo-branch does not accept
2706 // equality, it will never be taken, so we don't have to emit anything.
2707 return false;
2708 }
2709 if (IsSrcRegZero || IsTrgRegZero) {
2710 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2711 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2712 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2713 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2714 // the pseudo-branch will never be taken, so we don't emit anything.
2715 // This only applies to unsigned pseudo-branches.
2716 return false;
2717 }
2718 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2719 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2720 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2721 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2722 // the pseudo-branch will always be taken, so we emit an unconditional
2723 // branch.
2724 // This only applies to unsigned pseudo-branches.
2725 BranchInst.setOpcode(Mips::BEQ);
2726 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2727 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2728 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2729 Instructions.push_back(BranchInst);
2730 Warning(IDLoc, "branch is always taken");
2731 return false;
2732 }
2733 if (IsUnsigned) {
2734 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2735 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2736 // the pseudo-branch will be taken only when the non-zero register is
2737 // different from 0, so we emit a BNEZ.
2738 //
2739 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2740 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2741 // the pseudo-branch will be taken only when the non-zero register is
2742 // equal to 0, so we emit a BEQZ.
2743 //
2744 // Because only BLEU and BGEU branch on equality, we can use the
2745 // AcceptsEquality variable to decide when to emit the BEQZ.
2746 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQ : Mips::BNE);
2747 BranchInst.addOperand(
2748 MCOperand::createReg(IsSrcRegZero ? TrgReg : SrcReg));
2749 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2750 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2751 Instructions.push_back(BranchInst);
2752 return false;
2753 }
2754 // If we have a signed pseudo-branch and one of the registers is $0,
2755 // we can use an appropriate compare-to-zero branch. We select which one
2756 // to use in the switch statement above.
2757 BranchInst.setOpcode(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode);
2758 BranchInst.addOperand(MCOperand::createReg(IsSrcRegZero ? TrgReg : SrcReg));
2759 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2760 Instructions.push_back(BranchInst);
2761 return false;
2762 }
2763
2764 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2765 // expansions. If it is not available, we return.
2766 unsigned ATRegNum = getATReg(IDLoc);
2767 if (!ATRegNum)
2768 return true;
2769
2770 warnIfNoMacro(IDLoc);
2771
2772 // SLT fits well with 2 of our 4 pseudo-branches:
2773 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2774 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2775 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2776 // This is accomplished by using a BNEZ with the result of the SLT.
2777 //
2778 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2779 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2780 // Because only BGE and BLE branch on equality, we can use the
2781 // AcceptsEquality variable to decide when to emit the BEQZ.
2782 // Note that the order of the SLT arguments doesn't change between
2783 // opposites.
2784 //
2785 // The same applies to the unsigned variants, except that SLTu is used
2786 // instead of SLT.
2787 MCInst SetInst;
2788 SetInst.setOpcode(IsUnsigned ? Mips::SLTu : Mips::SLT);
2789 SetInst.addOperand(MCOperand::createReg(ATRegNum));
2790 SetInst.addOperand(MCOperand::createReg(ReverseOrderSLT ? TrgReg : SrcReg));
2791 SetInst.addOperand(MCOperand::createReg(ReverseOrderSLT ? SrcReg : TrgReg));
2792 Instructions.push_back(SetInst);
2793
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002794 if (!IsLikely)
2795 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQ : Mips::BNE);
2796 else
2797 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQL : Mips::BNEL);
Toma Tabacu1a108322015-06-17 13:20:24 +00002798 BranchInst.addOperand(MCOperand::createReg(ATRegNum));
2799 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2800 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2801 Instructions.push_back(BranchInst);
2802 return false;
2803}
2804
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002805bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
2806 SmallVectorImpl<MCInst> &Instructions,
2807 const bool IsMips64, const bool Signed) {
2808 if (hasMips32r6()) {
2809 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2810 return false;
2811 }
2812
2813 warnIfNoMacro(IDLoc);
2814
2815 const MCOperand &RsRegOp = Inst.getOperand(0);
2816 assert(RsRegOp.isReg() && "expected register operand kind");
2817 unsigned RsReg = RsRegOp.getReg();
2818
2819 const MCOperand &RtRegOp = Inst.getOperand(1);
2820 assert(RtRegOp.isReg() && "expected register operand kind");
2821 unsigned RtReg = RtRegOp.getReg();
2822 unsigned DivOp;
2823 unsigned ZeroReg;
2824
2825 if (IsMips64) {
2826 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2827 ZeroReg = Mips::ZERO_64;
2828 } else {
2829 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2830 ZeroReg = Mips::ZERO;
2831 }
2832
2833 bool UseTraps = useTraps();
2834
2835 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2836 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2837 Warning(IDLoc, "dividing zero by zero");
2838 if (IsMips64) {
2839 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2840 if (UseTraps) {
2841 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2842 return false;
2843 }
2844
2845 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2846 return false;
2847 }
2848 } else {
2849 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2850 return false;
2851 }
2852 }
2853
2854 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
2855 Warning(IDLoc, "division by zero");
2856 if (Signed) {
2857 if (UseTraps) {
2858 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2859 return false;
2860 }
2861
2862 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2863 return false;
2864 }
2865 }
2866
2867 // FIXME: The values for these two BranchTarget variables may be different in
2868 // micromips. These magic numbers need to be removed.
2869 unsigned BranchTargetNoTraps;
2870 unsigned BranchTarget;
2871
2872 if (UseTraps) {
2873 BranchTarget = IsMips64 ? 12 : 8;
2874 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2875 } else {
2876 BranchTarget = IsMips64 ? 20 : 16;
2877 BranchTargetNoTraps = 8;
2878 // Branch to the li instruction.
2879 emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc,
2880 Instructions);
2881 }
2882
2883 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2884
2885 if (!UseTraps)
2886 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2887
2888 if (!Signed) {
2889 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
2890 return false;
2891 }
2892
2893 unsigned ATReg = getATReg(IDLoc);
2894 if (!ATReg)
2895 return true;
2896
2897 emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, Instructions);
2898 if (IsMips64) {
2899 // Branch to the mflo instruction.
2900 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
2901 emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, Instructions);
2902 emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, Instructions);
2903 } else {
2904 // Branch to the mflo instruction.
2905 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
2906 emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, Instructions);
2907 }
2908
2909 if (UseTraps)
2910 emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, Instructions);
2911 else {
2912 // Branch to the mflo instruction.
2913 emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, Instructions);
2914 emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, Instructions);
2915 emitII(Mips::BREAK, 0x6, 0, IDLoc, Instructions);
2916 }
2917 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
2918 return false;
2919}
2920
Toma Tabacud88d79c2015-06-23 14:39:42 +00002921bool MipsAsmParser::expandUlhu(MCInst &Inst, SMLoc IDLoc,
2922 SmallVectorImpl<MCInst> &Instructions) {
2923 if (hasMips32r6() || hasMips64r6()) {
2924 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2925 return false;
2926 }
2927
2928 warnIfNoMacro(IDLoc);
2929
2930 const MCOperand &DstRegOp = Inst.getOperand(0);
2931 assert(DstRegOp.isReg() && "expected register operand kind");
2932
2933 const MCOperand &SrcRegOp = Inst.getOperand(1);
2934 assert(SrcRegOp.isReg() && "expected register operand kind");
2935
2936 const MCOperand &OffsetImmOp = Inst.getOperand(2);
2937 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
2938
2939 unsigned DstReg = DstRegOp.getReg();
2940 unsigned SrcReg = SrcRegOp.getReg();
2941 int64_t OffsetValue = OffsetImmOp.getImm();
2942
2943 // NOTE: We always need AT for ULHU, as it is always used as the source
2944 // register for one of the LBu's.
2945 unsigned ATReg = getATReg(IDLoc);
2946 if (!ATReg)
2947 return true;
2948
2949 // When the value of offset+1 does not fit in 16 bits, we have to load the
2950 // offset in AT, (D)ADDu the original source register (if there was one), and
2951 // then use AT as the source register for the 2 generated LBu's.
2952 bool LoadedOffsetInAT = false;
2953 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
2954 LoadedOffsetInAT = true;
2955
2956 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002957 true, IDLoc, Instructions))
Toma Tabacud88d79c2015-06-23 14:39:42 +00002958 return true;
2959
2960 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
2961 // because it will make our output more similar to GAS'. For example,
2962 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
2963 // instead of just an "ori $1, $9, 32768".
2964 // NOTE: If there is no source register specified in the ULHU, the parser
2965 // will interpret it as $0.
2966 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
2967 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
2968 }
2969
2970 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
2971 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
2972 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
2973
2974 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
2975 if (isLittle()) {
2976 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
2977 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
2978 } else {
2979 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
2980 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
2981 }
2982
2983 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
2984
2985 MCInst TmpInst;
2986 TmpInst.setOpcode(Mips::LBu);
2987 TmpInst.addOperand(MCOperand::createReg(FirstLbuDstReg));
2988 TmpInst.addOperand(MCOperand::createReg(LbuSrcReg));
2989 TmpInst.addOperand(MCOperand::createImm(FirstLbuOffset));
2990 Instructions.push_back(TmpInst);
2991
2992 TmpInst.clear();
2993 TmpInst.setOpcode(Mips::LBu);
2994 TmpInst.addOperand(MCOperand::createReg(SecondLbuDstReg));
2995 TmpInst.addOperand(MCOperand::createReg(LbuSrcReg));
2996 TmpInst.addOperand(MCOperand::createImm(SecondLbuOffset));
2997 Instructions.push_back(TmpInst);
2998
2999 TmpInst.clear();
3000 TmpInst.setOpcode(Mips::SLL);
3001 TmpInst.addOperand(MCOperand::createReg(SllReg));
3002 TmpInst.addOperand(MCOperand::createReg(SllReg));
3003 TmpInst.addOperand(MCOperand::createImm(8));
3004 Instructions.push_back(TmpInst);
3005
3006 TmpInst.clear();
3007 TmpInst.setOpcode(Mips::OR);
3008 TmpInst.addOperand(MCOperand::createReg(DstReg));
3009 TmpInst.addOperand(MCOperand::createReg(DstReg));
3010 TmpInst.addOperand(MCOperand::createReg(ATReg));
3011 Instructions.push_back(TmpInst);
3012
3013 return false;
3014}
3015
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003016bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
3017 SmallVectorImpl<MCInst> &Instructions) {
3018 if (hasMips32r6() || hasMips64r6()) {
3019 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3020 return false;
3021 }
3022
3023 const MCOperand &DstRegOp = Inst.getOperand(0);
3024 assert(DstRegOp.isReg() && "expected register operand kind");
3025
3026 const MCOperand &SrcRegOp = Inst.getOperand(1);
3027 assert(SrcRegOp.isReg() && "expected register operand kind");
3028
3029 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3030 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3031
3032 unsigned SrcReg = SrcRegOp.getReg();
3033 int64_t OffsetValue = OffsetImmOp.getImm();
3034 unsigned ATReg = 0;
3035
3036 // When the value of offset+3 does not fit in 16 bits, we have to load the
3037 // offset in AT, (D)ADDu the original source register (if there was one), and
3038 // then use AT as the source register for the generated LWL and LWR.
3039 bool LoadedOffsetInAT = false;
3040 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3041 ATReg = getATReg(IDLoc);
3042 if (!ATReg)
3043 return true;
3044 LoadedOffsetInAT = true;
3045
3046 warnIfNoMacro(IDLoc);
3047
3048 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003049 true, IDLoc, Instructions))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003050 return true;
3051
3052 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3053 // because it will make our output more similar to GAS'. For example,
3054 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3055 // instead of just an "ori $1, $9, 32768".
3056 // NOTE: If there is no source register specified in the ULW, the parser
3057 // will interpret it as $0.
3058 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3059 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3060 }
3061
3062 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3063 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3064 if (isLittle()) {
3065 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3066 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3067 } else {
3068 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3069 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3070 }
3071
3072 MCInst LeftLoadInst;
3073 LeftLoadInst.setOpcode(Mips::LWL);
3074 LeftLoadInst.addOperand(DstRegOp);
3075 LeftLoadInst.addOperand(MCOperand::createReg(FinalSrcReg));
3076 LeftLoadInst.addOperand(MCOperand::createImm(LeftLoadOffset));
3077 Instructions.push_back(LeftLoadInst);
3078
3079 MCInst RightLoadInst;
3080 RightLoadInst.setOpcode(Mips::LWR);
3081 RightLoadInst.addOperand(DstRegOp);
3082 RightLoadInst.addOperand(MCOperand::createReg(FinalSrcReg));
3083 RightLoadInst.addOperand(MCOperand::createImm(RightLoadOffset ));
3084 Instructions.push_back(RightLoadInst);
3085
3086 return false;
3087}
3088
Toma Tabacu234482a2015-03-16 12:03:39 +00003089void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
3090 SmallVectorImpl<MCInst> &Instructions) {
3091 MCInst NopInst;
3092 if (hasShortDelaySlot) {
3093 NopInst.setOpcode(Mips::MOVE16_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003094 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
3095 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
Toma Tabacu234482a2015-03-16 12:03:39 +00003096 } else {
3097 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00003098 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
3099 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
3100 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu234482a2015-03-16 12:03:39 +00003101 }
3102 Instructions.push_back(NopInst);
3103}
3104
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003105void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +00003106 unsigned TrgReg, bool Is64Bit,
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003107 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders03f9c012015-07-14 12:24:22 +00003108 emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
3109 Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003110}
3111
Matheus Almeida595fcab2014-06-11 15:05:56 +00003112unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3113 // As described by the Mips32r2 spec, the registers Rd and Rs for
3114 // jalr.hb must be different.
3115 unsigned Opcode = Inst.getOpcode();
3116
3117 if (Opcode == Mips::JALR_HB &&
3118 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3119 return Match_RequiresDifferentSrcAndDst;
3120
3121 return Match_Success;
3122}
3123
David Blaikie960ea3f2014-06-08 16:18:35 +00003124bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3125 OperandVector &Operands,
3126 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003127 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003128 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003129
Jack Carterb4dbc172012-09-05 23:34:03 +00003130 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00003131 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00003132 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003133 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003134
3135 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003136 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003137 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00003138 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00003139 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00003140 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00003141 return false;
3142 }
3143 case Match_MissingFeature:
3144 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3145 return true;
3146 case Match_InvalidOperand: {
3147 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003148 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003149 if (ErrorInfo >= Operands.size())
3150 return Error(IDLoc, "too few operands for instruction");
3151
David Blaikie960ea3f2014-06-08 16:18:35 +00003152 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003153 if (ErrorLoc == SMLoc())
3154 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003155 }
3156
3157 return Error(ErrorLoc, "invalid operand for instruction");
3158 }
3159 case Match_MnemonicFail:
3160 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003161 case Match_RequiresDifferentSrcAndDst:
3162 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00003163 }
Craig Topper589ceee2015-01-03 08:16:34 +00003164
3165 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003166}
3167
Toma Tabacud9d344b2015-04-27 14:05:04 +00003168void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3169 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3170 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3171 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003172}
3173
Toma Tabacu81496c12015-05-20 08:54:45 +00003174void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3175 if (!AssemblerOptions.back()->isMacro())
3176 Warning(Loc, "macro instruction expanded into multiple instructions");
3177}
3178
Daniel Sandersef638fe2014-10-03 15:37:37 +00003179void
3180MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3181 SMRange Range, bool ShowColors) {
3182 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003183 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003184 ShowColors);
3185}
3186
Jack Carter1ac53222013-02-20 23:11:17 +00003187int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003188 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003189
Vladimir Medic4c299852013-11-06 11:27:05 +00003190 CC = StringSwitch<unsigned>(Name)
3191 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003192 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003193 .Case("a0", 4)
3194 .Case("a1", 5)
3195 .Case("a2", 6)
3196 .Case("a3", 7)
3197 .Case("v0", 2)
3198 .Case("v1", 3)
3199 .Case("s0", 16)
3200 .Case("s1", 17)
3201 .Case("s2", 18)
3202 .Case("s3", 19)
3203 .Case("s4", 20)
3204 .Case("s5", 21)
3205 .Case("s6", 22)
3206 .Case("s7", 23)
3207 .Case("k0", 26)
3208 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003209 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003210 .Case("sp", 29)
3211 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003212 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003213 .Case("ra", 31)
3214 .Case("t0", 8)
3215 .Case("t1", 9)
3216 .Case("t2", 10)
3217 .Case("t3", 11)
3218 .Case("t4", 12)
3219 .Case("t5", 13)
3220 .Case("t6", 14)
3221 .Case("t7", 15)
3222 .Case("t8", 24)
3223 .Case("t9", 25)
3224 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003225
Toma Tabacufda445c2014-09-15 15:33:01 +00003226 if (!(isABI_N32() || isABI_N64()))
3227 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003228
Daniel Sandersef638fe2014-10-03 15:37:37 +00003229 if (12 <= CC && CC <= 15) {
3230 // Name is one of t4-t7
3231 AsmToken RegTok = getLexer().peekTok();
3232 SMRange RegRange = RegTok.getLocRange();
3233
3234 StringRef FixedName = StringSwitch<StringRef>(Name)
3235 .Case("t4", "t0")
3236 .Case("t5", "t1")
3237 .Case("t6", "t2")
3238 .Case("t7", "t3")
3239 .Default("");
3240 assert(FixedName != "" && "Register name is not one of t4-t7.");
3241
3242 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3243 "Did you mean $" + FixedName + "?", RegRange);
3244 }
3245
Toma Tabacufda445c2014-09-15 15:33:01 +00003246 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3247 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3248 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3249 if (8 <= CC && CC <= 11)
3250 CC += 4;
3251
3252 if (CC == -1)
3253 CC = StringSwitch<unsigned>(Name)
3254 .Case("a4", 8)
3255 .Case("a5", 9)
3256 .Case("a6", 10)
3257 .Case("a7", 11)
3258 .Case("kt0", 26)
3259 .Case("kt1", 27)
3260 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003261
3262 return CC;
3263}
Jack Carterd0bd6422013-04-18 00:41:53 +00003264
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003265int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3266 int CC;
3267
3268 CC = StringSwitch<unsigned>(Name)
3269 .Case("hwr_cpunum", 0)
3270 .Case("hwr_synci_step", 1)
3271 .Case("hwr_cc", 2)
3272 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003273 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003274 .Default(-1);
3275
3276 return CC;
3277}
3278
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003279int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003280
Jack Cartera63b16a2012-09-07 00:23:42 +00003281 if (Name[0] == 'f') {
3282 StringRef NumString = Name.substr(1);
3283 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003284 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003285 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003286 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003287 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003288 return IntVal;
3289 }
3290 return -1;
3291}
Jack Cartera63b16a2012-09-07 00:23:42 +00003292
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003293int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3294
3295 if (Name.startswith("fcc")) {
3296 StringRef NumString = Name.substr(3);
3297 unsigned IntVal;
3298 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003299 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003300 if (IntVal > 7) // There are only 8 fcc registers.
3301 return -1;
3302 return IntVal;
3303 }
3304 return -1;
3305}
3306
3307int MipsAsmParser::matchACRegisterName(StringRef Name) {
3308
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003309 if (Name.startswith("ac")) {
3310 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003311 unsigned IntVal;
3312 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003313 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003314 if (IntVal > 3) // There are only 3 acc registers.
3315 return -1;
3316 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003317 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003318 return -1;
3319}
Jack Carterd0bd6422013-04-18 00:41:53 +00003320
Jack Carter5dc8ac92013-09-25 23:50:44 +00003321int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3322 unsigned IntVal;
3323
3324 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3325 return -1;
3326
3327 if (IntVal > 31)
3328 return -1;
3329
3330 return IntVal;
3331}
3332
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003333int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3334 int CC;
3335
3336 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003337 .Case("msair", 0)
3338 .Case("msacsr", 1)
3339 .Case("msaaccess", 2)
3340 .Case("msasave", 3)
3341 .Case("msamodify", 4)
3342 .Case("msarequest", 5)
3343 .Case("msamap", 6)
3344 .Case("msaunmap", 7)
3345 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003346
3347 return CC;
3348}
3349
Toma Tabacu89a712b2015-04-15 10:48:56 +00003350unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00003351 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00003352 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00003353 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00003354 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00003355 return 0;
3356 }
3357 unsigned AT = getReg(
3358 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00003359 return AT;
3360}
Jack Carter0b744b32012-10-04 02:29:46 +00003361
Jack Carterd0bd6422013-04-18 00:41:53 +00003362unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00003363 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00003364}
3365
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003366unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003367 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00003368 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003369}
3370
Jack Carter873c7242013-01-12 01:03:14 +00003371int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003372 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00003373 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00003374 return -1;
3375
Jack Carter873c7242013-01-12 01:03:14 +00003376 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00003377}
3378
Toma Tabacu13964452014-09-04 13:23:44 +00003379bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003380 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003381 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003382
Jack Carter30a59822012-10-04 04:03:53 +00003383 // Check if the current operand has a custom associated parser, if so, try to
3384 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00003385 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3386 if (ResTy == MatchOperand_Success)
3387 return false;
3388 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3389 // there was a match, but an error occurred, in which case, just return that
3390 // the operand parsing failed.
3391 if (ResTy == MatchOperand_ParseFail)
3392 return true;
3393
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003394 DEBUG(dbgs() << ".. Generic Parser\n");
3395
Jack Carterb4dbc172012-09-05 23:34:03 +00003396 switch (getLexer().getKind()) {
3397 default:
3398 Error(Parser.getTok().getLoc(), "unexpected token in operand");
3399 return true;
3400 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003401 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00003402 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00003403
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003404 // Almost all registers have been parsed by custom parsers. There is only
3405 // one exception to this. $zero (and it's alias $0) will reach this point
3406 // for div, divu, and similar instructions because it is not an operand
3407 // to the instruction definition but an explicit register. Special case
3408 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00003409 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00003410 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003411
Jack Carterd0bd6422013-04-18 00:41:53 +00003412 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00003413 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003414 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00003415 return true;
3416
Jack Carter873c7242013-01-12 01:03:14 +00003417 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00003418 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00003419 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00003420 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003421 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00003422
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003423 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003424 return false;
3425 }
Vladimir Medic4c299852013-11-06 11:27:05 +00003426 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00003427 case AsmToken::LParen:
3428 case AsmToken::Minus:
3429 case AsmToken::Plus:
3430 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003431 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00003432 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003433 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003434 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003435 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00003436 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00003437 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003438 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003439 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003440 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00003441 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00003442 return true;
3443
Jack Carter873c7242013-01-12 01:03:14 +00003444 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3445
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003446 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00003447 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003448 } // case AsmToken::Percent
3449 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00003450 return true;
3451}
3452
Vladimir Medic4c299852013-11-06 11:27:05 +00003453const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00003454 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003455 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00003456 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003457 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00003458 // It's a constant, evaluate reloc value.
3459 int16_t Val;
3460 switch (getVariantKind(RelocStr)) {
3461 case MCSymbolRefExpr::VK_Mips_ABS_LO:
3462 // Get the 1st 16-bits.
3463 Val = MCE->getValue() & 0xffff;
3464 break;
3465 case MCSymbolRefExpr::VK_Mips_ABS_HI:
3466 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
3467 // 16 bits being negative.
3468 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
3469 break;
3470 case MCSymbolRefExpr::VK_Mips_HIGHER:
3471 // Get the 3rd 16-bits.
3472 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
3473 break;
3474 case MCSymbolRefExpr::VK_Mips_HIGHEST:
3475 // Get the 4th 16-bits.
3476 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
3477 break;
3478 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00003479 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00003480 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00003481 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003482 }
3483
Jack Carterb5cf5902013-04-17 00:18:04 +00003484 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003485 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00003486 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00003487 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003488 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003489 return Res;
3490 }
3491
3492 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00003493 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
3494
Sasa Stankovic06c47802014-04-03 10:37:45 +00003495 // Try to create target expression.
3496 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00003497 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003498
Jack Carterd0bd6422013-04-18 00:41:53 +00003499 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
3500 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003501 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003502 return Res;
3503 }
3504
3505 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003506 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003507 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00003508 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00003509 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003510 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003511 return Expr;
3512}
3513
3514bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
3515
3516 switch (Expr->getKind()) {
3517 case MCExpr::Constant:
3518 return true;
3519 case MCExpr::SymbolRef:
3520 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
3521 case MCExpr::Binary:
3522 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
3523 if (!isEvaluated(BE->getLHS()))
3524 return false;
3525 return isEvaluated(BE->getRHS());
3526 }
3527 case MCExpr::Unary:
3528 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003529 case MCExpr::Target:
3530 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003531 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003532 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00003533}
Jack Carterd0bd6422013-04-18 00:41:53 +00003534
Jack Carterb5cf5902013-04-17 00:18:04 +00003535bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003536 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003537 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00003538 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00003539 if (Tok.isNot(AsmToken::Identifier))
3540 return true;
3541
Yaron Keren075759a2015-03-30 15:42:36 +00003542 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00003543
Jack Carterd0bd6422013-04-18 00:41:53 +00003544 Parser.Lex(); // Eat the identifier.
3545 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003546 const MCExpr *IdVal;
3547 SMLoc EndLoc;
3548
3549 if (getLexer().getKind() == AsmToken::LParen) {
3550 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003551 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003552 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003553 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003554 const AsmToken &nextTok = Parser.getTok();
3555 if (nextTok.isNot(AsmToken::Identifier))
3556 return true;
3557 Str += "(%";
3558 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00003559 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00003560 if (getLexer().getKind() != AsmToken::LParen)
3561 return true;
3562 } else
3563 break;
3564 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003565 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00003566 return true;
3567
3568 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00003569 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003570
3571 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00003572 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003573
Jack Carterd0bd6422013-04-18 00:41:53 +00003574 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00003575 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003576}
3577
Jack Carterb4dbc172012-09-05 23:34:03 +00003578bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
3579 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003580 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00003581 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003582 if (ResTy == MatchOperand_Success) {
3583 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00003584 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003585 StartLoc = Operand.getStartLoc();
3586 EndLoc = Operand.getEndLoc();
3587
3588 // AFAIK, we only support numeric registers and named GPR's in CFI
3589 // directives.
3590 // Don't worry about eating tokens before failing. Using an unrecognised
3591 // register is a parse error.
3592 if (Operand.isGPRAsmReg()) {
3593 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003594 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003595 }
3596
3597 return (RegNo == (unsigned)-1);
3598 }
3599
3600 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00003601 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00003602}
3603
Jack Carterb5cf5902013-04-17 00:18:04 +00003604bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003605 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00003606 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003607 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003608 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00003609
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003610 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003611 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003612 ++NumOfLParen;
3613 }
Jack Carter873c7242013-01-12 01:03:14 +00003614
Jack Carterd0bd6422013-04-18 00:41:53 +00003615 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003616 default:
3617 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00003618 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00003619 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00003620 case AsmToken::Integer:
3621 case AsmToken::Minus:
3622 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00003623 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003624 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00003625 else
3626 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00003627 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00003628 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003629 break;
Jack Carter873c7242013-01-12 01:03:14 +00003630 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00003631 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003632 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003633 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003634}
3635
David Blaikie960ea3f2014-06-08 16:18:35 +00003636MipsAsmParser::OperandMatchResultTy
3637MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003638 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003639 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00003640 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00003641 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003642 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003643 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00003644 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00003645 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00003646
Jack Carterb5cf5902013-04-17 00:18:04 +00003647 if (getLexer().getKind() == AsmToken::LParen) {
3648 Parser.Lex();
3649 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003650 }
3651
Jack Carterb5cf5902013-04-17 00:18:04 +00003652 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003653 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00003654 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003655
Jack Carterd0bd6422013-04-18 00:41:53 +00003656 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003657 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003658 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003659 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003660 SMLoc E =
3661 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003662 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003663 return MatchOperand_Success;
3664 }
3665 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003666 SMLoc E =
3667 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00003668
Jack Carterd0bd6422013-04-18 00:41:53 +00003669 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003670 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00003671 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003672 S, E, *this);
3673 Operands.push_back(
3674 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003675 return MatchOperand_Success;
3676 }
3677 Error(Parser.getTok().getLoc(), "'(' expected");
3678 return MatchOperand_ParseFail;
3679 }
3680
Jack Carterd0bd6422013-04-18 00:41:53 +00003681 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003682 }
3683
Toma Tabacu13964452014-09-04 13:23:44 +00003684 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003685 if (Res != MatchOperand_Success)
3686 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003687
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003688 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003689 Error(Parser.getTok().getLoc(), "')' expected");
3690 return MatchOperand_ParseFail;
3691 }
3692
Jack Carter873c7242013-01-12 01:03:14 +00003693 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3694
Jack Carterd0bd6422013-04-18 00:41:53 +00003695 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003696
Craig Topper062a2ba2014-04-25 05:30:21 +00003697 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003698 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003699
Jack Carterd0bd6422013-04-18 00:41:53 +00003700 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00003701 std::unique_ptr<MipsOperand> op(
3702 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00003703 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003704 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003705 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00003706 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003707 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
3708 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003709 if (IdVal->evaluateAsAbsolute(Imm))
3710 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003711 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003712 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00003713 getContext());
3714 }
3715
David Blaikie960ea3f2014-06-08 16:18:35 +00003716 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003717 return MatchOperand_Success;
3718}
3719
David Blaikie960ea3f2014-06-08 16:18:35 +00003720bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003721 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00003722 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00003723 if (Sym) {
3724 SMLoc S = Parser.getTok().getLoc();
3725 const MCExpr *Expr;
3726 if (Sym->isVariable())
3727 Expr = Sym->getVariableValue();
3728 else
3729 return false;
3730 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003731 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00003732 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00003733 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003734 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003735 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00003736 if (ResTy == MatchOperand_Success) {
3737 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00003738 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00003739 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003740 llvm_unreachable("Should never ParseFail");
3741 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00003742 }
3743 } else if (Expr->getKind() == MCExpr::Constant) {
3744 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00003745 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00003746 Operands.push_back(
3747 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00003748 return true;
3749 }
3750 }
3751 return false;
3752}
Jack Carterd0bd6422013-04-18 00:41:53 +00003753
Jack Carter873c7242013-01-12 01:03:14 +00003754MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003755MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00003756 StringRef Identifier,
3757 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003758 int Index = matchCPURegisterName(Identifier);
3759 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003760 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003761 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3762 return MatchOperand_Success;
3763 }
3764
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003765 Index = matchHWRegsRegisterName(Identifier);
3766 if (Index != -1) {
3767 Operands.push_back(MipsOperand::createHWRegsReg(
3768 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3769 return MatchOperand_Success;
3770 }
3771
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003772 Index = matchFPURegisterName(Identifier);
3773 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003774 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003775 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3776 return MatchOperand_Success;
3777 }
3778
3779 Index = matchFCCRegisterName(Identifier);
3780 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003781 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003782 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3783 return MatchOperand_Success;
3784 }
3785
3786 Index = matchACRegisterName(Identifier);
3787 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003788 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003789 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3790 return MatchOperand_Success;
3791 }
3792
3793 Index = matchMSA128RegisterName(Identifier);
3794 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003795 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003796 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3797 return MatchOperand_Success;
3798 }
3799
3800 Index = matchMSA128CtrlRegisterName(Identifier);
3801 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003802 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003803 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3804 return MatchOperand_Success;
3805 }
3806
3807 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00003808}
3809
3810MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003811MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003812 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00003813 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003814
3815 if (Token.is(AsmToken::Identifier)) {
3816 DEBUG(dbgs() << ".. identifier\n");
3817 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00003818 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003819 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00003820 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003821 } else if (Token.is(AsmToken::Integer)) {
3822 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003823 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003824 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
3825 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003826 return MatchOperand_Success;
3827 }
3828
3829 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
3830
3831 return MatchOperand_NoMatch;
3832}
3833
David Blaikie960ea3f2014-06-08 16:18:35 +00003834MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003835MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003836 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003837 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003838
3839 auto Token = Parser.getTok();
3840
3841 SMLoc S = Token.getLoc();
3842
3843 if (Token.isNot(AsmToken::Dollar)) {
3844 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
3845 if (Token.is(AsmToken::Identifier)) {
3846 if (searchSymbolAlias(Operands))
3847 return MatchOperand_Success;
3848 }
3849 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
3850 return MatchOperand_NoMatch;
3851 }
3852 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003853
Toma Tabacu13964452014-09-04 13:23:44 +00003854 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00003855 if (ResTy == MatchOperand_Success) {
3856 Parser.Lex(); // $
3857 Parser.Lex(); // identifier
3858 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003859 return ResTy;
3860}
3861
3862MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003863MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003864 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003865 switch (getLexer().getKind()) {
3866 default:
3867 return MatchOperand_NoMatch;
3868 case AsmToken::LParen:
3869 case AsmToken::Minus:
3870 case AsmToken::Plus:
3871 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003872 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003873 case AsmToken::String:
3874 break;
3875 }
3876
3877 const MCExpr *IdVal;
3878 SMLoc S = Parser.getTok().getLoc();
3879 if (getParser().parseExpression(IdVal))
3880 return MatchOperand_ParseFail;
3881
3882 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3883 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
3884 return MatchOperand_Success;
3885}
3886
David Blaikie960ea3f2014-06-08 16:18:35 +00003887MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003888MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003889 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003890 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003891
3892 SMLoc S = getLexer().getLoc();
3893
3894 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00003895 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003896 if (ResTy != MatchOperand_NoMatch)
3897 return ResTy;
3898
Daniel Sanders315386c2014-04-01 10:40:14 +00003899 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00003900 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00003901 if (ResTy != MatchOperand_NoMatch)
3902 return ResTy;
3903
Daniel Sandersffd84362014-04-01 10:41:48 +00003904 const MCExpr *Expr = nullptr;
3905 if (Parser.parseExpression(Expr)) {
3906 // We have no way of knowing if a symbol was consumed so we must ParseFail
3907 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003908 }
Daniel Sandersffd84362014-04-01 10:41:48 +00003909 Operands.push_back(
3910 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003911 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00003912}
3913
Vladimir Medic2b953d02013-10-01 09:48:56 +00003914MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00003915MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003916 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00003917 const MCExpr *IdVal;
3918 // If the first token is '$' we may have register operand.
3919 if (Parser.getTok().is(AsmToken::Dollar))
3920 return MatchOperand_NoMatch;
3921 SMLoc S = Parser.getTok().getLoc();
3922 if (getParser().parseExpression(IdVal))
3923 return MatchOperand_ParseFail;
3924 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00003925 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00003926 int64_t Val = MCE->getValue();
3927 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3928 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003929 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00003930 return MatchOperand_Success;
3931}
3932
Matheus Almeida779c5932013-11-18 12:32:49 +00003933MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003934MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003935 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00003936 switch (getLexer().getKind()) {
3937 default:
3938 return MatchOperand_NoMatch;
3939 case AsmToken::LParen:
3940 case AsmToken::Plus:
3941 case AsmToken::Minus:
3942 case AsmToken::Integer:
3943 break;
3944 }
3945
3946 const MCExpr *Expr;
3947 SMLoc S = Parser.getTok().getLoc();
3948
3949 if (getParser().parseExpression(Expr))
3950 return MatchOperand_ParseFail;
3951
3952 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003953 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00003954 Error(S, "expected immediate value");
3955 return MatchOperand_ParseFail;
3956 }
3957
3958 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
3959 // and because the CPU always adds one to the immediate field, the allowed
3960 // range becomes 1..4. We'll only check the range here and will deal
3961 // with the addition/subtraction when actually decoding/encoding
3962 // the instruction.
3963 if (Val < 1 || Val > 4) {
3964 Error(S, "immediate not in range (1..4)");
3965 return MatchOperand_ParseFail;
3966 }
3967
Jack Carter3b2c96e2014-01-22 23:31:38 +00003968 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003969 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00003970 return MatchOperand_Success;
3971}
3972
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00003973MipsAsmParser::OperandMatchResultTy
3974MipsAsmParser::parseRegisterList(OperandVector &Operands) {
3975 MCAsmParser &Parser = getParser();
3976 SmallVector<unsigned, 10> Regs;
3977 unsigned RegNo;
3978 unsigned PrevReg = Mips::NoRegister;
3979 bool RegRange = false;
3980 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3981
3982 if (Parser.getTok().isNot(AsmToken::Dollar))
3983 return MatchOperand_ParseFail;
3984
3985 SMLoc S = Parser.getTok().getLoc();
3986 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
3987 SMLoc E = getLexer().getLoc();
3988 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
3989 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
3990 if (RegRange) {
3991 // Remove last register operand because registers from register range
3992 // should be inserted first.
3993 if (RegNo == Mips::RA) {
3994 Regs.push_back(RegNo);
3995 } else {
3996 unsigned TmpReg = PrevReg + 1;
3997 while (TmpReg <= RegNo) {
3998 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
3999 Error(E, "invalid register operand");
4000 return MatchOperand_ParseFail;
4001 }
4002
4003 PrevReg = TmpReg;
4004 Regs.push_back(TmpReg++);
4005 }
4006 }
4007
4008 RegRange = false;
4009 } else {
4010 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
4011 (RegNo != Mips::RA)) {
4012 Error(E, "$16 or $31 expected");
4013 return MatchOperand_ParseFail;
4014 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
4015 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
4016 Error(E, "invalid register operand");
4017 return MatchOperand_ParseFail;
4018 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
4019 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
4020 Error(E, "consecutive register numbers expected");
4021 return MatchOperand_ParseFail;
4022 }
4023
4024 Regs.push_back(RegNo);
4025 }
4026
4027 if (Parser.getTok().is(AsmToken::Minus))
4028 RegRange = true;
4029
4030 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4031 !Parser.getTok().isNot(AsmToken::Comma)) {
4032 Error(E, "',' or '-' expected");
4033 return MatchOperand_ParseFail;
4034 }
4035
4036 Lex(); // Consume comma or minus
4037 if (Parser.getTok().isNot(AsmToken::Dollar))
4038 break;
4039
4040 PrevReg = RegNo;
4041 }
4042
4043 SMLoc E = Parser.getTok().getLoc();
4044 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4045 parseMemOperand(Operands);
4046 return MatchOperand_Success;
4047}
4048
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004049MipsAsmParser::OperandMatchResultTy
4050MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4051 MCAsmParser &Parser = getParser();
4052
4053 SMLoc S = Parser.getTok().getLoc();
4054 if (parseAnyRegister(Operands) != MatchOperand_Success)
4055 return MatchOperand_ParseFail;
4056
4057 SMLoc E = Parser.getTok().getLoc();
4058 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
4059 unsigned Reg = Op.getGPR32Reg();
4060 Operands.pop_back();
4061 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
4062 return MatchOperand_Success;
4063}
4064
Zoran Jovanovic41688672015-02-10 16:36:20 +00004065MipsAsmParser::OperandMatchResultTy
4066MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4067 MCAsmParser &Parser = getParser();
4068 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4069 SmallVector<unsigned, 10> Regs;
4070
4071 if (Parser.getTok().isNot(AsmToken::Dollar))
4072 return MatchOperand_ParseFail;
4073
4074 SMLoc S = Parser.getTok().getLoc();
4075
4076 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4077 return MatchOperand_ParseFail;
4078
4079 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4080 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4081 Regs.push_back(RegNo);
4082
4083 SMLoc E = Parser.getTok().getLoc();
4084 if (Parser.getTok().isNot(AsmToken::Comma)) {
4085 Error(E, "',' expected");
4086 return MatchOperand_ParseFail;
4087 }
4088
4089 // Remove comma.
4090 Parser.Lex();
4091
4092 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4093 return MatchOperand_ParseFail;
4094
4095 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4096 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4097 Regs.push_back(RegNo);
4098
4099 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4100
4101 return MatchOperand_Success;
4102}
4103
Jack Carterdc1e35d2012-09-06 20:00:02 +00004104MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
4105
Vladimir Medic4c299852013-11-06 11:27:05 +00004106 MCSymbolRefExpr::VariantKind VK =
4107 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
4108 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
4109 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
4110 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
4111 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
4112 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
4113 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
4114 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
4115 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
4116 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
4117 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
4118 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
4119 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
4120 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
4121 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
4122 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
4123 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
4124 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00004125 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
4126 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
4127 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
4128 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
4129 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
4130 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00004131 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
4132 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00004133 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004134
Matheus Almeida2852af82014-04-22 10:15:54 +00004135 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00004136
Jack Carterdc1e35d2012-09-06 20:00:02 +00004137 return VK;
4138}
Jack Cartera63b16a2012-09-07 00:23:42 +00004139
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004140/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4141/// either this.
4142/// ::= '(', register, ')'
4143/// handle it before we iterate so we don't get tripped up by the lack of
4144/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004145bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004146 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004147 if (getLexer().is(AsmToken::LParen)) {
4148 Operands.push_back(
4149 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4150 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004151 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004152 SMLoc Loc = getLexer().getLoc();
4153 Parser.eatToEndOfStatement();
4154 return Error(Loc, "unexpected token in argument list");
4155 }
4156 if (Parser.getTok().isNot(AsmToken::RParen)) {
4157 SMLoc Loc = getLexer().getLoc();
4158 Parser.eatToEndOfStatement();
4159 return Error(Loc, "unexpected token, expected ')'");
4160 }
4161 Operands.push_back(
4162 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4163 Parser.Lex();
4164 }
4165 return false;
4166}
4167
4168/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4169/// either one of these.
4170/// ::= '[', register, ']'
4171/// ::= '[', integer, ']'
4172/// handle it before we iterate so we don't get tripped up by the lack of
4173/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004174bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004175 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004176 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004177 if (getLexer().is(AsmToken::LBrac)) {
4178 Operands.push_back(
4179 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4180 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004181 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004182 SMLoc Loc = getLexer().getLoc();
4183 Parser.eatToEndOfStatement();
4184 return Error(Loc, "unexpected token in argument list");
4185 }
4186 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4187 SMLoc Loc = getLexer().getLoc();
4188 Parser.eatToEndOfStatement();
4189 return Error(Loc, "unexpected token, expected ']'");
4190 }
4191 Operands.push_back(
4192 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4193 Parser.Lex();
4194 }
4195 return false;
4196}
4197
David Blaikie960ea3f2014-06-08 16:18:35 +00004198bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4199 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004200 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004201 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004202
4203 // We have reached first instruction, module directive are now forbidden.
4204 getTargetStreamer().forbidModuleDirective();
4205
Vladimir Medic74593e62013-07-17 15:00:42 +00004206 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004207 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004208 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004209 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004210 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004211 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004212 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004213
4214 // Read the remaining operands.
4215 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4216 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004217 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004218 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004219 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004220 return Error(Loc, "unexpected token in argument list");
4221 }
Toma Tabacu13964452014-09-04 13:23:44 +00004222 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004223 return true;
4224 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004225
Jack Carterd0bd6422013-04-18 00:41:53 +00004226 while (getLexer().is(AsmToken::Comma)) {
4227 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004228 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004229 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004230 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004231 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004232 return Error(Loc, "unexpected token in argument list");
4233 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004234 // Parse bracket and parenthesis suffixes before we iterate
4235 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004236 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004237 return true;
4238 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004239 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004240 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004241 }
4242 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004243 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4244 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004245 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004246 return Error(Loc, "unexpected token in argument list");
4247 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004248 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004249 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004250}
4251
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004252bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004253 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004254 SMLoc Loc = getLexer().getLoc();
4255 Parser.eatToEndOfStatement();
4256 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004257}
4258
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004259bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004260 return Error(Loc, ErrorMsg);
4261}
4262
Jack Carter0b744b32012-10-04 02:29:46 +00004263bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004264 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004265 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004266
4267 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004268 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004269
4270 Parser.Lex(); // Eat "noat".
4271
Jack Carterd0bd6422013-04-18 00:41:53 +00004272 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004273 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004274 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004275 return false;
4276 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004277
4278 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004279 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004280 return false;
4281}
Jack Carterd0bd6422013-04-18 00:41:53 +00004282
Jack Carter0b744b32012-10-04 02:29:46 +00004283bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004284 // Line can be: ".set at", which sets $at to $1
4285 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004286 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004287 Parser.Lex(); // Eat "at".
4288
Jack Carter0b744b32012-10-04 02:29:46 +00004289 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004290 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004291 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004292
4293 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004294 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004295 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004296 }
4297
4298 if (getLexer().isNot(AsmToken::Equal)) {
4299 reportParseError("unexpected token, expected equals sign");
4300 return false;
4301 }
4302 Parser.Lex(); // Eat "=".
4303
4304 if (getLexer().isNot(AsmToken::Dollar)) {
4305 if (getLexer().is(AsmToken::EndOfStatement)) {
4306 reportParseError("no register specified");
4307 return false;
4308 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004309 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004310 return false;
4311 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004312 }
4313 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004314
Toma Tabacu16a74492015-02-13 10:30:57 +00004315 // Find out what "reg" is.
4316 unsigned AtRegNo;
4317 const AsmToken &Reg = Parser.getTok();
4318 if (Reg.is(AsmToken::Identifier)) {
4319 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4320 } else if (Reg.is(AsmToken::Integer)) {
4321 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004322 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004323 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004324 return false;
4325 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004326
4327 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004328 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004329 reportParseError("invalid register");
4330 return false;
4331 }
4332 Parser.Lex(); // Eat "reg".
4333
4334 // If this is not the end of the statement, report an error.
4335 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4336 reportParseError("unexpected token, expected end of statement");
4337 return false;
4338 }
4339
4340 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4341
4342 Parser.Lex(); // Consume the EndOfStatement.
4343 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004344}
4345
4346bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004347 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004348 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004349 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004350 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004351 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004352 return false;
4353 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004354 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004355 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004356 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004357 return false;
4358}
4359
4360bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004361 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004362 Parser.Lex();
4363 // If this is not the end of the statement, report an error.
4364 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004365 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004366 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00004367 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004368 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00004369 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004370 Parser.Lex(); // Consume the EndOfStatement.
4371 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004372}
4373
4374bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004375 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004376 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004377 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004378 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004379 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004380 return false;
4381 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004382 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004383 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004384 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004385 return false;
4386}
4387
4388bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004389 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004390 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004391 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004392 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004393 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004394 return false;
4395 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004396 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00004397 reportParseError("`noreorder' must be set before `nomacro'");
4398 return false;
4399 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004400 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004401 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004402 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004403 return false;
4404}
Jack Carterd76b2372013-03-21 21:44:16 +00004405
Daniel Sanders44934432014-08-07 12:03:36 +00004406bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004407 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004408 Parser.Lex();
4409
4410 // If this is not the end of the statement, report an error.
4411 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004412 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004413
4414 setFeatureBits(Mips::FeatureMSA, "msa");
4415 getTargetStreamer().emitDirectiveSetMsa();
4416 return false;
4417}
4418
4419bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004420 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004421 Parser.Lex();
4422
4423 // If this is not the end of the statement, report an error.
4424 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004425 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004426
4427 clearFeatureBits(Mips::FeatureMSA, "msa");
4428 getTargetStreamer().emitDirectiveSetNoMsa();
4429 return false;
4430}
4431
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004432bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004433 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004434 Parser.Lex(); // Eat "nodsp".
4435
4436 // If this is not the end of the statement, report an error.
4437 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4438 reportParseError("unexpected token, expected end of statement");
4439 return false;
4440 }
4441
4442 clearFeatureBits(Mips::FeatureDSP, "dsp");
4443 getTargetStreamer().emitDirectiveSetNoDsp();
4444 return false;
4445}
4446
Toma Tabacucc2502d2014-11-04 17:18:07 +00004447bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004448 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004449 Parser.Lex(); // Eat "mips16".
4450
Jack Carter39536722014-01-22 23:08:42 +00004451 // If this is not the end of the statement, report an error.
4452 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004453 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00004454 return false;
4455 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00004456
4457 setFeatureBits(Mips::FeatureMips16, "mips16");
4458 getTargetStreamer().emitDirectiveSetMips16();
4459 Parser.Lex(); // Consume the EndOfStatement.
4460 return false;
4461}
4462
4463bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004464 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004465 Parser.Lex(); // Eat "nomips16".
4466
4467 // If this is not the end of the statement, report an error.
4468 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4469 reportParseError("unexpected token, expected end of statement");
4470 return false;
4471 }
4472
4473 clearFeatureBits(Mips::FeatureMips16, "mips16");
4474 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00004475 Parser.Lex(); // Consume the EndOfStatement.
4476 return false;
4477}
4478
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004479bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004480 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004481 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004482 // Line can be: .set fp=32
4483 // .set fp=xx
4484 // .set fp=64
4485 Parser.Lex(); // Eat fp token
4486 AsmToken Tok = Parser.getTok();
4487 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004488 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004489 return false;
4490 }
4491 Parser.Lex(); // Eat '=' token.
4492 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004493
4494 if (!parseFpABIValue(FpAbiVal, ".set"))
4495 return false;
4496
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004497 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004498 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004499 return false;
4500 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004501 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004502 Parser.Lex(); // Consume the EndOfStatement.
4503 return false;
4504}
4505
Toma Tabacu32c72aa2015-06-30 09:36:50 +00004506bool MipsAsmParser::parseSetOddSPRegDirective() {
4507 MCAsmParser &Parser = getParser();
4508
4509 Parser.Lex(); // Eat "oddspreg".
4510 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4511 reportParseError("unexpected token, expected end of statement");
4512 return false;
4513 }
4514
4515 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4516 getTargetStreamer().emitDirectiveSetOddSPReg();
4517 return false;
4518}
4519
4520bool MipsAsmParser::parseSetNoOddSPRegDirective() {
4521 MCAsmParser &Parser = getParser();
4522
4523 Parser.Lex(); // Eat "nooddspreg".
4524 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4525 reportParseError("unexpected token, expected end of statement");
4526 return false;
4527 }
4528
4529 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4530 getTargetStreamer().emitDirectiveSetNoOddSPReg();
4531 return false;
4532}
4533
Toma Tabacu9db22db2014-09-09 10:15:38 +00004534bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004535 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004536 SMLoc Loc = getLexer().getLoc();
4537
4538 Parser.Lex();
4539 if (getLexer().isNot(AsmToken::EndOfStatement))
4540 return reportParseError("unexpected token, expected end of statement");
4541
4542 // Always keep an element on the options "stack" to prevent the user
4543 // from changing the initial options. This is how we remember them.
4544 if (AssemblerOptions.size() == 2)
4545 return reportParseError(Loc, ".set pop with no .set push");
4546
4547 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00004548 setAvailableFeatures(
4549 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
4550 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00004551
4552 getTargetStreamer().emitDirectiveSetPop();
4553 return false;
4554}
4555
4556bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004557 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004558 Parser.Lex();
4559 if (getLexer().isNot(AsmToken::EndOfStatement))
4560 return reportParseError("unexpected token, expected end of statement");
4561
4562 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00004563 AssemblerOptions.push_back(
4564 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00004565
4566 getTargetStreamer().emitDirectiveSetPush();
4567 return false;
4568}
4569
Toma Tabacu29696502015-06-02 09:48:04 +00004570bool MipsAsmParser::parseSetSoftFloatDirective() {
4571 MCAsmParser &Parser = getParser();
4572 Parser.Lex();
4573 if (getLexer().isNot(AsmToken::EndOfStatement))
4574 return reportParseError("unexpected token, expected end of statement");
4575
4576 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4577 getTargetStreamer().emitDirectiveSetSoftFloat();
4578 return false;
4579}
4580
4581bool MipsAsmParser::parseSetHardFloatDirective() {
4582 MCAsmParser &Parser = getParser();
4583 Parser.Lex();
4584 if (getLexer().isNot(AsmToken::EndOfStatement))
4585 return reportParseError("unexpected token, expected end of statement");
4586
4587 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4588 getTargetStreamer().emitDirectiveSetHardFloat();
4589 return false;
4590}
4591
Jack Carterd76b2372013-03-21 21:44:16 +00004592bool MipsAsmParser::parseSetAssignment() {
4593 StringRef Name;
4594 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00004595 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00004596
4597 if (Parser.parseIdentifier(Name))
4598 reportParseError("expected identifier after .set");
4599
4600 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004601 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00004602 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00004603
Jack Carter3b2c96e2014-01-22 23:31:38 +00004604 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00004605 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00004606
Jim Grosbach6f482002015-05-18 18:43:14 +00004607 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00004608 Sym->setVariableValue(Value);
4609
4610 return false;
4611}
Jack Carterd0bd6422013-04-18 00:41:53 +00004612
Toma Tabacu26647792014-09-09 12:52:14 +00004613bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004614 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00004615 Parser.Lex();
4616 if (getLexer().isNot(AsmToken::EndOfStatement))
4617 return reportParseError("unexpected token, expected end of statement");
4618
4619 // Reset assembler options to their initial values.
Toma Tabacu465acfd2015-06-09 13:33:26 +00004620 setAvailableFeatures(
4621 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
4622 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00004623 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
4624
4625 getTargetStreamer().emitDirectiveSetMips0();
4626 return false;
4627}
4628
Toma Tabacu85618b32014-08-19 14:22:52 +00004629bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004630 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00004631 Parser.Lex();
4632 if (getLexer().isNot(AsmToken::Equal))
4633 return reportParseError("unexpected token, expected equals sign");
4634
4635 Parser.Lex();
4636 StringRef Arch;
4637 if (Parser.parseIdentifier(Arch))
4638 return reportParseError("expected arch identifier");
4639
4640 StringRef ArchFeatureName =
4641 StringSwitch<StringRef>(Arch)
4642 .Case("mips1", "mips1")
4643 .Case("mips2", "mips2")
4644 .Case("mips3", "mips3")
4645 .Case("mips4", "mips4")
4646 .Case("mips5", "mips5")
4647 .Case("mips32", "mips32")
4648 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004649 .Case("mips32r3", "mips32r3")
4650 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004651 .Case("mips32r6", "mips32r6")
4652 .Case("mips64", "mips64")
4653 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004654 .Case("mips64r3", "mips64r3")
4655 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004656 .Case("mips64r6", "mips64r6")
4657 .Case("cnmips", "cnmips")
4658 .Case("r4000", "mips3") // This is an implementation of Mips3.
4659 .Default("");
4660
4661 if (ArchFeatureName.empty())
4662 return reportParseError("unsupported architecture");
4663
4664 selectArch(ArchFeatureName);
4665 getTargetStreamer().emitDirectiveSetArch(Arch);
4666 return false;
4667}
4668
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004669bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004670 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004671 Parser.Lex();
4672 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004673 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004674
Matheus Almeida2852af82014-04-22 10:15:54 +00004675 switch (Feature) {
4676 default:
4677 llvm_unreachable("Unimplemented feature");
4678 case Mips::FeatureDSP:
4679 setFeatureBits(Mips::FeatureDSP, "dsp");
4680 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004681 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004682 case Mips::FeatureMicroMips:
4683 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004684 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004685 case Mips::FeatureMips1:
4686 selectArch("mips1");
4687 getTargetStreamer().emitDirectiveSetMips1();
4688 break;
4689 case Mips::FeatureMips2:
4690 selectArch("mips2");
4691 getTargetStreamer().emitDirectiveSetMips2();
4692 break;
4693 case Mips::FeatureMips3:
4694 selectArch("mips3");
4695 getTargetStreamer().emitDirectiveSetMips3();
4696 break;
4697 case Mips::FeatureMips4:
4698 selectArch("mips4");
4699 getTargetStreamer().emitDirectiveSetMips4();
4700 break;
4701 case Mips::FeatureMips5:
4702 selectArch("mips5");
4703 getTargetStreamer().emitDirectiveSetMips5();
4704 break;
4705 case Mips::FeatureMips32:
4706 selectArch("mips32");
4707 getTargetStreamer().emitDirectiveSetMips32();
4708 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004709 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004710 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004711 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004712 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004713 case Mips::FeatureMips32r3:
4714 selectArch("mips32r3");
4715 getTargetStreamer().emitDirectiveSetMips32R3();
4716 break;
4717 case Mips::FeatureMips32r5:
4718 selectArch("mips32r5");
4719 getTargetStreamer().emitDirectiveSetMips32R5();
4720 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004721 case Mips::FeatureMips32r6:
4722 selectArch("mips32r6");
4723 getTargetStreamer().emitDirectiveSetMips32R6();
4724 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004725 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004726 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00004727 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00004728 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004729 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004730 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004731 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00004732 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004733 case Mips::FeatureMips64r3:
4734 selectArch("mips64r3");
4735 getTargetStreamer().emitDirectiveSetMips64R3();
4736 break;
4737 case Mips::FeatureMips64r5:
4738 selectArch("mips64r5");
4739 getTargetStreamer().emitDirectiveSetMips64R5();
4740 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004741 case Mips::FeatureMips64r6:
4742 selectArch("mips64r6");
4743 getTargetStreamer().emitDirectiveSetMips64R6();
4744 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004745 }
4746 return false;
4747}
4748
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004749bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004750 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004751 if (getLexer().isNot(AsmToken::Comma)) {
4752 SMLoc Loc = getLexer().getLoc();
4753 Parser.eatToEndOfStatement();
4754 return Error(Loc, ErrorStr);
4755 }
4756
Matheus Almeida2852af82014-04-22 10:15:54 +00004757 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004758 return true;
4759}
4760
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004761bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00004762 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00004763 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004764
Toma Tabacudde4c462014-11-06 10:02:45 +00004765 if (inMips16Mode()) {
4766 reportParseError(".cpload is not supported in Mips16 mode");
4767 return false;
4768 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004769
David Blaikie960ea3f2014-06-08 16:18:35 +00004770 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00004771 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004772 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4773 reportParseError("expected register containing function address");
4774 return false;
4775 }
4776
David Blaikie960ea3f2014-06-08 16:18:35 +00004777 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
4778 if (!RegOpnd.isGPRAsmReg()) {
4779 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004780 return false;
4781 }
4782
Toma Tabacudde4c462014-11-06 10:02:45 +00004783 // If this is not the end of the statement, report an error.
4784 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4785 reportParseError("unexpected token, expected end of statement");
4786 return false;
4787 }
4788
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004789 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004790 return false;
4791}
4792
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004793bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004794 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004795 unsigned FuncReg;
4796 unsigned Save;
4797 bool SaveIsReg = true;
4798
Matheus Almeida7e815762014-06-18 13:08:59 +00004799 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004800 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00004801 if (ResTy == MatchOperand_NoMatch) {
4802 reportParseError("expected register containing function address");
4803 Parser.eatToEndOfStatement();
4804 return false;
4805 }
4806
4807 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4808 if (!FuncRegOpnd.isGPRAsmReg()) {
4809 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
4810 Parser.eatToEndOfStatement();
4811 return false;
4812 }
4813
4814 FuncReg = FuncRegOpnd.getGPR32Reg();
4815 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004816
Toma Tabacu65f10572014-09-16 15:00:52 +00004817 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004818 return true;
4819
Toma Tabacu13964452014-09-04 13:23:44 +00004820 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00004821 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004822 const AsmToken &Tok = Parser.getTok();
4823 if (Tok.is(AsmToken::Integer)) {
4824 Save = Tok.getIntVal();
4825 SaveIsReg = false;
4826 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00004827 } else {
4828 reportParseError("expected save register or stack offset");
4829 Parser.eatToEndOfStatement();
4830 return false;
4831 }
4832 } else {
4833 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4834 if (!SaveOpnd.isGPRAsmReg()) {
4835 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
4836 Parser.eatToEndOfStatement();
4837 return false;
4838 }
4839 Save = SaveOpnd.getGPR32Reg();
4840 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004841
Toma Tabacu65f10572014-09-16 15:00:52 +00004842 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004843 return true;
4844
Toma Tabacu8874eac2015-02-18 13:46:53 +00004845 const MCExpr *Expr;
4846 if (Parser.parseExpression(Expr)) {
4847 reportParseError("expected expression");
4848 return false;
4849 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004850
Toma Tabacu8874eac2015-02-18 13:46:53 +00004851 if (Expr->getKind() != MCExpr::SymbolRef) {
4852 reportParseError("expected symbol");
4853 return false;
4854 }
4855 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
4856
4857 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
4858 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004859 return false;
4860}
4861
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004862bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004863 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004864 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4865 const AsmToken &Tok = Parser.getTok();
4866
4867 if (Tok.getString() == "2008") {
4868 Parser.Lex();
4869 getTargetStreamer().emitDirectiveNaN2008();
4870 return false;
4871 } else if (Tok.getString() == "legacy") {
4872 Parser.Lex();
4873 getTargetStreamer().emitDirectiveNaNLegacy();
4874 return false;
4875 }
4876 }
4877 // If we don't recognize the option passed to the .nan
4878 // directive (e.g. no option or unknown option), emit an error.
4879 reportParseError("invalid option in .nan directive");
4880 return false;
4881}
4882
Jack Carter0b744b32012-10-04 02:29:46 +00004883bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004884 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004885 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00004886 const AsmToken &Tok = Parser.getTok();
4887
4888 if (Tok.getString() == "noat") {
4889 return parseSetNoAtDirective();
4890 } else if (Tok.getString() == "at") {
4891 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00004892 } else if (Tok.getString() == "arch") {
4893 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004894 } else if (Tok.getString() == "fp") {
4895 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00004896 } else if (Tok.getString() == "oddspreg") {
4897 return parseSetOddSPRegDirective();
4898 } else if (Tok.getString() == "nooddspreg") {
4899 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004900 } else if (Tok.getString() == "pop") {
4901 return parseSetPopDirective();
4902 } else if (Tok.getString() == "push") {
4903 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00004904 } else if (Tok.getString() == "reorder") {
4905 return parseSetReorderDirective();
4906 } else if (Tok.getString() == "noreorder") {
4907 return parseSetNoReorderDirective();
4908 } else if (Tok.getString() == "macro") {
4909 return parseSetMacroDirective();
4910 } else if (Tok.getString() == "nomacro") {
4911 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00004912 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00004913 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00004914 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00004915 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00004916 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00004917 getTargetStreamer().emitDirectiveSetNoMicroMips();
4918 Parser.eatToEndOfStatement();
4919 return false;
4920 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004921 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00004922 } else if (Tok.getString() == "mips0") {
4923 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00004924 } else if (Tok.getString() == "mips1") {
4925 return parseSetFeature(Mips::FeatureMips1);
4926 } else if (Tok.getString() == "mips2") {
4927 return parseSetFeature(Mips::FeatureMips2);
4928 } else if (Tok.getString() == "mips3") {
4929 return parseSetFeature(Mips::FeatureMips3);
4930 } else if (Tok.getString() == "mips4") {
4931 return parseSetFeature(Mips::FeatureMips4);
4932 } else if (Tok.getString() == "mips5") {
4933 return parseSetFeature(Mips::FeatureMips5);
4934 } else if (Tok.getString() == "mips32") {
4935 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00004936 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004937 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00004938 } else if (Tok.getString() == "mips32r3") {
4939 return parseSetFeature(Mips::FeatureMips32r3);
4940 } else if (Tok.getString() == "mips32r5") {
4941 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00004942 } else if (Tok.getString() == "mips32r6") {
4943 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00004944 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004945 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00004946 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004947 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00004948 } else if (Tok.getString() == "mips64r3") {
4949 return parseSetFeature(Mips::FeatureMips64r3);
4950 } else if (Tok.getString() == "mips64r5") {
4951 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00004952 } else if (Tok.getString() == "mips64r6") {
4953 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00004954 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004955 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004956 } else if (Tok.getString() == "nodsp") {
4957 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00004958 } else if (Tok.getString() == "msa") {
4959 return parseSetMsaDirective();
4960 } else if (Tok.getString() == "nomsa") {
4961 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00004962 } else if (Tok.getString() == "softfloat") {
4963 return parseSetSoftFloatDirective();
4964 } else if (Tok.getString() == "hardfloat") {
4965 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00004966 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00004967 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00004968 parseSetAssignment();
4969 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004970 }
Jack Carter07c818d2013-01-25 01:31:34 +00004971
Jack Carter0b744b32012-10-04 02:29:46 +00004972 return true;
4973}
4974
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004975/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00004976/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004977bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004978 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004979 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4980 for (;;) {
4981 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004982 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00004983 return true;
4984
4985 getParser().getStreamer().EmitValue(Value, Size);
4986
4987 if (getLexer().is(AsmToken::EndOfStatement))
4988 break;
4989
Jack Carter07c818d2013-01-25 01:31:34 +00004990 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004991 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00004992 Parser.Lex();
4993 }
4994 }
4995
4996 Parser.Lex();
4997 return false;
4998}
4999
Vladimir Medic4c299852013-11-06 11:27:05 +00005000/// parseDirectiveGpWord
5001/// ::= .gpword local_sym
5002bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005003 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005004 const MCExpr *Value;
5005 // EmitGPRel32Value requires an expression, so we are using base class
5006 // method to evaluate the expression.
5007 if (getParser().parseExpression(Value))
5008 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005009 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005010
Vladimir Medice10c1122013-11-13 13:18:04 +00005011 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005012 return Error(getLexer().getLoc(),
5013 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005014 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005015 return false;
5016}
5017
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005018/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005019/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005020bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005021 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005022 const MCExpr *Value;
5023 // EmitGPRel64Value requires an expression, so we are using base class
5024 // method to evaluate the expression.
5025 if (getParser().parseExpression(Value))
5026 return true;
5027 getParser().getStreamer().EmitGPRel64Value(Value);
5028
5029 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005030 return Error(getLexer().getLoc(),
5031 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005032 Parser.Lex(); // Eat EndOfStatement token.
5033 return false;
5034}
5035
Jack Carter0cd3c192014-01-06 23:27:31 +00005036bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005037 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005038 // Get the option token.
5039 AsmToken Tok = Parser.getTok();
5040 // At the moment only identifiers are supported.
5041 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005042 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005043 Parser.eatToEndOfStatement();
5044 return false;
5045 }
5046
5047 StringRef Option = Tok.getIdentifier();
5048
5049 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005050 // MipsAsmParser needs to know if the current PIC mode changes.
5051 IsPicEnabled = false;
5052
Jack Carter0cd3c192014-01-06 23:27:31 +00005053 getTargetStreamer().emitDirectiveOptionPic0();
5054 Parser.Lex();
5055 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5056 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005057 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005058 Parser.eatToEndOfStatement();
5059 }
5060 return false;
5061 }
5062
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005063 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005064 // MipsAsmParser needs to know if the current PIC mode changes.
5065 IsPicEnabled = true;
5066
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005067 getTargetStreamer().emitDirectiveOptionPic2();
5068 Parser.Lex();
5069 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5070 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005071 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005072 Parser.eatToEndOfStatement();
5073 }
5074 return false;
5075 }
5076
Jack Carter0cd3c192014-01-06 23:27:31 +00005077 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005078 Warning(Parser.getTok().getLoc(),
5079 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005080 Parser.eatToEndOfStatement();
5081 return false;
5082}
5083
Toma Tabacu9ca50962015-04-16 09:53:47 +00005084/// parseInsnDirective
5085/// ::= .insn
5086bool MipsAsmParser::parseInsnDirective() {
5087 // If this is not the end of the statement, report an error.
5088 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5089 reportParseError("unexpected token, expected end of statement");
5090 return false;
5091 }
5092
5093 // The actual label marking happens in
5094 // MipsELFStreamer::createPendingLabelRelocs().
5095 getTargetStreamer().emitDirectiveInsn();
5096
5097 getParser().Lex(); // Eat EndOfStatement token.
5098 return false;
5099}
5100
Daniel Sanders7e527422014-07-10 13:38:23 +00005101/// parseDirectiveModule
5102/// ::= .module oddspreg
5103/// ::= .module nooddspreg
5104/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005105/// ::= .module softfloat
5106/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005107bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005108 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005109 MCAsmLexer &Lexer = getLexer();
5110 SMLoc L = Lexer.getLoc();
5111
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005112 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005113 // TODO : get a better message.
5114 reportParseError(".module directive must appear before any code");
5115 return false;
5116 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005117
Toma Tabacuc405c822015-01-23 10:40:19 +00005118 StringRef Option;
5119 if (Parser.parseIdentifier(Option)) {
5120 reportParseError("expected .module option identifier");
5121 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005122 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005123
Toma Tabacuc405c822015-01-23 10:40:19 +00005124 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005125 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005126
Toma Tabacu3c499582015-06-25 10:56:57 +00005127 // Synchronize the abiflags information with the FeatureBits information we
5128 // changed above.
5129 getTargetStreamer().updateABIInfo(*this);
5130
5131 // If printing assembly, use the recently updated abiflags information.
5132 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5133 // emitted at the end).
5134 getTargetStreamer().emitDirectiveModuleOddSPReg();
5135
Toma Tabacuc405c822015-01-23 10:40:19 +00005136 // If this is not the end of the statement, report an error.
5137 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5138 reportParseError("unexpected token, expected end of statement");
5139 return false;
5140 }
5141
5142 return false; // parseDirectiveModule has finished successfully.
5143 } else if (Option == "nooddspreg") {
5144 if (!isABI_O32()) {
5145 Error(L, "'.module nooddspreg' requires the O32 ABI");
5146 return false;
5147 }
5148
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005149 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005150
Toma Tabacu3c499582015-06-25 10:56:57 +00005151 // Synchronize the abiflags information with the FeatureBits information we
5152 // changed above.
5153 getTargetStreamer().updateABIInfo(*this);
5154
5155 // If printing assembly, use the recently updated abiflags information.
5156 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5157 // emitted at the end).
5158 getTargetStreamer().emitDirectiveModuleOddSPReg();
5159
Toma Tabacuc405c822015-01-23 10:40:19 +00005160 // If this is not the end of the statement, report an error.
5161 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5162 reportParseError("unexpected token, expected end of statement");
5163 return false;
5164 }
5165
5166 return false; // parseDirectiveModule has finished successfully.
5167 } else if (Option == "fp") {
5168 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005169 } else if (Option == "softfloat") {
5170 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5171
5172 // Synchronize the ABI Flags information with the FeatureBits information we
5173 // updated above.
5174 getTargetStreamer().updateABIInfo(*this);
5175
5176 // If printing assembly, use the recently updated ABI Flags information.
5177 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5178 // emitted later).
5179 getTargetStreamer().emitDirectiveModuleSoftFloat();
5180
5181 // If this is not the end of the statement, report an error.
5182 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5183 reportParseError("unexpected token, expected end of statement");
5184 return false;
5185 }
5186
5187 return false; // parseDirectiveModule has finished successfully.
5188 } else if (Option == "hardfloat") {
5189 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5190
5191 // Synchronize the ABI Flags information with the FeatureBits information we
5192 // updated above.
5193 getTargetStreamer().updateABIInfo(*this);
5194
5195 // If printing assembly, use the recently updated ABI Flags information.
5196 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5197 // emitted later).
5198 getTargetStreamer().emitDirectiveModuleHardFloat();
5199
5200 // If this is not the end of the statement, report an error.
5201 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5202 reportParseError("unexpected token, expected end of statement");
5203 return false;
5204 }
5205
5206 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005207 } else {
5208 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5209 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005210}
5211
5212/// parseDirectiveModuleFP
5213/// ::= =32
5214/// ::= =xx
5215/// ::= =64
5216bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005217 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005218 MCAsmLexer &Lexer = getLexer();
5219
5220 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005221 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005222 return false;
5223 }
5224 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005225
Daniel Sanders7e527422014-07-10 13:38:23 +00005226 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005227 if (!parseFpABIValue(FpABI, ".module"))
5228 return false;
5229
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005230 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005231 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005232 return false;
5233 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005234
Toma Tabacua64e5402015-06-25 12:44:38 +00005235 // Synchronize the abiflags information with the FeatureBits information we
5236 // changed above.
5237 getTargetStreamer().updateABIInfo(*this);
5238
5239 // If printing assembly, use the recently updated abiflags information.
5240 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5241 // emitted at the end).
5242 getTargetStreamer().emitDirectiveModuleFP();
5243
Daniel Sanders7e527422014-07-10 13:38:23 +00005244 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005245 return false;
5246}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005247
Daniel Sanders7e527422014-07-10 13:38:23 +00005248bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005249 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005250 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005251 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005252 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005253
5254 if (Lexer.is(AsmToken::Identifier)) {
5255 StringRef Value = Parser.getTok().getString();
5256 Parser.Lex();
5257
5258 if (Value != "xx") {
5259 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5260 return false;
5261 }
5262
5263 if (!isABI_O32()) {
5264 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5265 return false;
5266 }
5267
Daniel Sanders7e527422014-07-10 13:38:23 +00005268 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005269 if (ModuleLevelOptions) {
5270 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5271 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5272 } else {
5273 setFeatureBits(Mips::FeatureFPXX, "fpxx");
5274 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5275 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005276 return true;
5277 }
5278
5279 if (Lexer.is(AsmToken::Integer)) {
5280 unsigned Value = Parser.getTok().getIntVal();
5281 Parser.Lex();
5282
5283 if (Value != 32 && Value != 64) {
5284 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5285 return false;
5286 }
5287
5288 if (Value == 32) {
5289 if (!isABI_O32()) {
5290 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
5291 return false;
5292 }
5293
Daniel Sanders7e527422014-07-10 13:38:23 +00005294 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005295 if (ModuleLevelOptions) {
5296 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5297 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5298 } else {
5299 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5300 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5301 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005302 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00005303 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005304 if (ModuleLevelOptions) {
5305 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5306 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5307 } else {
5308 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5309 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
5310 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005311 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005312
Daniel Sanders7e527422014-07-10 13:38:23 +00005313 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005314 }
5315
5316 return false;
5317}
5318
Jack Carter0b744b32012-10-04 02:29:46 +00005319bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005320 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005321 StringRef IDVal = DirectiveID.getString();
5322
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005323 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005324 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00005325 if (IDVal == ".dword") {
5326 parseDataDirective(8, DirectiveID.getLoc());
5327 return false;
5328 }
Jack Carterd0bd6422013-04-18 00:41:53 +00005329 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005330 StringRef SymbolName;
5331
5332 if (Parser.parseIdentifier(SymbolName)) {
5333 reportParseError("expected identifier after .ent");
5334 return false;
5335 }
5336
5337 // There's an undocumented extension that allows an integer to
5338 // follow the name of the procedure which AFAICS is ignored by GAS.
5339 // Example: .ent foo,2
5340 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5341 if (getLexer().isNot(AsmToken::Comma)) {
5342 // Even though we accept this undocumented extension for compatibility
5343 // reasons, the additional integer argument does not actually change
5344 // the behaviour of the '.ent' directive, so we would like to discourage
5345 // its use. We do this by not referring to the extended version in
5346 // error messages which are not directly related to its use.
5347 reportParseError("unexpected token, expected end of statement");
5348 return false;
5349 }
5350 Parser.Lex(); // Eat the comma.
5351 const MCExpr *DummyNumber;
5352 int64_t DummyNumberVal;
5353 // If the user was explicitly trying to use the extended version,
5354 // we still give helpful extension-related error messages.
5355 if (Parser.parseExpression(DummyNumber)) {
5356 reportParseError("expected number after comma");
5357 return false;
5358 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00005359 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005360 reportParseError("expected an absolute expression after comma");
5361 return false;
5362 }
5363 }
5364
5365 // If this is not the end of the statement, report an error.
5366 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5367 reportParseError("unexpected token, expected end of statement");
5368 return false;
5369 }
5370
Jim Grosbach6f482002015-05-18 18:43:14 +00005371 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005372
5373 getTargetStreamer().emitDirectiveEnt(*Sym);
5374 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00005375 return false;
5376 }
5377
Jack Carter07c818d2013-01-25 01:31:34 +00005378 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005379 StringRef SymbolName;
5380
5381 if (Parser.parseIdentifier(SymbolName)) {
5382 reportParseError("expected identifier after .end");
5383 return false;
5384 }
5385
5386 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5387 reportParseError("unexpected token, expected end of statement");
5388 return false;
5389 }
5390
5391 if (CurrentFn == nullptr) {
5392 reportParseError(".end used without .ent");
5393 return false;
5394 }
5395
5396 if ((SymbolName != CurrentFn->getName())) {
5397 reportParseError(".end symbol does not match .ent symbol");
5398 return false;
5399 }
5400
5401 getTargetStreamer().emitDirectiveEnd(SymbolName);
5402 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00005403 return false;
5404 }
5405
Jack Carter07c818d2013-01-25 01:31:34 +00005406 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005407 // .frame $stack_reg, frame_size_in_bytes, $return_reg
5408 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005409 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005410 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5411 reportParseError("expected stack register");
5412 return false;
5413 }
5414
5415 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5416 if (!StackRegOpnd.isGPRAsmReg()) {
5417 reportParseError(StackRegOpnd.getStartLoc(),
5418 "expected general purpose register");
5419 return false;
5420 }
5421 unsigned StackReg = StackRegOpnd.getGPR32Reg();
5422
5423 if (Parser.getTok().is(AsmToken::Comma))
5424 Parser.Lex();
5425 else {
5426 reportParseError("unexpected token, expected comma");
5427 return false;
5428 }
5429
5430 // Parse the frame size.
5431 const MCExpr *FrameSize;
5432 int64_t FrameSizeVal;
5433
5434 if (Parser.parseExpression(FrameSize)) {
5435 reportParseError("expected frame size value");
5436 return false;
5437 }
5438
Jim Grosbach13760bd2015-05-30 01:25:56 +00005439 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005440 reportParseError("frame size not an absolute expression");
5441 return false;
5442 }
5443
5444 if (Parser.getTok().is(AsmToken::Comma))
5445 Parser.Lex();
5446 else {
5447 reportParseError("unexpected token, expected comma");
5448 return false;
5449 }
5450
5451 // Parse the return register.
5452 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00005453 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005454 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5455 reportParseError("expected return register");
5456 return false;
5457 }
5458
5459 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5460 if (!ReturnRegOpnd.isGPRAsmReg()) {
5461 reportParseError(ReturnRegOpnd.getStartLoc(),
5462 "expected general purpose register");
5463 return false;
5464 }
5465
5466 // If this is not the end of the statement, report an error.
5467 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5468 reportParseError("unexpected token, expected end of statement");
5469 return false;
5470 }
5471
5472 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
5473 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00005474 return false;
5475 }
5476
Jack Carter07c818d2013-01-25 01:31:34 +00005477 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00005478 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00005479 }
5480
Daniel Sandersd97a6342014-08-13 10:07:34 +00005481 if (IDVal == ".mask" || IDVal == ".fmask") {
5482 // .mask bitmask, frame_offset
5483 // bitmask: One bit for each register used.
5484 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
5485 // first register is expected to be saved.
5486 // Examples:
5487 // .mask 0x80000000, -4
5488 // .fmask 0x80000000, -4
5489 //
Jack Carterbe332172012-09-07 00:48:02 +00005490
Daniel Sandersd97a6342014-08-13 10:07:34 +00005491 // Parse the bitmask
5492 const MCExpr *BitMask;
5493 int64_t BitMaskVal;
5494
5495 if (Parser.parseExpression(BitMask)) {
5496 reportParseError("expected bitmask value");
5497 return false;
5498 }
5499
Jim Grosbach13760bd2015-05-30 01:25:56 +00005500 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005501 reportParseError("bitmask not an absolute expression");
5502 return false;
5503 }
5504
5505 if (Parser.getTok().is(AsmToken::Comma))
5506 Parser.Lex();
5507 else {
5508 reportParseError("unexpected token, expected comma");
5509 return false;
5510 }
5511
5512 // Parse the frame_offset
5513 const MCExpr *FrameOffset;
5514 int64_t FrameOffsetVal;
5515
5516 if (Parser.parseExpression(FrameOffset)) {
5517 reportParseError("expected frame offset value");
5518 return false;
5519 }
5520
Jim Grosbach13760bd2015-05-30 01:25:56 +00005521 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005522 reportParseError("frame offset not an absolute expression");
5523 return false;
5524 }
5525
5526 // If this is not the end of the statement, report an error.
5527 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5528 reportParseError("unexpected token, expected end of statement");
5529 return false;
5530 }
5531
5532 if (IDVal == ".mask")
5533 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
5534 else
5535 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00005536 return false;
5537 }
5538
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005539 if (IDVal == ".nan")
5540 return parseDirectiveNaN();
5541
Jack Carter07c818d2013-01-25 01:31:34 +00005542 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005543 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00005544 return false;
5545 }
5546
Rafael Espindolab59fb732014-03-28 18:50:26 +00005547 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005548 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005549 return false;
5550 }
5551
Jack Carter07c818d2013-01-25 01:31:34 +00005552 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005553 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00005554 return false;
5555 }
5556
Jack Carter0cd3c192014-01-06 23:27:31 +00005557 if (IDVal == ".option")
5558 return parseDirectiveOption();
5559
5560 if (IDVal == ".abicalls") {
5561 getTargetStreamer().emitDirectiveAbiCalls();
5562 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005563 Error(Parser.getTok().getLoc(),
5564 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005565 // Clear line
5566 Parser.eatToEndOfStatement();
5567 }
5568 return false;
5569 }
5570
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005571 if (IDVal == ".cpsetup")
5572 return parseDirectiveCPSetup();
5573
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005574 if (IDVal == ".module")
5575 return parseDirectiveModule();
5576
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005577 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
5578 return parseInternalDirectiveReallowModule();
5579
Toma Tabacu9ca50962015-04-16 09:53:47 +00005580 if (IDVal == ".insn")
5581 return parseInsnDirective();
5582
Rafael Espindola870c4e92012-01-11 03:56:41 +00005583 return true;
5584}
5585
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005586bool MipsAsmParser::parseInternalDirectiveReallowModule() {
5587 // If this is not the end of the statement, report an error.
5588 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5589 reportParseError("unexpected token, expected end of statement");
5590 return false;
5591 }
5592
5593 getTargetStreamer().reallowModuleDirective();
5594
5595 getParser().Lex(); // Eat EndOfStatement token.
5596 return false;
5597}
5598
Rafael Espindola870c4e92012-01-11 03:56:41 +00005599extern "C" void LLVMInitializeMipsAsmParser() {
5600 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
5601 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
5602 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
5603 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
5604}
Jack Carterb4dbc172012-09-05 23:34:03 +00005605
5606#define GET_REGISTER_MATCHER
5607#define GET_MATCHER_IMPLEMENTATION
5608#include "MipsGenAsmMatcher.inc"