blob: f43e8f0fe36bd879063e08c7efdf592fd41b7ae2 [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;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000119 bool IsCpRestoreSet;
120 int CpRestoreOffset;
Daniel Sandersf173dda2015-09-22 10:50:09 +0000121 unsigned CpSaveLocation;
122 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
123 bool CpSaveLocationIsRegister;
Jack Carter0b744b32012-10-04 02:29:46 +0000124
Daniel Sandersef638fe2014-10-03 15:37:37 +0000125 // Print a warning along with its fix-it message at the given range.
126 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
127 SMRange Range, bool ShowColors = true);
128
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000129#define GET_ASSEMBLER_HEADER
130#include "MipsGenAsmMatcher.inc"
131
Matheus Almeida595fcab2014-06-11 15:05:56 +0000132 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
133
Chad Rosier49963552012-10-13 00:26:04 +0000134 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000135 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000136 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000137 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000138
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000139 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000140 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000141
Toma Tabacu13964452014-09-04 13:23:44 +0000142 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000143
Toma Tabacu13964452014-09-04 13:23:44 +0000144 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000145
David Blaikie960ea3f2014-06-08 16:18:35 +0000146 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
147 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000148
Craig Topper56c590a2014-04-29 07:58:02 +0000149 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000150
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000151 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
152 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000153 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000154 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000155 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
156 SMLoc S);
157 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
158 OperandMatchResultTy parseImm(OperandVector &Operands);
159 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
160 OperandMatchResultTy parseInvNum(OperandVector &Operands);
161 OperandMatchResultTy parseLSAImm(OperandVector &Operands);
162 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
163 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
164 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000165
David Blaikie960ea3f2014-06-08 16:18:35 +0000166 bool searchSymbolAlias(OperandVector &Operands);
167
Toma Tabacu13964452014-09-04 13:23:44 +0000168 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000169
Jack Carter30a59822012-10-04 04:03:53 +0000170 bool needsExpansion(MCInst &Inst);
171
Matheus Almeida3813d572014-06-19 14:39:14 +0000172 // Expands assembly pseudo instructions.
173 // Returns false on success, true otherwise.
174 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000175 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000176
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000177 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
178 SmallVectorImpl<MCInst> &Instructions);
179
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000180 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000181 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000182 SmallVectorImpl<MCInst> &Instructions);
183
Toma Tabacuf712ede2015-06-17 14:31:51 +0000184 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
185 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
186 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacu674825c2015-06-16 12:16:24 +0000187
Toma Tabacu00e98672015-05-01 12:19:27 +0000188 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000189 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000190
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000191 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
192 const MCOperand &Offset, bool Is32BitAddress,
193 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000194
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000195 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
196 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000197
Jack Carter9e65aa32013-03-22 00:05:30 +0000198 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000199 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
200 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000201
202 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
203 SmallVectorImpl<MCInst> &Instructions);
204
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000205 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
206 SmallVectorImpl<MCInst> &Instructions);
207
Toma Tabacue1e460d2015-06-11 10:36:10 +0000208 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc,
209 SmallVectorImpl<MCInst> &Instructions);
210
Toma Tabacu1a108322015-06-17 13:20:24 +0000211 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc,
212 SmallVectorImpl<MCInst> &Instructions);
213
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000214 bool expandDiv(MCInst &Inst, SMLoc IDLoc,
215 SmallVectorImpl<MCInst> &Instructions, const bool IsMips64,
216 const bool Signed);
217
Toma Tabacud88d79c2015-06-23 14:39:42 +0000218 bool expandUlhu(MCInst &Inst, SMLoc IDLoc,
219 SmallVectorImpl<MCInst> &Instructions);
220
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000221 bool expandUlw(MCInst &Inst, SMLoc IDLoc,
222 SmallVectorImpl<MCInst> &Instructions);
223
Toma Tabacu234482a2015-03-16 12:03:39 +0000224 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
225 SmallVectorImpl<MCInst> &Instructions);
226
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000227 void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +0000228 bool Is64Bit, SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000229
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000230 void createCpRestoreMemOp(bool IsLoad, int StackOffset, SMLoc IDLoc,
231 SmallVectorImpl<MCInst> &Instructions);
232
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000233 bool reportParseError(Twine ErrorMsg);
234 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000235
Jack Carterb5cf5902013-04-17 00:18:04 +0000236 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000237 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000238
Vladimir Medic4c299852013-11-06 11:27:05 +0000239 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000240
241 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000242 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000243 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000244 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000245 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000246 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000247 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000248 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000249 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000250 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000251 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000252 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000253 bool parseInsnDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000254
255 bool parseSetAtDirective();
256 bool parseSetNoAtDirective();
257 bool parseSetMacroDirective();
258 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000259 bool parseSetMsaDirective();
260 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000261 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000262 bool parseSetReorderDirective();
263 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000264 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000265 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000266 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000267 bool parseSetOddSPRegDirective();
268 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000269 bool parseSetPopDirective();
270 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000271 bool parseSetSoftFloatDirective();
272 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000273
Jack Carterd76b2372013-03-21 21:44:16 +0000274 bool parseSetAssignment();
275
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000276 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000277 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000278 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000279 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000280 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000281 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
282 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000283
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000284 bool parseInternalDirectiveReallowModule();
285
Jack Carterdc1e35d2012-09-06 20:00:02 +0000286 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000287
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000288 bool eatComma(StringRef ErrorStr);
289
Jack Carter1ac53222013-02-20 23:11:17 +0000290 int matchCPURegisterName(StringRef Symbol);
291
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000292 int matchHWRegsRegisterName(StringRef Symbol);
293
Jack Carter873c7242013-01-12 01:03:14 +0000294 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000295
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000296 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000297
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000298 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000299
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000300 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000301
Jack Carter5dc8ac92013-09-25 23:50:44 +0000302 int matchMSA128RegisterName(StringRef Name);
303
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000304 int matchMSA128CtrlRegisterName(StringRef Name);
305
Jack Carterd0bd6422013-04-18 00:41:53 +0000306 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000307
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000308 unsigned getGPR(int RegNo);
309
Toma Tabacu89a712b2015-04-15 10:48:56 +0000310 /// Returns the internal register number for the current AT. Also checks if
311 /// the current AT is unavailable (set to $0) and gives an error if it is.
312 /// This should be used in pseudo-instruction expansions which need AT.
313 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000314
315 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000316 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000317
318 // Helper function that checks if the value of a vector index is within the
319 // boundaries of accepted values for each RegisterKind
320 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
321 bool validateMSAIndex(int Val, int RegKind);
322
Daniel Sandersf0df2212014-08-04 12:20:00 +0000323 // Selects a new architecture by updating the FeatureBits with the necessary
324 // info including implied dependencies.
325 // Internally, it clears all the feature bits related to *any* architecture
326 // and selects the new one using the ToggleFeature functionality of the
327 // MCSubtargetInfo object that handles implied dependencies. The reason we
328 // clear all the arch related bits manually is because ToggleFeature only
329 // clears the features that imply the feature being cleared and not the
330 // features implied by the feature being cleared. This is easier to see
331 // with an example:
332 // --------------------------------------------------
333 // | Feature | Implies |
334 // | -------------------------------------------------|
335 // | FeatureMips1 | None |
336 // | FeatureMips2 | FeatureMips1 |
337 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
338 // | FeatureMips4 | FeatureMips3 |
339 // | ... | |
340 // --------------------------------------------------
341 //
342 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
343 // FeatureMipsGP64 | FeatureMips1)
344 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
345 void selectArch(StringRef ArchFeature) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000346 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000347 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
348 STI.setFeatureBits(FeatureBits);
349 setAvailableFeatures(
350 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000351 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000352 }
353
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000354 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000355 if (!(STI.getFeatureBits()[Feature])) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000356 setAvailableFeatures(
357 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000358 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000359 }
360 }
361
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000362 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000363 if (STI.getFeatureBits()[Feature]) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000364 setAvailableFeatures(
365 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000366 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000367 }
368 }
369
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000370 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
371 setFeatureBits(Feature, FeatureString);
372 AssemblerOptions.front()->setFeatures(STI.getFeatureBits());
373 }
374
375 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
376 clearFeatureBits(Feature, FeatureString);
377 AssemblerOptions.front()->setFeatures(STI.getFeatureBits());
378 }
379
Rafael Espindola870c4e92012-01-11 03:56:41 +0000380public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000381 enum MipsMatchResultTy {
382 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
383#define GET_OPERAND_DIAGNOSTIC_TYPES
384#include "MipsGenAsmMatcher.inc"
385#undef GET_OPERAND_DIAGNOSTIC_TYPES
386
387 };
388
Joey Gouly0e76fa72013-09-12 10:28:05 +0000389 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000390 const MCInstrInfo &MII, const MCTargetOptions &Options)
Colin LeMahieufe2c8b82015-07-27 21:56:53 +0000391 : MCTargetAsmParser(Options), STI(sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000392 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
393 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000394 MCAsmParserExtension::Initialize(parser);
395
Toma Tabacu11e14a92015-04-21 11:50:52 +0000396 parser.addAliasForDirective(".asciiz", ".asciz");
397
Jack Carterb4dbc172012-09-05 23:34:03 +0000398 // Initialize the set of available features.
399 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000400
Toma Tabacu9db22db2014-09-09 10:15:38 +0000401 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000402 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000403 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000404
Toma Tabacu9db22db2014-09-09 10:15:38 +0000405 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000406 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000407 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000408
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000409 getTargetStreamer().updateABIInfo(*this);
410
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000411 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000412 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000413
414 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000415
Daniel Sandersa6994442015-08-18 12:33:54 +0000416 IsPicEnabled =
417 (getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_);
418
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000419 IsCpRestoreSet = false;
420 CpRestoreOffset = -1;
421
Daniel Sanders50f17232015-09-15 16:17:27 +0000422 Triple TheTriple(sti.getTargetTriple());
423 if ((TheTriple.getArch() == Triple::mips) ||
424 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000425 IsLittleEndian = false;
426 else
427 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000428 }
429
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000430 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
431 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
432
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000433 bool isGP64bit() const { return STI.getFeatureBits()[Mips::FeatureGP64Bit]; }
434 bool isFP64bit() const { return STI.getFeatureBits()[Mips::FeatureFP64Bit]; }
Eric Christophera5762812015-01-26 17:33:46 +0000435 const MipsABIInfo &getABI() const { return ABI; }
436 bool isABI_N32() const { return ABI.IsN32(); }
437 bool isABI_N64() const { return ABI.IsN64(); }
438 bool isABI_O32() const { return ABI.IsO32(); }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000439 bool isABI_FPXX() const { return STI.getFeatureBits()[Mips::FeatureFPXX]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000440
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000441 bool useOddSPReg() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000442 return !(STI.getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000443 }
444
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000445 bool inMicroMipsMode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000446 return STI.getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000447 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000448 bool hasMips1() const { return STI.getFeatureBits()[Mips::FeatureMips1]; }
449 bool hasMips2() const { return STI.getFeatureBits()[Mips::FeatureMips2]; }
450 bool hasMips3() const { return STI.getFeatureBits()[Mips::FeatureMips3]; }
451 bool hasMips4() const { return STI.getFeatureBits()[Mips::FeatureMips4]; }
452 bool hasMips5() const { return STI.getFeatureBits()[Mips::FeatureMips5]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000453 bool hasMips32() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000454 return STI.getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000455 }
456 bool hasMips64() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000457 return STI.getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000458 }
459 bool hasMips32r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000460 return STI.getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000461 }
462 bool hasMips64r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000463 return STI.getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000464 }
Daniel Sanders17793142015-02-18 16:24:50 +0000465 bool hasMips32r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000466 return (STI.getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000467 }
468 bool hasMips64r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000469 return (STI.getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000470 }
471 bool hasMips32r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000472 return (STI.getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000473 }
474 bool hasMips64r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000475 return (STI.getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000476 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000477 bool hasMips32r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000478 return STI.getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000479 }
480 bool hasMips64r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000481 return STI.getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000482 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000483
484 bool hasDSP() const { return STI.getFeatureBits()[Mips::FeatureDSP]; }
485 bool hasDSPR2() const { return STI.getFeatureBits()[Mips::FeatureDSPR2]; }
486 bool hasMSA() const { return STI.getFeatureBits()[Mips::FeatureMSA]; }
Kai Nackee0245392015-01-27 19:11:28 +0000487 bool hasCnMips() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000488 return (STI.getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000489 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000490
Daniel Sandersa6994442015-08-18 12:33:54 +0000491 bool inPicMode() {
492 return IsPicEnabled;
493 }
494
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000495 bool inMips16Mode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000496 return STI.getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000497 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000498
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000499 bool useTraps() const {
500 return STI.getFeatureBits()[Mips::FeatureUseTCCInDIV];
501 }
502
Eric Christophere8ae3e32015-05-07 23:10:21 +0000503 bool useSoftFloat() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000504 return STI.getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000505 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000506
Toma Tabacud9d344b2015-04-27 14:05:04 +0000507 /// Warn if RegIndex is the same as the current AT.
508 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000509
510 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000511
512 bool isLittle() const { return IsLittleEndian; }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000513};
514}
515
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000516namespace {
517
518/// MipsOperand - Instances of this class represent a parsed Mips machine
519/// instruction.
520class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000521public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000522 /// Broad categories of register classes
523 /// The exact class is finalized by the render method.
524 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000525 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000526 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000527 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000528 RegKind_FCC = 4, /// FCC
529 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
530 RegKind_MSACtrl = 16, /// MSA control registers
531 RegKind_COP2 = 32, /// COP2
532 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
533 /// context).
534 RegKind_CCR = 128, /// CCR
535 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000536 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000537 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000538 /// Potentially any (e.g. $1)
539 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
540 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000541 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000542 };
543
544private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000545 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000546 k_Immediate, /// An immediate (possibly involving symbol references)
547 k_Memory, /// Base + Offset Memory Address
548 k_PhysRegister, /// A physical register from the Mips namespace
549 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000550 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000551 k_RegList, /// A physical register list
552 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000553 } Kind;
554
David Blaikie960ea3f2014-06-08 16:18:35 +0000555public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000556 MipsOperand(KindTy K, MipsAsmParser &Parser)
557 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
558
David Blaikie960ea3f2014-06-08 16:18:35 +0000559private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000560 /// For diagnostics, and checking the assembler temporary
561 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000562
Eric Christopher8996c5d2013-03-15 00:42:55 +0000563 struct Token {
564 const char *Data;
565 unsigned Length;
566 };
567
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000568 struct PhysRegOp {
569 unsigned Num; /// Register Number
570 };
571
572 struct RegIdxOp {
573 unsigned Index; /// Index into the register class
574 RegKind Kind; /// Bitfield of the kinds it could possibly be
575 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000576 };
577
578 struct ImmOp {
579 const MCExpr *Val;
580 };
581
582 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000583 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000584 const MCExpr *Off;
585 };
586
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000587 struct RegListOp {
588 SmallVector<unsigned, 10> *List;
589 };
590
Jack Carterb4dbc172012-09-05 23:34:03 +0000591 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000592 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000593 struct PhysRegOp PhysReg;
594 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000595 struct ImmOp Imm;
596 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000597 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000598 };
599
600 SMLoc StartLoc, EndLoc;
601
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000602 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000603 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
604 const MCRegisterInfo *RegInfo,
605 SMLoc S, SMLoc E,
606 MipsAsmParser &Parser) {
607 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000608 Op->RegIdx.Index = Index;
609 Op->RegIdx.RegInfo = RegInfo;
610 Op->RegIdx.Kind = RegKind;
611 Op->StartLoc = S;
612 Op->EndLoc = E;
613 return Op;
614 }
615
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000616public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000617 /// Coerce the register to GPR32 and return the real register for the current
618 /// target.
619 unsigned getGPR32Reg() const {
620 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000621 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000622 unsigned ClassID = Mips::GPR32RegClassID;
623 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000624 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000625
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000626 /// Coerce the register to GPR32 and return the real register for the current
627 /// target.
628 unsigned getGPRMM16Reg() const {
629 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
630 unsigned ClassID = Mips::GPR32RegClassID;
631 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
632 }
633
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000634 /// Coerce the register to GPR64 and return the real register for the current
635 /// target.
636 unsigned getGPR64Reg() const {
637 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
638 unsigned ClassID = Mips::GPR64RegClassID;
639 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000640 }
641
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000642private:
643 /// Coerce the register to AFGR64 and return the real register for the current
644 /// target.
645 unsigned getAFGR64Reg() const {
646 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
647 if (RegIdx.Index % 2 != 0)
648 AsmParser.Warning(StartLoc, "Float register should be even.");
649 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
650 .getRegister(RegIdx.Index / 2);
651 }
652
653 /// Coerce the register to FGR64 and return the real register for the current
654 /// target.
655 unsigned getFGR64Reg() const {
656 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
657 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
658 .getRegister(RegIdx.Index);
659 }
660
661 /// Coerce the register to FGR32 and return the real register for the current
662 /// target.
663 unsigned getFGR32Reg() const {
664 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
665 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
666 .getRegister(RegIdx.Index);
667 }
668
669 /// Coerce the register to FGRH32 and return the real register for the current
670 /// target.
671 unsigned getFGRH32Reg() const {
672 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
673 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
674 .getRegister(RegIdx.Index);
675 }
676
677 /// Coerce the register to FCC and return the real register for the current
678 /// target.
679 unsigned getFCCReg() const {
680 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
681 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
682 .getRegister(RegIdx.Index);
683 }
684
685 /// Coerce the register to MSA128 and return the real register for the current
686 /// target.
687 unsigned getMSA128Reg() const {
688 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
689 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
690 // identical
691 unsigned ClassID = Mips::MSA128BRegClassID;
692 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
693 }
694
695 /// Coerce the register to MSACtrl and return the real register for the
696 /// current target.
697 unsigned getMSACtrlReg() const {
698 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
699 unsigned ClassID = Mips::MSACtrlRegClassID;
700 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
701 }
702
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000703 /// Coerce the register to COP0 and return the real register for the
704 /// current target.
705 unsigned getCOP0Reg() const {
706 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
707 unsigned ClassID = Mips::COP0RegClassID;
708 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
709 }
710
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000711 /// Coerce the register to COP2 and return the real register for the
712 /// current target.
713 unsigned getCOP2Reg() const {
714 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
715 unsigned ClassID = Mips::COP2RegClassID;
716 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
717 }
718
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000719 /// Coerce the register to COP3 and return the real register for the
720 /// current target.
721 unsigned getCOP3Reg() const {
722 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
723 unsigned ClassID = Mips::COP3RegClassID;
724 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
725 }
726
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000727 /// Coerce the register to ACC64DSP and return the real register for the
728 /// current target.
729 unsigned getACC64DSPReg() const {
730 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
731 unsigned ClassID = Mips::ACC64DSPRegClassID;
732 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
733 }
734
735 /// Coerce the register to HI32DSP and return the real register for the
736 /// current target.
737 unsigned getHI32DSPReg() const {
738 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
739 unsigned ClassID = Mips::HI32DSPRegClassID;
740 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
741 }
742
743 /// Coerce the register to LO32DSP and return the real register for the
744 /// current target.
745 unsigned getLO32DSPReg() const {
746 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
747 unsigned ClassID = Mips::LO32DSPRegClassID;
748 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
749 }
750
751 /// Coerce the register to CCR and return the real register for the
752 /// current target.
753 unsigned getCCRReg() const {
754 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
755 unsigned ClassID = Mips::CCRRegClassID;
756 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
757 }
758
759 /// Coerce the register to HWRegs and return the real register for the
760 /// current target.
761 unsigned getHWRegsReg() const {
762 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
763 unsigned ClassID = Mips::HWRegsRegClassID;
764 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
765 }
766
767public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000768 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000769 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000770 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000771 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000772 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000773 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000774 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000775 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000776 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000777
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000778 void addRegOperands(MCInst &Inst, unsigned N) const {
779 llvm_unreachable("Use a custom parser instead");
780 }
781
Daniel Sanders21bce302014-04-01 12:35:23 +0000782 /// Render the operand to an MCInst as a GPR32
783 /// Asserts if the wrong number of operands are requested, or the operand
784 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000785 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
786 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000787 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000788 }
789
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000790 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
791 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000792 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000793 }
794
Jozef Kolek1904fa22014-11-24 14:25:53 +0000795 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
796 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000797 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000798 }
799
Zoran Jovanovic41688672015-02-10 16:36:20 +0000800 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
801 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000802 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000803 }
804
Daniel Sanders21bce302014-04-01 12:35:23 +0000805 /// Render the operand to an MCInst as a GPR64
806 /// Asserts if the wrong number of operands are requested, or the operand
807 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000808 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
809 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000810 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000811 }
812
813 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
814 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000815 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000816 }
817
818 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
819 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000820 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000821 }
822
823 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
824 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000825 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000826 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000827 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000828 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
829 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000830 }
831
832 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
833 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000834 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000835 }
836
837 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
838 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000839 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000840 }
841
842 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
843 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000844 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000845 }
846
847 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
848 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000849 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000850 }
851
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000852 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
853 assert(N == 1 && "Invalid number of operands!");
854 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
855 }
856
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000857 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
858 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000859 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000860 }
861
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000862 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
863 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000864 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000865 }
866
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000867 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
868 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000869 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000870 }
871
872 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
873 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000874 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000875 }
876
877 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
878 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000879 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000880 }
881
882 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
883 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000884 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000885 }
886
887 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
888 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000889 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000890 }
891
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000892 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000893 assert(N == 1 && "Invalid number of operands!");
894 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000895 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000896 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000897
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000898 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000899 assert(N == 2 && "Invalid number of operands!");
900
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000901 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
902 ? getMemBase()->getGPR64Reg()
903 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000904
905 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000906 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000907 }
908
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000909 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
910 assert(N == 2 && "Invalid number of operands!");
911
Jim Grosbache9119e42015-05-13 18:37:00 +0000912 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000913
914 const MCExpr *Expr = getMemOff();
915 addExpr(Inst, Expr);
916 }
917
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000918 void addRegListOperands(MCInst &Inst, unsigned N) const {
919 assert(N == 1 && "Invalid number of operands!");
920
921 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000922 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000923 }
924
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000925 void addRegPairOperands(MCInst &Inst, unsigned N) const {
926 assert(N == 2 && "Invalid number of operands!");
927 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +0000928 Inst.addOperand(MCOperand::createReg(RegNo++));
929 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000930 }
931
Zoran Jovanovic41688672015-02-10 16:36:20 +0000932 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
933 assert(N == 2 && "Invalid number of operands!");
934 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000935 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000936 }
937
Craig Topper56c590a2014-04-29 07:58:02 +0000938 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000939 // As a special case until we sort out the definition of div/divu, pretend
940 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
941 if (isGPRAsmReg() && RegIdx.Index == 0)
942 return true;
943
944 return Kind == k_PhysRegister;
945 }
946 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000947 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000948 bool isConstantImm() const {
949 return isImm() && dyn_cast<MCConstantExpr>(getImm());
950 }
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +0000951 template <unsigned Bits> bool isUImm() const {
952 return isImm() && isConstantImm() && isUInt<Bits>(getConstantImm());
953 }
Craig Topper56c590a2014-04-29 07:58:02 +0000954 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000955 // Note: It's not possible to pretend that other operand kinds are tokens.
956 // The matcher emitter checks tokens first.
957 return Kind == k_Token;
958 }
Craig Topper56c590a2014-04-29 07:58:02 +0000959 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000960 bool isConstantMemOff() const {
961 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
962 }
963 template <unsigned Bits> bool isMemWithSimmOffset() const {
Zoran Jovanovica6593ff2015-08-18 12:53:08 +0000964 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
965 && getMemBase()->isGPRAsmReg();
966 }
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +0000967 template <unsigned Bits> bool isMemWithSimmOffsetGPR() const {
968 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) &&
969 getMemBase()->isGPRAsmReg();
970 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000971 bool isMemWithGRPMM16Base() const {
972 return isMem() && getMemBase()->isMM16AsmReg();
973 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000974 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
975 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
976 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
977 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000978 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
979 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
980 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
981 && (getMemBase()->getGPR32Reg() == Mips::SP);
982 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000983 bool isRegList16() const {
984 if (!isRegList())
985 return false;
986
987 int Size = RegList.List->size();
988 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
989 RegList.List->back() != Mips::RA)
990 return false;
991
992 int PrevReg = *RegList.List->begin();
993 for (int i = 1; i < Size - 1; i++) {
994 int Reg = (*(RegList.List))[i];
995 if ( Reg != PrevReg + 1)
996 return false;
997 PrevReg = Reg;
998 }
999
1000 return true;
1001 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001002 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001003 bool isLSAImm() const {
1004 if (!isConstantImm())
1005 return false;
1006 int64_t Val = getConstantImm();
1007 return 1 <= Val && Val <= 4;
1008 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001009 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001010 bool isMovePRegPair() const {
1011 if (Kind != k_RegList || RegList.List->size() != 2)
1012 return false;
1013
1014 unsigned R0 = RegList.List->front();
1015 unsigned R1 = RegList.List->back();
1016
1017 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1018 (R0 == Mips::A1 && R1 == Mips::A3) ||
1019 (R0 == Mips::A2 && R1 == Mips::A3) ||
1020 (R0 == Mips::A0 && R1 == Mips::S5) ||
1021 (R0 == Mips::A0 && R1 == Mips::S6) ||
1022 (R0 == Mips::A0 && R1 == Mips::A1) ||
1023 (R0 == Mips::A0 && R1 == Mips::A2) ||
1024 (R0 == Mips::A0 && R1 == Mips::A3))
1025 return true;
1026
1027 return false;
1028 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001029
1030 StringRef getToken() const {
1031 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001032 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001033 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001034 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001035
Craig Topper56c590a2014-04-29 07:58:02 +00001036 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001037 // As a special case until we sort out the definition of div/divu, pretend
1038 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1039 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1040 RegIdx.Kind & RegKind_GPR)
1041 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001042
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001043 assert(Kind == k_PhysRegister && "Invalid access!");
1044 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001045 }
1046
Jack Carterb4dbc172012-09-05 23:34:03 +00001047 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001048 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001049 return Imm.Val;
1050 }
1051
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001052 int64_t getConstantImm() const {
1053 const MCExpr *Val = getImm();
1054 return static_cast<const MCConstantExpr *>(Val)->getValue();
1055 }
1056
1057 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001058 assert((Kind == k_Memory) && "Invalid access!");
1059 return Mem.Base;
1060 }
1061
1062 const MCExpr *getMemOff() const {
1063 assert((Kind == k_Memory) && "Invalid access!");
1064 return Mem.Off;
1065 }
1066
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001067 int64_t getConstantMemOff() const {
1068 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1069 }
1070
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001071 const SmallVectorImpl<unsigned> &getRegList() const {
1072 assert((Kind == k_RegList) && "Invalid access!");
1073 return *(RegList.List);
1074 }
1075
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001076 unsigned getRegPair() const {
1077 assert((Kind == k_RegPair) && "Invalid access!");
1078 return RegIdx.Index;
1079 }
1080
David Blaikie960ea3f2014-06-08 16:18:35 +00001081 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1082 MipsAsmParser &Parser) {
1083 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001084 Op->Tok.Data = Str.data();
1085 Op->Tok.Length = Str.size();
1086 Op->StartLoc = S;
1087 Op->EndLoc = S;
1088 return Op;
1089 }
1090
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001091 /// Create a numeric register (e.g. $1). The exact register remains
1092 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001093 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001094 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001095 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001096 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001097 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001098 }
1099
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001100 /// Create a register that is definitely a GPR.
1101 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001102 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001103 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001104 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001105 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001106 }
1107
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001108 /// Create a register that is definitely a FGR.
1109 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001110 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001111 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001112 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001113 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1114 }
1115
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001116 /// Create a register that is definitely a HWReg.
1117 /// This is typically only used for named registers such as $hwr_cpunum.
1118 static std::unique_ptr<MipsOperand>
1119 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1120 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1121 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1122 }
1123
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001124 /// Create a register that is definitely an FCC.
1125 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001126 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001127 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001128 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001129 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1130 }
1131
1132 /// Create a register that is definitely an ACC.
1133 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001134 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001135 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001136 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001137 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1138 }
1139
1140 /// Create a register that is definitely an MSA128.
1141 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001142 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001143 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001144 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001145 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1146 }
1147
1148 /// Create a register that is definitely an MSACtrl.
1149 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001150 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001151 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001152 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001153 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1154 }
1155
David Blaikie960ea3f2014-06-08 16:18:35 +00001156 static std::unique_ptr<MipsOperand>
1157 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1158 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001159 Op->Imm.Val = Val;
1160 Op->StartLoc = S;
1161 Op->EndLoc = E;
1162 return Op;
1163 }
1164
David Blaikie960ea3f2014-06-08 16:18:35 +00001165 static std::unique_ptr<MipsOperand>
1166 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1167 SMLoc E, MipsAsmParser &Parser) {
1168 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1169 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001170 Op->Mem.Off = Off;
1171 Op->StartLoc = S;
1172 Op->EndLoc = E;
1173 return Op;
1174 }
1175
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001176 static std::unique_ptr<MipsOperand>
1177 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1178 MipsAsmParser &Parser) {
1179 assert (Regs.size() > 0 && "Empty list not allowed");
1180
1181 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001182 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001183 Op->StartLoc = StartLoc;
1184 Op->EndLoc = EndLoc;
1185 return Op;
1186 }
1187
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001188 static std::unique_ptr<MipsOperand>
1189 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1190 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1191 Op->RegIdx.Index = RegNo;
1192 Op->StartLoc = S;
1193 Op->EndLoc = E;
1194 return Op;
1195 }
1196
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001197 bool isGPRAsmReg() const {
1198 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001199 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001200 bool isMM16AsmReg() const {
1201 if (!(isRegIdx() && RegIdx.Kind))
1202 return false;
1203 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1204 || RegIdx.Index == 16 || RegIdx.Index == 17);
1205 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001206 bool isMM16AsmRegZero() const {
1207 if (!(isRegIdx() && RegIdx.Kind))
1208 return false;
1209 return (RegIdx.Index == 0 ||
1210 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1211 RegIdx.Index == 17);
1212 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001213 bool isMM16AsmRegMoveP() const {
1214 if (!(isRegIdx() && RegIdx.Kind))
1215 return false;
1216 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1217 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1218 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001219 bool isFGRAsmReg() const {
1220 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1221 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001222 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001223 bool isHWRegsAsmReg() const {
1224 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001225 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001226 bool isCCRAsmReg() const {
1227 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001228 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001229 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001230 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1231 return false;
1232 if (!AsmParser.hasEightFccRegisters())
1233 return RegIdx.Index == 0;
1234 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001235 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001236 bool isACCAsmReg() const {
1237 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001238 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001239 bool isCOP0AsmReg() const {
1240 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1241 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001242 bool isCOP2AsmReg() const {
1243 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001244 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001245 bool isCOP3AsmReg() const {
1246 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1247 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001248 bool isMSA128AsmReg() const {
1249 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001250 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001251 bool isMSACtrlAsmReg() const {
1252 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001253 }
1254
Jack Carterb4dbc172012-09-05 23:34:03 +00001255 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001256 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001257 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001258 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001259
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001260 virtual ~MipsOperand() {
1261 switch (Kind) {
1262 case k_Immediate:
1263 break;
1264 case k_Memory:
1265 delete Mem.Base;
1266 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001267 case k_RegList:
1268 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001269 case k_PhysRegister:
1270 case k_RegisterIndex:
1271 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001272 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001273 break;
1274 }
1275 }
1276
Craig Topper56c590a2014-04-29 07:58:02 +00001277 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001278 switch (Kind) {
1279 case k_Immediate:
1280 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001281 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001282 OS << ">";
1283 break;
1284 case k_Memory:
1285 OS << "Mem<";
1286 Mem.Base->print(OS);
1287 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001288 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001289 OS << ">";
1290 break;
1291 case k_PhysRegister:
1292 OS << "PhysReg<" << PhysReg.Num << ">";
1293 break;
1294 case k_RegisterIndex:
1295 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1296 break;
1297 case k_Token:
1298 OS << Tok.Data;
1299 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001300 case k_RegList:
1301 OS << "RegList< ";
1302 for (auto Reg : (*RegList.List))
1303 OS << Reg << " ";
1304 OS << ">";
1305 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001306 case k_RegPair:
1307 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1308 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001309 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001310 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001311}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001312} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001313
Jack Carter9e65aa32013-03-22 00:05:30 +00001314namespace llvm {
1315extern const MCInstrDesc MipsInsts[];
1316}
1317static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1318 return MipsInsts[Opcode];
1319}
1320
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001321static bool hasShortDelaySlot(unsigned Opcode) {
1322 switch (Opcode) {
1323 case Mips::JALS_MM:
1324 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001325 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001326 case Mips::BGEZALS_MM:
1327 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001328 return true;
1329 default:
1330 return false;
1331 }
1332}
1333
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001334static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1335 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1336 return &SRExpr->getSymbol();
1337 }
1338
1339 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1340 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1341 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1342
1343 if (LHSSym)
1344 return LHSSym;
1345
1346 if (RHSSym)
1347 return RHSSym;
1348
1349 return nullptr;
1350 }
1351
1352 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1353 return getSingleMCSymbol(UExpr->getSubExpr());
1354
1355 return nullptr;
1356}
1357
1358static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1359 if (isa<MCSymbolRefExpr>(Expr))
1360 return 1;
1361
1362 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1363 return countMCSymbolRefExpr(BExpr->getLHS()) +
1364 countMCSymbolRefExpr(BExpr->getRHS());
1365
1366 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1367 return countMCSymbolRefExpr(UExpr->getSubExpr());
1368
1369 return 0;
1370}
1371
Jack Carter9e65aa32013-03-22 00:05:30 +00001372bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001373 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001374 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001375 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001376
Jack Carter9e65aa32013-03-22 00:05:30 +00001377 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001378
1379 if (MCID.isBranch() || MCID.isCall()) {
1380 const unsigned Opcode = Inst.getOpcode();
1381 MCOperand Offset;
1382
1383 switch (Opcode) {
1384 default:
1385 break;
Kai Nackee0245392015-01-27 19:11:28 +00001386 case Mips::BBIT0:
1387 case Mips::BBIT032:
1388 case Mips::BBIT1:
1389 case Mips::BBIT132:
1390 assert(hasCnMips() && "instruction only valid for octeon cpus");
1391 // Fall through
1392
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001393 case Mips::BEQ:
1394 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001395 case Mips::BEQ_MM:
1396 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001397 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001398 Offset = Inst.getOperand(2);
1399 if (!Offset.isImm())
1400 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001401 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001402 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001403 if (OffsetToAlignment(Offset.getImm(),
1404 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001405 return Error(IDLoc, "branch to misaligned address");
1406 break;
1407 case Mips::BGEZ:
1408 case Mips::BGTZ:
1409 case Mips::BLEZ:
1410 case Mips::BLTZ:
1411 case Mips::BGEZAL:
1412 case Mips::BLTZAL:
1413 case Mips::BC1F:
1414 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001415 case Mips::BGEZ_MM:
1416 case Mips::BGTZ_MM:
1417 case Mips::BLEZ_MM:
1418 case Mips::BLTZ_MM:
1419 case Mips::BGEZAL_MM:
1420 case Mips::BLTZAL_MM:
1421 case Mips::BC1F_MM:
1422 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001423 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001424 Offset = Inst.getOperand(1);
1425 if (!Offset.isImm())
1426 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001427 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001428 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001429 if (OffsetToAlignment(Offset.getImm(),
1430 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001431 return Error(IDLoc, "branch to misaligned address");
1432 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001433 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001434 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001435 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001436 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001437 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1438 Offset = Inst.getOperand(1);
1439 if (!Offset.isImm())
1440 break; // We'll deal with this situation later on when applying fixups.
1441 if (!isIntN(8, Offset.getImm()))
1442 return Error(IDLoc, "branch target out of range");
1443 if (OffsetToAlignment(Offset.getImm(), 2LL))
1444 return Error(IDLoc, "branch to misaligned address");
1445 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001446 }
1447 }
1448
Daniel Sandersa84989a2014-06-16 13:25:35 +00001449 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1450 // We still accept it but it is a normal nop.
1451 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1452 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1453 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1454 "nop instruction");
1455 }
1456
Kai Nackee0245392015-01-27 19:11:28 +00001457 if (hasCnMips()) {
1458 const unsigned Opcode = Inst.getOpcode();
1459 MCOperand Opnd;
1460 int Imm;
1461
1462 switch (Opcode) {
1463 default:
1464 break;
1465
1466 case Mips::BBIT0:
1467 case Mips::BBIT032:
1468 case Mips::BBIT1:
1469 case Mips::BBIT132:
1470 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1471 // The offset is handled above
1472 Opnd = Inst.getOperand(1);
1473 if (!Opnd.isImm())
1474 return Error(IDLoc, "expected immediate operand kind");
1475 Imm = Opnd.getImm();
1476 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1477 Opcode == Mips::BBIT1 ? 63 : 31))
1478 return Error(IDLoc, "immediate operand value out of range");
1479 if (Imm > 31) {
1480 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1481 : Mips::BBIT132);
1482 Inst.getOperand(1).setImm(Imm - 32);
1483 }
1484 break;
1485
1486 case Mips::CINS:
1487 case Mips::CINS32:
1488 case Mips::EXTS:
1489 case Mips::EXTS32:
1490 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1491 // Check length
1492 Opnd = Inst.getOperand(3);
1493 if (!Opnd.isImm())
1494 return Error(IDLoc, "expected immediate operand kind");
1495 Imm = Opnd.getImm();
1496 if (Imm < 0 || Imm > 31)
1497 return Error(IDLoc, "immediate operand value out of range");
1498 // Check position
1499 Opnd = Inst.getOperand(2);
1500 if (!Opnd.isImm())
1501 return Error(IDLoc, "expected immediate operand kind");
1502 Imm = Opnd.getImm();
1503 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1504 Opcode == Mips::EXTS ? 63 : 31))
1505 return Error(IDLoc, "immediate operand value out of range");
1506 if (Imm > 31) {
1507 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1508 Inst.getOperand(2).setImm(Imm - 32);
1509 }
1510 break;
1511
1512 case Mips::SEQi:
1513 case Mips::SNEi:
1514 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1515 Opnd = Inst.getOperand(2);
1516 if (!Opnd.isImm())
1517 return Error(IDLoc, "expected immediate operand kind");
1518 Imm = Opnd.getImm();
1519 if (!isInt<10>(Imm))
1520 return Error(IDLoc, "immediate operand value out of range");
1521 break;
1522 }
1523 }
1524
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001525 // This expansion is not in a function called by expandInstruction() because
1526 // the pseudo-instruction doesn't have a distinct opcode.
1527 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1528 inPicMode()) {
1529 warnIfNoMacro(IDLoc);
1530
1531 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1532
1533 // We can do this expansion if there's only 1 symbol in the argument
1534 // expression.
1535 if (countMCSymbolRefExpr(JalExpr) > 1)
1536 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1537
1538 // FIXME: This is checking the expression can be handled by the later stages
1539 // of the assembler. We ought to leave it to those later stages but
1540 // we can't do that until we stop evaluateRelocExpr() rewriting the
1541 // expressions into non-equivalent forms.
1542 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1543
1544 // FIXME: Add support for label+offset operands (currently causes an error).
1545 // FIXME: Add support for forward-declared local symbols.
1546 // FIXME: Add expansion for when the LargeGOT option is enabled.
1547 if (JalSym->isInSection() || JalSym->isTemporary()) {
1548 if (isABI_O32()) {
1549 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001550 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001551 // R_(MICRO)MIPS_GOT16 label
1552 // addiu $25, $25, 0
1553 // R_(MICRO)MIPS_LO16 label
1554 // jalr $25
1555 const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
1556 const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
1557
1558 MCInst LwInst;
1559 LwInst.setOpcode(Mips::LW);
1560 LwInst.addOperand(MCOperand::createReg(Mips::T9));
1561 LwInst.addOperand(MCOperand::createReg(Mips::GP));
1562 LwInst.addOperand(MCOperand::createExpr(Got16RelocExpr));
1563 Instructions.push_back(LwInst);
1564
1565 MCInst AddiuInst;
1566 AddiuInst.setOpcode(Mips::ADDiu);
1567 AddiuInst.addOperand(MCOperand::createReg(Mips::T9));
1568 AddiuInst.addOperand(MCOperand::createReg(Mips::T9));
1569 AddiuInst.addOperand(MCOperand::createExpr(Lo16RelocExpr));
1570 Instructions.push_back(AddiuInst);
1571 } else if (isABI_N32() || isABI_N64()) {
1572 // If it's a local symbol and the N32/N64 ABIs are being used,
1573 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001574 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001575 // R_(MICRO)MIPS_GOT_DISP label
1576 // jalr $25
1577 const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
1578
1579 MCInst LoadInst;
1580 LoadInst.setOpcode(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW);
1581 LoadInst.addOperand(MCOperand::createReg(Mips::T9));
1582 LoadInst.addOperand(MCOperand::createReg(Mips::GP));
1583 LoadInst.addOperand(MCOperand::createExpr(GotDispRelocExpr));
1584 Instructions.push_back(LoadInst);
1585 }
1586 } else {
1587 // If it's an external/weak symbol, we expand to:
1588 // lw/ld $25, 0($gp)
1589 // R_(MICRO)MIPS_CALL16 label
1590 // jalr $25
1591 const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
1592
1593 MCInst LoadInst;
1594 LoadInst.setOpcode(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW);
1595 LoadInst.addOperand(MCOperand::createReg(Mips::T9));
1596 LoadInst.addOperand(MCOperand::createReg(Mips::GP));
1597 LoadInst.addOperand(MCOperand::createExpr(Call16RelocExpr));
1598 Instructions.push_back(LoadInst);
1599 }
1600
1601 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001602 if (IsCpRestoreSet && inMicroMipsMode())
1603 JalrInst.setOpcode(Mips::JALRS_MM);
1604 else
1605 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001606 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1607 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1608
1609 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1610 // This relocation is supposed to be an optimization hint for the linker
1611 // and is not necessary for correctness.
1612
1613 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001614 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001615 }
1616
Jack Carter9e65aa32013-03-22 00:05:30 +00001617 if (MCID.mayLoad() || MCID.mayStore()) {
1618 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001619 // reference or immediate we may have to expand instructions.
1620 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001621 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001622 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1623 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001624 MCOperand &Op = Inst.getOperand(i);
1625 if (Op.isImm()) {
1626 int MemOffset = Op.getImm();
1627 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001628 // Offset can't exceed 16bit value.
1629 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001630 return false;
1631 }
1632 } else if (Op.isExpr()) {
1633 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001634 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001635 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001636 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001637 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001638 // Expand symbol.
1639 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001640 return false;
1641 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001642 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001643 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001644 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001645 }
1646 }
1647 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001648 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001649 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001650
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001651 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001652 if (MCID.mayLoad()) {
1653 // Try to create 16-bit GP relative load instruction.
1654 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1655 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1656 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1657 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1658 MCOperand &Op = Inst.getOperand(i);
1659 if (Op.isImm()) {
1660 int MemOffset = Op.getImm();
1661 MCOperand &DstReg = Inst.getOperand(0);
1662 MCOperand &BaseReg = Inst.getOperand(1);
1663 if (isIntN(9, MemOffset) && (MemOffset % 4 == 0) &&
1664 getContext().getRegisterInfo()->getRegClass(
1665 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001666 (BaseReg.getReg() == Mips::GP ||
1667 BaseReg.getReg() == Mips::GP_64)) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001668 MCInst TmpInst;
1669 TmpInst.setLoc(IDLoc);
1670 TmpInst.setOpcode(Mips::LWGP_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00001671 TmpInst.addOperand(MCOperand::createReg(DstReg.getReg()));
1672 TmpInst.addOperand(MCOperand::createReg(Mips::GP));
1673 TmpInst.addOperand(MCOperand::createImm(MemOffset));
Jozef Koleke10a02e2015-01-28 17:27:26 +00001674 Instructions.push_back(TmpInst);
1675 return false;
1676 }
1677 }
1678 }
1679 } // for
1680 } // if load
1681
1682 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1683
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001684 MCOperand Opnd;
1685 int Imm;
1686
1687 switch (Inst.getOpcode()) {
1688 default:
1689 break;
1690 case Mips::ADDIUS5_MM:
1691 Opnd = Inst.getOperand(2);
1692 if (!Opnd.isImm())
1693 return Error(IDLoc, "expected immediate operand kind");
1694 Imm = Opnd.getImm();
1695 if (Imm < -8 || Imm > 7)
1696 return Error(IDLoc, "immediate operand value out of range");
1697 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001698 case Mips::ADDIUSP_MM:
1699 Opnd = Inst.getOperand(0);
1700 if (!Opnd.isImm())
1701 return Error(IDLoc, "expected immediate operand kind");
1702 Imm = Opnd.getImm();
1703 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1704 Imm % 4 != 0)
1705 return Error(IDLoc, "immediate operand value out of range");
1706 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001707 case Mips::SLL16_MM:
1708 case Mips::SRL16_MM:
1709 Opnd = Inst.getOperand(2);
1710 if (!Opnd.isImm())
1711 return Error(IDLoc, "expected immediate operand kind");
1712 Imm = Opnd.getImm();
1713 if (Imm < 1 || Imm > 8)
1714 return Error(IDLoc, "immediate operand value out of range");
1715 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001716 case Mips::LI16_MM:
1717 Opnd = Inst.getOperand(1);
1718 if (!Opnd.isImm())
1719 return Error(IDLoc, "expected immediate operand kind");
1720 Imm = Opnd.getImm();
1721 if (Imm < -1 || Imm > 126)
1722 return Error(IDLoc, "immediate operand value out of range");
1723 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001724 case Mips::ADDIUR2_MM:
1725 Opnd = Inst.getOperand(2);
1726 if (!Opnd.isImm())
1727 return Error(IDLoc, "expected immediate operand kind");
1728 Imm = Opnd.getImm();
1729 if (!(Imm == 1 || Imm == -1 ||
1730 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1731 return Error(IDLoc, "immediate operand value out of range");
1732 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001733 case Mips::ADDIUR1SP_MM:
1734 Opnd = Inst.getOperand(1);
1735 if (!Opnd.isImm())
1736 return Error(IDLoc, "expected immediate operand kind");
1737 Imm = Opnd.getImm();
1738 if (OffsetToAlignment(Imm, 4LL))
1739 return Error(IDLoc, "misaligned immediate operand value");
1740 if (Imm < 0 || Imm > 255)
1741 return Error(IDLoc, "immediate operand value out of range");
1742 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001743 case Mips::ANDI16_MM:
1744 Opnd = Inst.getOperand(2);
1745 if (!Opnd.isImm())
1746 return Error(IDLoc, "expected immediate operand kind");
1747 Imm = Opnd.getImm();
1748 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1749 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1750 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1751 return Error(IDLoc, "immediate operand value out of range");
1752 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001753 case Mips::LBU16_MM:
1754 Opnd = Inst.getOperand(2);
1755 if (!Opnd.isImm())
1756 return Error(IDLoc, "expected immediate operand kind");
1757 Imm = Opnd.getImm();
1758 if (Imm < -1 || Imm > 14)
1759 return Error(IDLoc, "immediate operand value out of range");
1760 break;
Zoran Jovanovic7ba636c2015-09-17 10:14:09 +00001761 case Mips::TEQ_MM:
1762 case Mips::TGE_MM:
1763 case Mips::TGEU_MM:
1764 case Mips::TLT_MM:
1765 case Mips::TLTU_MM:
1766 case Mips::TNE_MM:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001767 case Mips::SB16_MM:
1768 Opnd = Inst.getOperand(2);
1769 if (!Opnd.isImm())
1770 return Error(IDLoc, "expected immediate operand kind");
1771 Imm = Opnd.getImm();
1772 if (Imm < 0 || Imm > 15)
1773 return Error(IDLoc, "immediate operand value out of range");
1774 break;
1775 case Mips::LHU16_MM:
1776 case Mips::SH16_MM:
1777 Opnd = Inst.getOperand(2);
1778 if (!Opnd.isImm())
1779 return Error(IDLoc, "expected immediate operand kind");
1780 Imm = Opnd.getImm();
1781 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1782 return Error(IDLoc, "immediate operand value out of range");
1783 break;
1784 case Mips::LW16_MM:
1785 case Mips::SW16_MM:
1786 Opnd = Inst.getOperand(2);
1787 if (!Opnd.isImm())
1788 return Error(IDLoc, "expected immediate operand kind");
1789 Imm = Opnd.getImm();
1790 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1791 return Error(IDLoc, "immediate operand value out of range");
1792 break;
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +00001793 case Mips::PREFX_MM:
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001794 case Mips::CACHE:
1795 case Mips::PREF:
1796 Opnd = Inst.getOperand(2);
1797 if (!Opnd.isImm())
1798 return Error(IDLoc, "expected immediate operand kind");
1799 Imm = Opnd.getImm();
1800 if (!isUInt<5>(Imm))
1801 return Error(IDLoc, "immediate operand value out of range");
1802 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001803 case Mips::ADDIUPC_MM:
1804 MCOperand Opnd = Inst.getOperand(1);
1805 if (!Opnd.isImm())
1806 return Error(IDLoc, "expected immediate operand kind");
1807 int Imm = Opnd.getImm();
1808 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1809 return Error(IDLoc, "immediate operand value out of range");
1810 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001811 }
1812 }
1813
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001814 if (needsExpansion(Inst)) {
1815 if (expandInstruction(Inst, IDLoc, Instructions))
1816 return true;
1817 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001818 Instructions.push_back(Inst);
1819
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001820 // If this instruction has a delay slot and .set reorder is active,
1821 // emit a NOP after it.
1822 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1823 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1824
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001825 if ((Inst.getOpcode() == Mips::JalOneReg ||
1826 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
1827 isPicAndNotNxxAbi()) {
1828 if (IsCpRestoreSet) {
1829 // We need a NOP between the JALR and the LW:
1830 // If .set reorder has been used, we've already emitted a NOP.
1831 // If .set noreorder has been used, we need to emit a NOP at this point.
1832 if (!AssemblerOptions.back()->isReorder())
1833 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1834
1835 // Load the $gp from the stack.
1836 SmallVector<MCInst, 3> LoadInsts;
1837 createCpRestoreMemOp(true /*IsLoad*/, CpRestoreOffset /*StackOffset*/,
1838 IDLoc, LoadInsts);
1839
1840 for (const MCInst &Inst : LoadInsts)
1841 Instructions.push_back(Inst);
1842
1843 } else
1844 Warning(IDLoc, "no .cprestore used in PIC mode");
1845 }
1846
Jack Carter9e65aa32013-03-22 00:05:30 +00001847 return false;
1848}
1849
Jack Carter30a59822012-10-04 04:03:53 +00001850bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1851
Jack Carterd0bd6422013-04-18 00:41:53 +00001852 switch (Inst.getOpcode()) {
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001853 case Mips::LoadImm32:
1854 case Mips::LoadImm64:
1855 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001856 case Mips::LoadAddrImm64:
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001857 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001858 case Mips::LoadAddrReg64:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001859 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001860 case Mips::B_MMR6_Pseudo:
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001861 case Mips::LWM_MM:
1862 case Mips::SWM_MM:
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001863 case Mips::JalOneReg:
1864 case Mips::JalTwoReg:
Toma Tabacue1e460d2015-06-11 10:36:10 +00001865 case Mips::BneImm:
1866 case Mips::BeqImm:
Toma Tabacu1a108322015-06-17 13:20:24 +00001867 case Mips::BLT:
1868 case Mips::BLE:
1869 case Mips::BGE:
1870 case Mips::BGT:
1871 case Mips::BLTU:
1872 case Mips::BLEU:
1873 case Mips::BGEU:
1874 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00001875 case Mips::BLTL:
1876 case Mips::BLEL:
1877 case Mips::BGEL:
1878 case Mips::BGTL:
1879 case Mips::BLTUL:
1880 case Mips::BLEUL:
1881 case Mips::BGEUL:
1882 case Mips::BGTUL:
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00001883 case Mips::SDivMacro:
1884 case Mips::UDivMacro:
1885 case Mips::DSDivMacro:
1886 case Mips::DUDivMacro:
Toma Tabacud88d79c2015-06-23 14:39:42 +00001887 case Mips::Ulhu:
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00001888 case Mips::Ulw:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00001889 case Mips::NORImm:
Jack Carterd0bd6422013-04-18 00:41:53 +00001890 return true;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00001891 case Mips::ADDi:
1892 case Mips::ADDiu:
1893 case Mips::SLTi:
1894 case Mips::SLTiu:
1895 if ((Inst.getNumOperands() == 3) &&
1896 Inst.getOperand(0).isReg() &&
1897 Inst.getOperand(1).isReg() &&
1898 Inst.getOperand(2).isImm()) {
1899 int64_t ImmValue = Inst.getOperand(2).getImm();
1900 return !isInt<16>(ImmValue);
1901 }
1902 return false;
1903 case Mips::ANDi:
1904 case Mips::ORi:
1905 case Mips::XORi:
1906 if ((Inst.getNumOperands() == 3) &&
1907 Inst.getOperand(0).isReg() &&
1908 Inst.getOperand(1).isReg() &&
1909 Inst.getOperand(2).isImm()) {
1910 int64_t ImmValue = Inst.getOperand(2).getImm();
1911 return !isUInt<16>(ImmValue);
1912 }
1913 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001914 default:
1915 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001916 }
1917}
Jack Carter92995f12012-10-06 00:53:28 +00001918
Matheus Almeida3813d572014-06-19 14:39:14 +00001919bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001920 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001921 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001922 default: llvm_unreachable("unimplemented expansion");
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001923 case Mips::LoadImm32:
Toma Tabacu00e98672015-05-01 12:19:27 +00001924 return expandLoadImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001925 case Mips::LoadImm64:
Toma Tabacu00e98672015-05-01 12:19:27 +00001926 return expandLoadImm(Inst, false, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001927 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001928 case Mips::LoadAddrImm64:
1929 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1930 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1931 "expected immediate operand kind");
1932
1933 return expandLoadAddress(
1934 Inst.getOperand(0).getReg(), Mips::NoRegister, Inst.getOperand(1),
1935 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001936 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001937 case Mips::LoadAddrReg64:
1938 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1939 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1940 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
1941 "expected immediate operand kind");
1942
1943 return expandLoadAddress(
1944 Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(), Inst.getOperand(2),
1945 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001946 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001947 case Mips::B_MMR6_Pseudo:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001948 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001949 case Mips::SWM_MM:
1950 case Mips::LWM_MM:
1951 return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001952 case Mips::JalOneReg:
1953 case Mips::JalTwoReg:
1954 return expandJalWithRegs(Inst, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00001955 case Mips::BneImm:
1956 case Mips::BeqImm:
1957 return expandBranchImm(Inst, IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00001958 case Mips::BLT:
1959 case Mips::BLE:
1960 case Mips::BGE:
1961 case Mips::BGT:
1962 case Mips::BLTU:
1963 case Mips::BLEU:
1964 case Mips::BGEU:
1965 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00001966 case Mips::BLTL:
1967 case Mips::BLEL:
1968 case Mips::BGEL:
1969 case Mips::BGTL:
1970 case Mips::BLTUL:
1971 case Mips::BLEUL:
1972 case Mips::BGEUL:
1973 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00001974 return expandCondBranches(Inst, IDLoc, Instructions);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00001975 case Mips::SDivMacro:
1976 return expandDiv(Inst, IDLoc, Instructions, false, true);
1977 case Mips::DSDivMacro:
1978 return expandDiv(Inst, IDLoc, Instructions, true, true);
1979 case Mips::UDivMacro:
1980 return expandDiv(Inst, IDLoc, Instructions, false, false);
1981 case Mips::DUDivMacro:
1982 return expandDiv(Inst, IDLoc, Instructions, true, false);
Toma Tabacud88d79c2015-06-23 14:39:42 +00001983 case Mips::Ulhu:
1984 return expandUlhu(Inst, IDLoc, Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00001985 case Mips::Ulw:
1986 return expandUlw(Inst, IDLoc, Instructions);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00001987 case Mips::ADDi:
1988 case Mips::ADDiu:
1989 case Mips::ANDi:
1990 case Mips::NORImm:
1991 case Mips::ORi:
1992 case Mips::SLTi:
1993 case Mips::SLTiu:
1994 case Mips::XORi:
1995 return expandAliasImmediate(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001996 }
Jack Carter30a59822012-10-04 04:03:53 +00001997}
Jack Carter92995f12012-10-06 00:53:28 +00001998
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001999namespace {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002000void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc,
Daniel Sanders03f9c012015-07-14 12:24:22 +00002001 SmallVectorImpl<MCInst> &Instructions) {
2002 MCInst tmpInst;
2003 tmpInst.setOpcode(Opcode);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002004 tmpInst.addOperand(MCOperand::createReg(Reg0));
2005 tmpInst.addOperand(Op1);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002006 tmpInst.setLoc(IDLoc);
2007 Instructions.push_back(tmpInst);
2008}
2009
Daniel Sandersf1ae3672015-08-18 09:55:57 +00002010void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc,
Daniel Sanders03f9c012015-07-14 12:24:22 +00002011 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002012 emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002013}
2014
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002015void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc,
2016 SmallVectorImpl<MCInst> &Instructions) {
2017 emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, Instructions);
2018}
2019
2020void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc,
2021 SmallVectorImpl<MCInst> &Instructions) {
2022 MCInst tmpInst;
2023 tmpInst.setOpcode(Opcode);
2024 tmpInst.addOperand(MCOperand::createImm(Imm1));
2025 tmpInst.addOperand(MCOperand::createImm(Imm2));
2026 tmpInst.setLoc(IDLoc);
2027 Instructions.push_back(tmpInst);
2028}
2029
2030void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
2031 SmallVectorImpl<MCInst> &Instructions) {
2032 MCInst tmpInst;
2033 tmpInst.setOpcode(Opcode);
2034 tmpInst.addOperand(MCOperand::createReg(Reg0));
2035 tmpInst.setLoc(IDLoc);
2036 Instructions.push_back(tmpInst);
2037}
2038
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002039void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2,
Daniel Sanders03f9c012015-07-14 12:24:22 +00002040 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
2041 MCInst tmpInst;
2042 tmpInst.setOpcode(Opcode);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002043 tmpInst.addOperand(MCOperand::createReg(Reg0));
2044 tmpInst.addOperand(MCOperand::createReg(Reg1));
2045 tmpInst.addOperand(Op2);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002046 tmpInst.setLoc(IDLoc);
2047 Instructions.push_back(tmpInst);
2048}
2049
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002050void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
Daniel Sanders03f9c012015-07-14 12:24:22 +00002051 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002052 emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc,
Daniel Sanders03f9c012015-07-14 12:24:22 +00002053 Instructions);
2054}
2055
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002056void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
2057 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
2058 emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc,
2059 Instructions);
2060}
Daniel Sanders03f9c012015-07-14 12:24:22 +00002061
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002062void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount,
2063 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
2064 if (ShiftAmount >= 32) {
2065 emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc,
2066 Instructions);
Toma Tabacu7dea2e32015-04-28 14:06:35 +00002067 return;
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002068 }
Toma Tabacu7dea2e32015-04-28 14:06:35 +00002069
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002070 emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00002071}
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002072} // end anonymous namespace.
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00002073
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002074bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
2075 SmallVectorImpl<MCInst> &Instructions) {
2076 // Create a JALR instruction which is going to replace the pseudo-JAL.
2077 MCInst JalrInst;
2078 JalrInst.setLoc(IDLoc);
2079 const MCOperand FirstRegOp = Inst.getOperand(0);
2080 const unsigned Opcode = Inst.getOpcode();
2081
2082 if (Opcode == Mips::JalOneReg) {
2083 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002084 if (IsCpRestoreSet && inMicroMipsMode()) {
2085 JalrInst.setOpcode(Mips::JALRS16_MM);
2086 JalrInst.addOperand(FirstRegOp);
2087 } else if (inMicroMipsMode()) {
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002088 JalrInst.setOpcode(Mips::JALR16_MM);
2089 JalrInst.addOperand(FirstRegOp);
2090 } else {
2091 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002092 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002093 JalrInst.addOperand(FirstRegOp);
2094 }
2095 } else if (Opcode == Mips::JalTwoReg) {
2096 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002097 if (IsCpRestoreSet && inMicroMipsMode())
2098 JalrInst.setOpcode(Mips::JALRS_MM);
2099 else
2100 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002101 JalrInst.addOperand(FirstRegOp);
2102 const MCOperand SecondRegOp = Inst.getOperand(1);
2103 JalrInst.addOperand(SecondRegOp);
2104 }
2105 Instructions.push_back(JalrInst);
2106
2107 // If .set reorder is active, emit a NOP after it.
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002108 if (AssemblerOptions.back()->isReorder())
2109 createNop(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002110
2111 return false;
2112}
2113
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002114/// Can the value be represented by a unsigned N-bit value and a shift left?
2115template<unsigned N>
2116bool isShiftedUIntAtAnyPosition(uint64_t x) {
2117 unsigned BitNum = findFirstSet(x);
2118
2119 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2120}
2121
2122/// Load (or add) an immediate into a register.
2123///
2124/// @param ImmValue The immediate to load.
2125/// @param DstReg The register that will hold the immediate.
2126/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2127/// for a simple initialization.
2128/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2129/// @param IsAddress True if the immediate represents an address. False if it
2130/// is an integer.
2131/// @param IDLoc Location of the immediate in the source file.
2132/// @param Instructions The instructions emitted by this expansion.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002133bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002134 unsigned SrcReg, bool Is32BitImm,
2135 bool IsAddress, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00002136 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00002137 if (!Is32BitImm && !isGP64bit()) {
2138 Error(IDLoc, "instruction requires a 64-bit architecture");
2139 return true;
2140 }
2141
Daniel Sanders03f9c012015-07-14 12:24:22 +00002142 if (Is32BitImm) {
2143 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2144 // Sign extend up to 64-bit so that the predicates match the hardware
2145 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2146 // true.
2147 ImmValue = SignExtend64<32>(ImmValue);
2148 } else {
2149 Error(IDLoc, "instruction requires a 32-bit immediate");
2150 return true;
2151 }
2152 }
2153
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002154 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2155 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2156
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002157 bool UseSrcReg = false;
2158 if (SrcReg != Mips::NoRegister)
2159 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002160
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002161 unsigned TmpReg = DstReg;
2162 if (UseSrcReg && (DstReg == SrcReg)) {
2163 // At this point we need AT to perform the expansions and we exit if it is
2164 // not available.
2165 unsigned ATReg = getATReg(IDLoc);
2166 if (!ATReg)
2167 return true;
2168 TmpReg = ATReg;
2169 }
2170
Daniel Sanders03f9c012015-07-14 12:24:22 +00002171 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002172 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002173 SrcReg = ZeroReg;
2174
2175 // This doesn't quite follow the usual ABI expectations for N32 but matches
2176 // traditional assembler behaviour. N32 would normally use addiu for both
2177 // integers and addresses.
2178 if (IsAddress && !Is32BitImm) {
2179 emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2180 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002181 }
2182
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002183 emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2184 return false;
2185 }
2186
2187 if (isUInt<16>(ImmValue)) {
2188 unsigned TmpReg = DstReg;
2189 if (SrcReg == DstReg) {
2190 TmpReg = getATReg(IDLoc);
2191 if (!TmpReg)
2192 return true;
2193 }
2194
2195 emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002196 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002197 emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2198 return false;
2199 }
2200
2201 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002202 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002203
Toma Tabacu79588102015-04-29 10:19:56 +00002204 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2205 uint16_t Bits15To0 = ImmValue & 0xffff;
2206
Toma Tabacua3d056f2015-05-15 09:42:11 +00002207 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002208 // Traditional behaviour seems to special case this particular value. It's
2209 // not clear why other masks are handled differently.
2210 if (ImmValue == 0xffffffff) {
Daniel Sandersf1ae3672015-08-18 09:55:57 +00002211 emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002212 emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, Instructions);
2213 if (UseSrcReg)
2214 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2215 return false;
2216 }
2217
2218 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002219 // upper 32 bits.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002220 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002221 emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002222 if (Bits15To0)
2223 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
2224 if (UseSrcReg)
2225 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2226 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002227 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002228
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002229 emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions);
2230 if (Bits15To0)
2231 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002232 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002233 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2234 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002235 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002236
2237 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2238 if (Is32BitImm) {
2239 Error(IDLoc, "instruction requires a 32-bit immediate");
2240 return true;
2241 }
2242
2243 // Traditionally, these immediates are shifted as little as possible and as
2244 // such we align the most significant bit to bit 15 of our temporary.
2245 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2246 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2247 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2248 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
2249 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, Instructions);
2250 emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, Instructions);
2251
2252 if (UseSrcReg)
2253 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2254
2255 return false;
2256 }
2257
2258 warnIfNoMacro(IDLoc);
2259
2260 // The remaining case is packed with a sequence of dsll and ori with zeros
2261 // being omitted and any neighbouring dsll's being coalesced.
2262 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2263
2264 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2265 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
2266 IDLoc, Instructions))
2267 return false;
2268
2269 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2270 // skip it and defer the shift to the next chunk.
2271 unsigned ShiftCarriedForwards = 16;
2272 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2273 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2274
2275 if (ImmChunk != 0) {
2276 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2277 Instructions);
2278 emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, Instructions);
2279 ShiftCarriedForwards = 0;
2280 }
2281
2282 ShiftCarriedForwards += 16;
2283 }
2284 ShiftCarriedForwards -= 16;
2285
2286 // Finish any remaining shifts left by trailing zeros.
2287 if (ShiftCarriedForwards)
2288 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2289 Instructions);
2290
2291 if (UseSrcReg)
2292 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2293
Matheus Almeida3813d572014-06-19 14:39:14 +00002294 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002295}
Jack Carter92995f12012-10-06 00:53:28 +00002296
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002297bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
2298 SmallVectorImpl<MCInst> &Instructions) {
2299 const MCOperand &ImmOp = Inst.getOperand(1);
2300 assert(ImmOp.isImm() && "expected immediate operand kind");
2301 const MCOperand &DstRegOp = Inst.getOperand(0);
2302 assert(DstRegOp.isReg() && "expected register operand kind");
2303
2304 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002305 Is32BitImm, false, IDLoc, Instructions))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002306 return true;
2307
2308 return false;
2309}
2310
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002311bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2312 const MCOperand &Offset,
2313 bool Is32BitAddress, SMLoc IDLoc,
2314 SmallVectorImpl<MCInst> &Instructions) {
2315 // la can't produce a usable address when addresses are 64-bit.
2316 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2317 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2318 // We currently can't do this because we depend on the equality
2319 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2320 Error(IDLoc, "la used to load 64-bit address");
2321 // Continue as if we had 'dla' instead.
2322 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002323 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002324
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002325 // dla requires 64-bit addresses.
2326 if (!Is32BitAddress && !ABI.ArePtrs64bit()) {
2327 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002328 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002329 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002330
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002331 if (!Offset.isImm())
2332 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
2333 Is32BitAddress, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002334
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002335 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
2336 IDLoc, Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +00002337}
2338
Toma Tabacuf712ede2015-06-17 14:31:51 +00002339bool MipsAsmParser::loadAndAddSymbolAddress(
2340 const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
2341 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002342 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002343
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002344 // FIXME: The way we're handling symbols right now prevents simple expressions
2345 // like foo+8. We'll be able to fix this once our unary operators (%hi
2346 // and similar) are treated as operators rather than as fixup types.
Toma Tabacu674825c2015-06-16 12:16:24 +00002347 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymExpr);
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002348 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::create(
2349 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
2350 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::create(
2351 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
2352
Toma Tabacufb9d1252015-06-22 12:08:39 +00002353 bool UseSrcReg = SrcReg != Mips::NoRegister;
2354
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002355 // This is the 64-bit symbol address expansion.
2356 if (ABI.ArePtrs64bit() && isGP64bit()) {
2357 // We always need AT for the 64-bit expansion.
2358 // If it is not available we exit.
2359 unsigned ATReg = getATReg(IDLoc);
2360 if (!ATReg)
2361 return true;
2362
2363 const MCSymbolRefExpr *HighestExpr = MCSymbolRefExpr::create(
2364 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
2365 const MCSymbolRefExpr *HigherExpr = MCSymbolRefExpr::create(
2366 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
2367
2368 if (UseSrcReg && (DstReg == SrcReg)) {
2369 // If $rs is the same as $rd:
2370 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2371 // daddiu $at, $at, %higher(sym)
2372 // dsll $at, $at, 16
2373 // daddiu $at, $at, %hi(sym)
2374 // dsll $at, $at, 16
2375 // daddiu $at, $at, %lo(sym)
2376 // daddu $rd, $at, $rd
2377 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2378 Instructions);
2379 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr),
2380 IDLoc, Instructions);
2381 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2382 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2383 Instructions);
2384 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2385 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2386 Instructions);
2387 emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions);
2388
2389 return false;
2390 }
2391
2392 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2393 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2394 // lui $at, %hi(sym)
2395 // daddiu $rd, $rd, %higher(sym)
2396 // daddiu $at, $at, %lo(sym)
2397 // dsll32 $rd, $rd, 0
2398 // daddu $rd, $rd, $at
2399 // (daddu $rd, $rd, $rs)
2400 emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2401 Instructions);
2402 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2403 Instructions);
2404 emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr),
2405 IDLoc, Instructions);
2406 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2407 Instructions);
2408 emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions);
2409 emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions);
2410 if (UseSrcReg)
2411 emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions);
2412
2413 return false;
2414 }
2415
2416 // And now, the 32-bit symbol address expansion:
2417 // If $rs is the same as $rd:
2418 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2419 // ori $at, $at, %lo(sym)
2420 // addu $rd, $at, $rd
2421 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2422 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2423 // ori $rd, $rd, %lo(sym)
2424 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002425 unsigned TmpReg = DstReg;
2426 if (UseSrcReg && (DstReg == SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002427 // If $rs is the same as $rd, we need to use AT.
2428 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002429 unsigned ATReg = getATReg(IDLoc);
2430 if (!ATReg)
2431 return true;
2432 TmpReg = ATReg;
2433 }
2434
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002435 emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions);
2436 emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc,
2437 Instructions);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002438
Toma Tabacufb9d1252015-06-22 12:08:39 +00002439 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002440 emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2441 else
2442 assert(DstReg == TmpReg);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002443
Toma Tabacu674825c2015-06-16 12:16:24 +00002444 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002445}
2446
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002447bool MipsAsmParser::expandUncondBranchMMPseudo(
2448 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002449 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2450 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002451
2452 MCOperand Offset = Inst.getOperand(0);
2453 if (Offset.isExpr()) {
2454 Inst.clear();
2455 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002456 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2457 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2458 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002459 } else {
2460 assert(Offset.isImm() && "expected immediate operand kind");
2461 if (isIntN(11, Offset.getImm())) {
2462 // If offset fits into 11 bits then this instruction becomes microMIPS
2463 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002464 if (inMicroMipsMode())
2465 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002466 } else {
2467 if (!isIntN(17, Offset.getImm()))
2468 Error(IDLoc, "branch target out of range");
2469 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2470 Error(IDLoc, "branch to misaligned address");
2471 Inst.clear();
2472 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002473 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2474 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2475 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002476 }
2477 }
2478 Instructions.push_back(Inst);
2479
Zoran Jovanovicada70912015-09-07 11:56:37 +00002480 // If .set reorder is active and branch instruction has a delay slot,
2481 // emit a NOP after it.
2482 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2483 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Toma Tabacu234482a2015-03-16 12:03:39 +00002484 createNop(true, IDLoc, Instructions);
2485
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002486 return false;
2487}
2488
Toma Tabacue1e460d2015-06-11 10:36:10 +00002489bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2490 SmallVectorImpl<MCInst> &Instructions) {
2491 const MCOperand &DstRegOp = Inst.getOperand(0);
2492 assert(DstRegOp.isReg() && "expected register operand kind");
2493
2494 const MCOperand &ImmOp = Inst.getOperand(1);
2495 assert(ImmOp.isImm() && "expected immediate operand kind");
2496
2497 const MCOperand &MemOffsetOp = Inst.getOperand(2);
2498 assert(MemOffsetOp.isImm() && "expected immediate operand kind");
2499
2500 unsigned OpCode = 0;
2501 switch(Inst.getOpcode()) {
2502 case Mips::BneImm:
2503 OpCode = Mips::BNE;
2504 break;
2505 case Mips::BeqImm:
2506 OpCode = Mips::BEQ;
2507 break;
2508 default:
2509 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2510 break;
2511 }
2512
2513 int64_t ImmValue = ImmOp.getImm();
2514 if (ImmValue == 0) {
2515 MCInst BranchInst;
2516 BranchInst.setOpcode(OpCode);
2517 BranchInst.addOperand(DstRegOp);
2518 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2519 BranchInst.addOperand(MemOffsetOp);
2520 Instructions.push_back(BranchInst);
2521 } else {
2522 warnIfNoMacro(IDLoc);
2523
2524 unsigned ATReg = getATReg(IDLoc);
2525 if (!ATReg)
2526 return true;
2527
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002528 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
2529 IDLoc, Instructions))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002530 return true;
2531
2532 MCInst BranchInst;
2533 BranchInst.setOpcode(OpCode);
2534 BranchInst.addOperand(DstRegOp);
2535 BranchInst.addOperand(MCOperand::createReg(ATReg));
2536 BranchInst.addOperand(MemOffsetOp);
2537 Instructions.push_back(BranchInst);
2538 }
2539 return false;
2540}
2541
Jack Carter9e65aa32013-03-22 00:05:30 +00002542void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002543 SmallVectorImpl<MCInst> &Instructions,
2544 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002545 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00002546 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002547 const MCExpr *ExprOffset;
2548 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002549 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002550 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2551 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002552 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002553 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2554 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002555 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002556 if (isImmOpnd) {
2557 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2558 ImmOffset = Inst.getOperand(2).getImm();
2559 LoOffset = ImmOffset & 0x0000ffff;
2560 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002561 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002562 if (LoOffset & 0x8000)
2563 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002564 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002565 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002566 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002567 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002568 // These are some of the types of expansions we perform here:
2569 // 1) lw $8, sym => lui $8, %hi(sym)
2570 // lw $8, %lo(sym)($8)
2571 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2572 // add $8, $8, $9
2573 // lw $8, %lo(offset)($9)
2574 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2575 // add $at, $at, $8
2576 // lw $8, %lo(offset)($at)
2577 // 4) sw $8, sym => lui $at, %hi(sym)
2578 // sw $8, %lo(sym)($at)
2579 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2580 // add $at, $at, $8
2581 // sw $8, %lo(offset)($at)
2582 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2583 // ldc1 $f0, %lo(sym)($at)
2584 //
2585 // For load instructions we can use the destination register as a temporary
2586 // if base and dst are different (examples 1 and 2) and if the base register
2587 // is general purpose otherwise we must use $at (example 6) and error if it's
2588 // not available. For stores we must use $at (examples 4 and 5) because we
2589 // must not clobber the source register setting up the offset.
2590 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2591 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2592 unsigned RegClassIDOp0 =
2593 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2594 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2595 (RegClassIDOp0 == Mips::GPR64RegClassID);
2596 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002597 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002598 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002599 // At this point we need AT to perform the expansions and we exit if it is
2600 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002601 TmpRegNum = getATReg(IDLoc);
2602 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002603 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002604 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002605
Jack Carter9e65aa32013-03-22 00:05:30 +00002606 TempInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00002607 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002608 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002609 TempInst.addOperand(MCOperand::createImm(HiOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002610 else {
Toma Tabacu07c97b32015-06-17 10:43:45 +00002611 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
2612 TempInst.addOperand(MCOperand::createExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002613 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002614 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002615 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002616 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002617 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002618 // Add temp register to base.
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002619 if (BaseRegNum != Mips::ZERO) {
2620 TempInst.setOpcode(Mips::ADDu);
Jim Grosbache9119e42015-05-13 18:37:00 +00002621 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2622 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2623 TempInst.addOperand(MCOperand::createReg(BaseRegNum));
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002624 Instructions.push_back(TempInst);
2625 TempInst.clear();
2626 }
Alp Tokercb402912014-01-24 17:20:08 +00002627 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002628 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002629 TempInst.setOpcode(Inst.getOpcode());
Jim Grosbache9119e42015-05-13 18:37:00 +00002630 TempInst.addOperand(MCOperand::createReg(RegOpNum));
2631 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002632 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002633 TempInst.addOperand(MCOperand::createImm(LoOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002634 else {
Toma Tabacu07c97b32015-06-17 10:43:45 +00002635 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
2636 TempInst.addOperand(MCOperand::createExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002637 }
2638 Instructions.push_back(TempInst);
2639 TempInst.clear();
2640}
2641
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002642bool
2643MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2644 SmallVectorImpl<MCInst> &Instructions) {
2645 unsigned OpNum = Inst.getNumOperands();
2646 unsigned Opcode = Inst.getOpcode();
2647 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2648
2649 assert (Inst.getOperand(OpNum - 1).isImm() &&
2650 Inst.getOperand(OpNum - 2).isReg() &&
2651 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2652
2653 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2654 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2655 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2656 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2657 // It can be implemented as SWM16 or LWM16 instruction.
2658 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2659
2660 Inst.setOpcode(NewOpcode);
2661 Instructions.push_back(Inst);
2662 return false;
2663}
2664
Toma Tabacu1a108322015-06-17 13:20:24 +00002665bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2666 SmallVectorImpl<MCInst> &Instructions) {
2667 unsigned PseudoOpcode = Inst.getOpcode();
2668 unsigned SrcReg = Inst.getOperand(0).getReg();
2669 unsigned TrgReg = Inst.getOperand(1).getReg();
2670 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2671
2672 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002673 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002674
2675 switch (PseudoOpcode) {
2676 case Mips::BLT:
2677 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002678 case Mips::BLTL:
2679 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002680 AcceptsEquality = false;
2681 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002682 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2683 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002684 ZeroSrcOpcode = Mips::BGTZ;
2685 ZeroTrgOpcode = Mips::BLTZ;
2686 break;
2687 case Mips::BLE:
2688 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002689 case Mips::BLEL:
2690 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002691 AcceptsEquality = true;
2692 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002693 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2694 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002695 ZeroSrcOpcode = Mips::BGEZ;
2696 ZeroTrgOpcode = Mips::BLEZ;
2697 break;
2698 case Mips::BGE:
2699 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002700 case Mips::BGEL:
2701 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002702 AcceptsEquality = true;
2703 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002704 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2705 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002706 ZeroSrcOpcode = Mips::BLEZ;
2707 ZeroTrgOpcode = Mips::BGEZ;
2708 break;
2709 case Mips::BGT:
2710 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002711 case Mips::BGTL:
2712 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002713 AcceptsEquality = false;
2714 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002715 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2716 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002717 ZeroSrcOpcode = Mips::BLTZ;
2718 ZeroTrgOpcode = Mips::BGTZ;
2719 break;
2720 default:
2721 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2722 }
2723
2724 MCInst BranchInst;
2725 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2726 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2727 if (IsSrcRegZero && IsTrgRegZero) {
2728 // FIXME: All of these Opcode-specific if's are needed for compatibility
2729 // with GAS' behaviour. However, they may not generate the most efficient
2730 // code in some circumstances.
2731 if (PseudoOpcode == Mips::BLT) {
2732 BranchInst.setOpcode(Mips::BLTZ);
2733 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2734 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2735 Instructions.push_back(BranchInst);
2736 return false;
2737 }
2738 if (PseudoOpcode == Mips::BLE) {
2739 BranchInst.setOpcode(Mips::BLEZ);
2740 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2741 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2742 Instructions.push_back(BranchInst);
2743 Warning(IDLoc, "branch is always taken");
2744 return false;
2745 }
2746 if (PseudoOpcode == Mips::BGE) {
2747 BranchInst.setOpcode(Mips::BGEZ);
2748 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2749 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2750 Instructions.push_back(BranchInst);
2751 Warning(IDLoc, "branch is always taken");
2752 return false;
2753 }
2754 if (PseudoOpcode == Mips::BGT) {
2755 BranchInst.setOpcode(Mips::BGTZ);
2756 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2757 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2758 Instructions.push_back(BranchInst);
2759 return false;
2760 }
2761 if (PseudoOpcode == Mips::BGTU) {
2762 BranchInst.setOpcode(Mips::BNE);
2763 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2764 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2765 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2766 Instructions.push_back(BranchInst);
2767 return false;
2768 }
2769 if (AcceptsEquality) {
2770 // If both registers are $0 and the pseudo-branch accepts equality, it
2771 // will always be taken, so we emit an unconditional branch.
2772 BranchInst.setOpcode(Mips::BEQ);
2773 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2774 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2775 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2776 Instructions.push_back(BranchInst);
2777 Warning(IDLoc, "branch is always taken");
2778 return false;
2779 }
2780 // If both registers are $0 and the pseudo-branch does not accept
2781 // equality, it will never be taken, so we don't have to emit anything.
2782 return false;
2783 }
2784 if (IsSrcRegZero || IsTrgRegZero) {
2785 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2786 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2787 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2788 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2789 // the pseudo-branch will never be taken, so we don't emit anything.
2790 // This only applies to unsigned pseudo-branches.
2791 return false;
2792 }
2793 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2794 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2795 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2796 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2797 // the pseudo-branch will always be taken, so we emit an unconditional
2798 // branch.
2799 // This only applies to unsigned pseudo-branches.
2800 BranchInst.setOpcode(Mips::BEQ);
2801 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2802 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2803 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2804 Instructions.push_back(BranchInst);
2805 Warning(IDLoc, "branch is always taken");
2806 return false;
2807 }
2808 if (IsUnsigned) {
2809 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2810 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2811 // the pseudo-branch will be taken only when the non-zero register is
2812 // different from 0, so we emit a BNEZ.
2813 //
2814 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2815 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2816 // the pseudo-branch will be taken only when the non-zero register is
2817 // equal to 0, so we emit a BEQZ.
2818 //
2819 // Because only BLEU and BGEU branch on equality, we can use the
2820 // AcceptsEquality variable to decide when to emit the BEQZ.
2821 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQ : Mips::BNE);
2822 BranchInst.addOperand(
2823 MCOperand::createReg(IsSrcRegZero ? TrgReg : SrcReg));
2824 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2825 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2826 Instructions.push_back(BranchInst);
2827 return false;
2828 }
2829 // If we have a signed pseudo-branch and one of the registers is $0,
2830 // we can use an appropriate compare-to-zero branch. We select which one
2831 // to use in the switch statement above.
2832 BranchInst.setOpcode(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode);
2833 BranchInst.addOperand(MCOperand::createReg(IsSrcRegZero ? TrgReg : SrcReg));
2834 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2835 Instructions.push_back(BranchInst);
2836 return false;
2837 }
2838
2839 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2840 // expansions. If it is not available, we return.
2841 unsigned ATRegNum = getATReg(IDLoc);
2842 if (!ATRegNum)
2843 return true;
2844
2845 warnIfNoMacro(IDLoc);
2846
2847 // SLT fits well with 2 of our 4 pseudo-branches:
2848 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2849 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2850 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2851 // This is accomplished by using a BNEZ with the result of the SLT.
2852 //
2853 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2854 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2855 // Because only BGE and BLE branch on equality, we can use the
2856 // AcceptsEquality variable to decide when to emit the BEQZ.
2857 // Note that the order of the SLT arguments doesn't change between
2858 // opposites.
2859 //
2860 // The same applies to the unsigned variants, except that SLTu is used
2861 // instead of SLT.
2862 MCInst SetInst;
2863 SetInst.setOpcode(IsUnsigned ? Mips::SLTu : Mips::SLT);
2864 SetInst.addOperand(MCOperand::createReg(ATRegNum));
2865 SetInst.addOperand(MCOperand::createReg(ReverseOrderSLT ? TrgReg : SrcReg));
2866 SetInst.addOperand(MCOperand::createReg(ReverseOrderSLT ? SrcReg : TrgReg));
2867 Instructions.push_back(SetInst);
2868
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002869 if (!IsLikely)
2870 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQ : Mips::BNE);
2871 else
2872 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQL : Mips::BNEL);
Toma Tabacu1a108322015-06-17 13:20:24 +00002873 BranchInst.addOperand(MCOperand::createReg(ATRegNum));
2874 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2875 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2876 Instructions.push_back(BranchInst);
2877 return false;
2878}
2879
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002880bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
2881 SmallVectorImpl<MCInst> &Instructions,
2882 const bool IsMips64, const bool Signed) {
2883 if (hasMips32r6()) {
2884 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2885 return false;
2886 }
2887
2888 warnIfNoMacro(IDLoc);
2889
2890 const MCOperand &RsRegOp = Inst.getOperand(0);
2891 assert(RsRegOp.isReg() && "expected register operand kind");
2892 unsigned RsReg = RsRegOp.getReg();
2893
2894 const MCOperand &RtRegOp = Inst.getOperand(1);
2895 assert(RtRegOp.isReg() && "expected register operand kind");
2896 unsigned RtReg = RtRegOp.getReg();
2897 unsigned DivOp;
2898 unsigned ZeroReg;
2899
2900 if (IsMips64) {
2901 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2902 ZeroReg = Mips::ZERO_64;
2903 } else {
2904 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2905 ZeroReg = Mips::ZERO;
2906 }
2907
2908 bool UseTraps = useTraps();
2909
2910 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2911 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2912 Warning(IDLoc, "dividing zero by zero");
2913 if (IsMips64) {
2914 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2915 if (UseTraps) {
2916 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2917 return false;
2918 }
2919
2920 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2921 return false;
2922 }
2923 } else {
2924 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2925 return false;
2926 }
2927 }
2928
2929 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
2930 Warning(IDLoc, "division by zero");
2931 if (Signed) {
2932 if (UseTraps) {
2933 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2934 return false;
2935 }
2936
2937 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2938 return false;
2939 }
2940 }
2941
2942 // FIXME: The values for these two BranchTarget variables may be different in
2943 // micromips. These magic numbers need to be removed.
2944 unsigned BranchTargetNoTraps;
2945 unsigned BranchTarget;
2946
2947 if (UseTraps) {
2948 BranchTarget = IsMips64 ? 12 : 8;
2949 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2950 } else {
2951 BranchTarget = IsMips64 ? 20 : 16;
2952 BranchTargetNoTraps = 8;
2953 // Branch to the li instruction.
2954 emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc,
2955 Instructions);
2956 }
2957
2958 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2959
2960 if (!UseTraps)
2961 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2962
2963 if (!Signed) {
2964 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
2965 return false;
2966 }
2967
2968 unsigned ATReg = getATReg(IDLoc);
2969 if (!ATReg)
2970 return true;
2971
2972 emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, Instructions);
2973 if (IsMips64) {
2974 // Branch to the mflo instruction.
2975 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
2976 emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, Instructions);
2977 emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, Instructions);
2978 } else {
2979 // Branch to the mflo instruction.
2980 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
2981 emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, Instructions);
2982 }
2983
2984 if (UseTraps)
2985 emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, Instructions);
2986 else {
2987 // Branch to the mflo instruction.
2988 emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, Instructions);
2989 emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, Instructions);
2990 emitII(Mips::BREAK, 0x6, 0, IDLoc, Instructions);
2991 }
2992 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
2993 return false;
2994}
2995
Toma Tabacud88d79c2015-06-23 14:39:42 +00002996bool MipsAsmParser::expandUlhu(MCInst &Inst, SMLoc IDLoc,
2997 SmallVectorImpl<MCInst> &Instructions) {
2998 if (hasMips32r6() || hasMips64r6()) {
2999 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3000 return false;
3001 }
3002
3003 warnIfNoMacro(IDLoc);
3004
3005 const MCOperand &DstRegOp = Inst.getOperand(0);
3006 assert(DstRegOp.isReg() && "expected register operand kind");
3007
3008 const MCOperand &SrcRegOp = Inst.getOperand(1);
3009 assert(SrcRegOp.isReg() && "expected register operand kind");
3010
3011 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3012 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3013
3014 unsigned DstReg = DstRegOp.getReg();
3015 unsigned SrcReg = SrcRegOp.getReg();
3016 int64_t OffsetValue = OffsetImmOp.getImm();
3017
3018 // NOTE: We always need AT for ULHU, as it is always used as the source
3019 // register for one of the LBu's.
3020 unsigned ATReg = getATReg(IDLoc);
3021 if (!ATReg)
3022 return true;
3023
3024 // When the value of offset+1 does not fit in 16 bits, we have to load the
3025 // offset in AT, (D)ADDu the original source register (if there was one), and
3026 // then use AT as the source register for the 2 generated LBu's.
3027 bool LoadedOffsetInAT = false;
3028 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3029 LoadedOffsetInAT = true;
3030
3031 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003032 true, IDLoc, Instructions))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003033 return true;
3034
3035 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3036 // because it will make our output more similar to GAS'. For example,
3037 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3038 // instead of just an "ori $1, $9, 32768".
3039 // NOTE: If there is no source register specified in the ULHU, the parser
3040 // will interpret it as $0.
3041 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3042 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3043 }
3044
3045 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3046 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3047 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3048
3049 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3050 if (isLittle()) {
3051 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3052 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3053 } else {
3054 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3055 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3056 }
3057
3058 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3059
3060 MCInst TmpInst;
3061 TmpInst.setOpcode(Mips::LBu);
3062 TmpInst.addOperand(MCOperand::createReg(FirstLbuDstReg));
3063 TmpInst.addOperand(MCOperand::createReg(LbuSrcReg));
3064 TmpInst.addOperand(MCOperand::createImm(FirstLbuOffset));
3065 Instructions.push_back(TmpInst);
3066
3067 TmpInst.clear();
3068 TmpInst.setOpcode(Mips::LBu);
3069 TmpInst.addOperand(MCOperand::createReg(SecondLbuDstReg));
3070 TmpInst.addOperand(MCOperand::createReg(LbuSrcReg));
3071 TmpInst.addOperand(MCOperand::createImm(SecondLbuOffset));
3072 Instructions.push_back(TmpInst);
3073
3074 TmpInst.clear();
3075 TmpInst.setOpcode(Mips::SLL);
3076 TmpInst.addOperand(MCOperand::createReg(SllReg));
3077 TmpInst.addOperand(MCOperand::createReg(SllReg));
3078 TmpInst.addOperand(MCOperand::createImm(8));
3079 Instructions.push_back(TmpInst);
3080
3081 TmpInst.clear();
3082 TmpInst.setOpcode(Mips::OR);
3083 TmpInst.addOperand(MCOperand::createReg(DstReg));
3084 TmpInst.addOperand(MCOperand::createReg(DstReg));
3085 TmpInst.addOperand(MCOperand::createReg(ATReg));
3086 Instructions.push_back(TmpInst);
3087
3088 return false;
3089}
3090
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003091bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
3092 SmallVectorImpl<MCInst> &Instructions) {
3093 if (hasMips32r6() || hasMips64r6()) {
3094 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3095 return false;
3096 }
3097
3098 const MCOperand &DstRegOp = Inst.getOperand(0);
3099 assert(DstRegOp.isReg() && "expected register operand kind");
3100
3101 const MCOperand &SrcRegOp = Inst.getOperand(1);
3102 assert(SrcRegOp.isReg() && "expected register operand kind");
3103
3104 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3105 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3106
3107 unsigned SrcReg = SrcRegOp.getReg();
3108 int64_t OffsetValue = OffsetImmOp.getImm();
3109 unsigned ATReg = 0;
3110
3111 // When the value of offset+3 does not fit in 16 bits, we have to load the
3112 // offset in AT, (D)ADDu the original source register (if there was one), and
3113 // then use AT as the source register for the generated LWL and LWR.
3114 bool LoadedOffsetInAT = false;
3115 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3116 ATReg = getATReg(IDLoc);
3117 if (!ATReg)
3118 return true;
3119 LoadedOffsetInAT = true;
3120
3121 warnIfNoMacro(IDLoc);
3122
3123 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003124 true, IDLoc, Instructions))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003125 return true;
3126
3127 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3128 // because it will make our output more similar to GAS'. For example,
3129 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3130 // instead of just an "ori $1, $9, 32768".
3131 // NOTE: If there is no source register specified in the ULW, the parser
3132 // will interpret it as $0.
3133 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3134 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3135 }
3136
3137 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3138 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3139 if (isLittle()) {
3140 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3141 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3142 } else {
3143 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3144 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3145 }
3146
3147 MCInst LeftLoadInst;
3148 LeftLoadInst.setOpcode(Mips::LWL);
3149 LeftLoadInst.addOperand(DstRegOp);
3150 LeftLoadInst.addOperand(MCOperand::createReg(FinalSrcReg));
3151 LeftLoadInst.addOperand(MCOperand::createImm(LeftLoadOffset));
3152 Instructions.push_back(LeftLoadInst);
3153
3154 MCInst RightLoadInst;
3155 RightLoadInst.setOpcode(Mips::LWR);
3156 RightLoadInst.addOperand(DstRegOp);
3157 RightLoadInst.addOperand(MCOperand::createReg(FinalSrcReg));
3158 RightLoadInst.addOperand(MCOperand::createImm(RightLoadOffset ));
3159 Instructions.push_back(RightLoadInst);
3160
3161 return false;
3162}
3163
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003164bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
3165 SmallVectorImpl<MCInst> &Instructions) {
3166
3167 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3168 assert (Inst.getOperand(0).isReg() &&
3169 Inst.getOperand(1).isReg() &&
3170 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3171
3172 unsigned ATReg = Mips::NoRegister;
3173 unsigned FinalDstReg = Mips::NoRegister;
3174 unsigned DstReg = Inst.getOperand(0).getReg();
3175 unsigned SrcReg = Inst.getOperand(1).getReg();
3176 int64_t ImmValue = Inst.getOperand(2).getImm();
3177
3178 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3179
3180 unsigned FinalOpcode = Inst.getOpcode();
3181
3182 if (DstReg == SrcReg) {
3183 ATReg = getATReg(Inst.getLoc());
3184 if (!ATReg)
3185 return true;
3186 FinalDstReg = DstReg;
3187 DstReg = ATReg;
3188 }
3189
3190 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Instructions)) {
3191 switch (FinalOpcode) {
3192 default:
3193 llvm_unreachable("unimplemented expansion");
3194 case (Mips::ADDi):
3195 FinalOpcode = Mips::ADD;
3196 break;
3197 case (Mips::ADDiu):
3198 FinalOpcode = Mips::ADDu;
3199 break;
3200 case (Mips::ANDi):
3201 FinalOpcode = Mips::AND;
3202 break;
3203 case (Mips::NORImm):
3204 FinalOpcode = Mips::NOR;
3205 break;
3206 case (Mips::ORi):
3207 FinalOpcode = Mips::OR;
3208 break;
3209 case (Mips::SLTi):
3210 FinalOpcode = Mips::SLT;
3211 break;
3212 case (Mips::SLTiu):
3213 FinalOpcode = Mips::SLTu;
3214 break;
3215 case (Mips::XORi):
3216 FinalOpcode = Mips::XOR;
3217 break;
3218 }
3219
3220 MCInst tmpInst;
3221
3222 tmpInst.clear();
3223 tmpInst.setLoc(Inst.getLoc());
3224 tmpInst.setOpcode(FinalOpcode);
3225 if (FinalDstReg == Mips::NoRegister) {
3226 tmpInst.addOperand(MCOperand::createReg(DstReg));
3227 tmpInst.addOperand(MCOperand::createReg(DstReg));
3228 tmpInst.addOperand(MCOperand::createReg(SrcReg));
3229 } else {
3230 tmpInst.addOperand(MCOperand::createReg(FinalDstReg));
3231 tmpInst.addOperand(MCOperand::createReg(FinalDstReg));
3232 tmpInst.addOperand(MCOperand::createReg(DstReg));
3233 }
3234 Instructions.push_back(tmpInst);
3235 return false;
3236 }
3237 return true;
3238}
3239
Toma Tabacu234482a2015-03-16 12:03:39 +00003240void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
3241 SmallVectorImpl<MCInst> &Instructions) {
3242 MCInst NopInst;
3243 if (hasShortDelaySlot) {
3244 NopInst.setOpcode(Mips::MOVE16_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003245 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
3246 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
Toma Tabacu234482a2015-03-16 12:03:39 +00003247 } else {
3248 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00003249 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
3250 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
3251 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu234482a2015-03-16 12:03:39 +00003252 }
3253 Instructions.push_back(NopInst);
3254}
3255
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003256void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +00003257 unsigned TrgReg, bool Is64Bit,
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003258 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders03f9c012015-07-14 12:24:22 +00003259 emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
3260 Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003261}
3262
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003263void MipsAsmParser::createCpRestoreMemOp(
3264 bool IsLoad, int StackOffset, SMLoc IDLoc,
3265 SmallVectorImpl<MCInst> &Instructions) {
3266 MCInst MemInst;
3267 MemInst.setOpcode(IsLoad ? Mips::LW : Mips::SW);
3268 MemInst.addOperand(MCOperand::createReg(Mips::GP));
3269 MemInst.addOperand(MCOperand::createReg(Mips::SP));
3270 MemInst.addOperand(MCOperand::createImm(StackOffset));
3271
3272 // If the offset can not fit into 16 bits, we need to expand.
3273 if (!isInt<16>(StackOffset))
3274 expandMemInst(MemInst, IDLoc, Instructions, IsLoad, true /*HasImmOpnd*/);
3275 else
3276 Instructions.push_back(MemInst);
3277}
3278
Matheus Almeida595fcab2014-06-11 15:05:56 +00003279unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3280 // As described by the Mips32r2 spec, the registers Rd and Rs for
3281 // jalr.hb must be different.
3282 unsigned Opcode = Inst.getOpcode();
3283
3284 if (Opcode == Mips::JALR_HB &&
3285 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3286 return Match_RequiresDifferentSrcAndDst;
3287
3288 return Match_Success;
3289}
3290
David Blaikie960ea3f2014-06-08 16:18:35 +00003291bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3292 OperandVector &Operands,
3293 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003294 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003295 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003296
Jack Carterb4dbc172012-09-05 23:34:03 +00003297 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00003298 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00003299 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003300 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003301
3302 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003303 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003304 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00003305 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00003306 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00003307 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00003308 return false;
3309 }
3310 case Match_MissingFeature:
3311 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3312 return true;
3313 case Match_InvalidOperand: {
3314 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003315 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003316 if (ErrorInfo >= Operands.size())
3317 return Error(IDLoc, "too few operands for instruction");
3318
David Blaikie960ea3f2014-06-08 16:18:35 +00003319 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003320 if (ErrorLoc == SMLoc())
3321 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003322 }
3323
3324 return Error(ErrorLoc, "invalid operand for instruction");
3325 }
3326 case Match_MnemonicFail:
3327 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003328 case Match_RequiresDifferentSrcAndDst:
3329 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00003330 }
Craig Topper589ceee2015-01-03 08:16:34 +00003331
3332 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003333}
3334
Toma Tabacud9d344b2015-04-27 14:05:04 +00003335void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3336 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3337 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3338 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003339}
3340
Toma Tabacu81496c12015-05-20 08:54:45 +00003341void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3342 if (!AssemblerOptions.back()->isMacro())
3343 Warning(Loc, "macro instruction expanded into multiple instructions");
3344}
3345
Daniel Sandersef638fe2014-10-03 15:37:37 +00003346void
3347MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3348 SMRange Range, bool ShowColors) {
3349 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003350 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003351 ShowColors);
3352}
3353
Jack Carter1ac53222013-02-20 23:11:17 +00003354int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003355 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003356
Vladimir Medic4c299852013-11-06 11:27:05 +00003357 CC = StringSwitch<unsigned>(Name)
3358 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003359 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003360 .Case("a0", 4)
3361 .Case("a1", 5)
3362 .Case("a2", 6)
3363 .Case("a3", 7)
3364 .Case("v0", 2)
3365 .Case("v1", 3)
3366 .Case("s0", 16)
3367 .Case("s1", 17)
3368 .Case("s2", 18)
3369 .Case("s3", 19)
3370 .Case("s4", 20)
3371 .Case("s5", 21)
3372 .Case("s6", 22)
3373 .Case("s7", 23)
3374 .Case("k0", 26)
3375 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003376 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003377 .Case("sp", 29)
3378 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003379 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003380 .Case("ra", 31)
3381 .Case("t0", 8)
3382 .Case("t1", 9)
3383 .Case("t2", 10)
3384 .Case("t3", 11)
3385 .Case("t4", 12)
3386 .Case("t5", 13)
3387 .Case("t6", 14)
3388 .Case("t7", 15)
3389 .Case("t8", 24)
3390 .Case("t9", 25)
3391 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003392
Toma Tabacufda445c2014-09-15 15:33:01 +00003393 if (!(isABI_N32() || isABI_N64()))
3394 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003395
Daniel Sandersef638fe2014-10-03 15:37:37 +00003396 if (12 <= CC && CC <= 15) {
3397 // Name is one of t4-t7
3398 AsmToken RegTok = getLexer().peekTok();
3399 SMRange RegRange = RegTok.getLocRange();
3400
3401 StringRef FixedName = StringSwitch<StringRef>(Name)
3402 .Case("t4", "t0")
3403 .Case("t5", "t1")
3404 .Case("t6", "t2")
3405 .Case("t7", "t3")
3406 .Default("");
3407 assert(FixedName != "" && "Register name is not one of t4-t7.");
3408
3409 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3410 "Did you mean $" + FixedName + "?", RegRange);
3411 }
3412
Toma Tabacufda445c2014-09-15 15:33:01 +00003413 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3414 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3415 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3416 if (8 <= CC && CC <= 11)
3417 CC += 4;
3418
3419 if (CC == -1)
3420 CC = StringSwitch<unsigned>(Name)
3421 .Case("a4", 8)
3422 .Case("a5", 9)
3423 .Case("a6", 10)
3424 .Case("a7", 11)
3425 .Case("kt0", 26)
3426 .Case("kt1", 27)
3427 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003428
3429 return CC;
3430}
Jack Carterd0bd6422013-04-18 00:41:53 +00003431
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003432int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3433 int CC;
3434
3435 CC = StringSwitch<unsigned>(Name)
3436 .Case("hwr_cpunum", 0)
3437 .Case("hwr_synci_step", 1)
3438 .Case("hwr_cc", 2)
3439 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003440 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003441 .Default(-1);
3442
3443 return CC;
3444}
3445
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003446int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003447
Jack Cartera63b16a2012-09-07 00:23:42 +00003448 if (Name[0] == 'f') {
3449 StringRef NumString = Name.substr(1);
3450 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003451 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003452 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003453 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003454 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003455 return IntVal;
3456 }
3457 return -1;
3458}
Jack Cartera63b16a2012-09-07 00:23:42 +00003459
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003460int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3461
3462 if (Name.startswith("fcc")) {
3463 StringRef NumString = Name.substr(3);
3464 unsigned IntVal;
3465 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003466 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003467 if (IntVal > 7) // There are only 8 fcc registers.
3468 return -1;
3469 return IntVal;
3470 }
3471 return -1;
3472}
3473
3474int MipsAsmParser::matchACRegisterName(StringRef Name) {
3475
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003476 if (Name.startswith("ac")) {
3477 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003478 unsigned IntVal;
3479 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003480 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003481 if (IntVal > 3) // There are only 3 acc registers.
3482 return -1;
3483 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003484 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003485 return -1;
3486}
Jack Carterd0bd6422013-04-18 00:41:53 +00003487
Jack Carter5dc8ac92013-09-25 23:50:44 +00003488int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3489 unsigned IntVal;
3490
3491 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3492 return -1;
3493
3494 if (IntVal > 31)
3495 return -1;
3496
3497 return IntVal;
3498}
3499
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003500int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3501 int CC;
3502
3503 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003504 .Case("msair", 0)
3505 .Case("msacsr", 1)
3506 .Case("msaaccess", 2)
3507 .Case("msasave", 3)
3508 .Case("msamodify", 4)
3509 .Case("msarequest", 5)
3510 .Case("msamap", 6)
3511 .Case("msaunmap", 7)
3512 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003513
3514 return CC;
3515}
3516
Toma Tabacu89a712b2015-04-15 10:48:56 +00003517unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00003518 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00003519 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00003520 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00003521 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00003522 return 0;
3523 }
3524 unsigned AT = getReg(
3525 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00003526 return AT;
3527}
Jack Carter0b744b32012-10-04 02:29:46 +00003528
Jack Carterd0bd6422013-04-18 00:41:53 +00003529unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00003530 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00003531}
3532
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003533unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003534 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00003535 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003536}
3537
Jack Carter873c7242013-01-12 01:03:14 +00003538int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003539 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00003540 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00003541 return -1;
3542
Jack Carter873c7242013-01-12 01:03:14 +00003543 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00003544}
3545
Toma Tabacu13964452014-09-04 13:23:44 +00003546bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003547 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003548 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003549
Jack Carter30a59822012-10-04 04:03:53 +00003550 // Check if the current operand has a custom associated parser, if so, try to
3551 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00003552 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3553 if (ResTy == MatchOperand_Success)
3554 return false;
3555 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3556 // there was a match, but an error occurred, in which case, just return that
3557 // the operand parsing failed.
3558 if (ResTy == MatchOperand_ParseFail)
3559 return true;
3560
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003561 DEBUG(dbgs() << ".. Generic Parser\n");
3562
Jack Carterb4dbc172012-09-05 23:34:03 +00003563 switch (getLexer().getKind()) {
3564 default:
3565 Error(Parser.getTok().getLoc(), "unexpected token in operand");
3566 return true;
3567 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003568 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00003569 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00003570
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003571 // Almost all registers have been parsed by custom parsers. There is only
3572 // one exception to this. $zero (and it's alias $0) will reach this point
3573 // for div, divu, and similar instructions because it is not an operand
3574 // to the instruction definition but an explicit register. Special case
3575 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00003576 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00003577 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003578
Jack Carterd0bd6422013-04-18 00:41:53 +00003579 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00003580 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003581 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00003582 return true;
3583
Jack Carter873c7242013-01-12 01:03:14 +00003584 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00003585 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00003586 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00003587 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003588 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00003589
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003590 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003591 return false;
3592 }
Vladimir Medic4c299852013-11-06 11:27:05 +00003593 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00003594 case AsmToken::LParen:
3595 case AsmToken::Minus:
3596 case AsmToken::Plus:
3597 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003598 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00003599 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003600 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003601 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003602 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00003603 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00003604 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003605 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003606 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003607 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00003608 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00003609 return true;
3610
Jack Carter873c7242013-01-12 01:03:14 +00003611 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3612
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003613 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00003614 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003615 } // case AsmToken::Percent
3616 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00003617 return true;
3618}
3619
Vladimir Medic4c299852013-11-06 11:27:05 +00003620const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00003621 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003622 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00003623 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003624 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00003625 // It's a constant, evaluate reloc value.
3626 int16_t Val;
3627 switch (getVariantKind(RelocStr)) {
3628 case MCSymbolRefExpr::VK_Mips_ABS_LO:
3629 // Get the 1st 16-bits.
3630 Val = MCE->getValue() & 0xffff;
3631 break;
3632 case MCSymbolRefExpr::VK_Mips_ABS_HI:
3633 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
3634 // 16 bits being negative.
3635 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
3636 break;
3637 case MCSymbolRefExpr::VK_Mips_HIGHER:
3638 // Get the 3rd 16-bits.
3639 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
3640 break;
3641 case MCSymbolRefExpr::VK_Mips_HIGHEST:
3642 // Get the 4th 16-bits.
3643 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
3644 break;
3645 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00003646 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00003647 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00003648 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003649 }
3650
Jack Carterb5cf5902013-04-17 00:18:04 +00003651 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003652 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00003653 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00003654 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003655 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003656 return Res;
3657 }
3658
3659 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00003660 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
3661
Sasa Stankovic06c47802014-04-03 10:37:45 +00003662 // Try to create target expression.
3663 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00003664 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003665
Jack Carterd0bd6422013-04-18 00:41:53 +00003666 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
3667 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003668 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003669 return Res;
3670 }
3671
3672 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003673 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003674 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00003675 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00003676 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003677 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003678 return Expr;
3679}
3680
3681bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
3682
3683 switch (Expr->getKind()) {
3684 case MCExpr::Constant:
3685 return true;
3686 case MCExpr::SymbolRef:
3687 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
3688 case MCExpr::Binary:
3689 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
3690 if (!isEvaluated(BE->getLHS()))
3691 return false;
3692 return isEvaluated(BE->getRHS());
3693 }
3694 case MCExpr::Unary:
3695 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003696 case MCExpr::Target:
3697 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003698 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003699 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00003700}
Jack Carterd0bd6422013-04-18 00:41:53 +00003701
Jack Carterb5cf5902013-04-17 00:18:04 +00003702bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003703 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003704 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00003705 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00003706 if (Tok.isNot(AsmToken::Identifier))
3707 return true;
3708
Yaron Keren075759a2015-03-30 15:42:36 +00003709 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00003710
Jack Carterd0bd6422013-04-18 00:41:53 +00003711 Parser.Lex(); // Eat the identifier.
3712 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003713 const MCExpr *IdVal;
3714 SMLoc EndLoc;
3715
3716 if (getLexer().getKind() == AsmToken::LParen) {
3717 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003718 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003719 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003720 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003721 const AsmToken &nextTok = Parser.getTok();
3722 if (nextTok.isNot(AsmToken::Identifier))
3723 return true;
3724 Str += "(%";
3725 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00003726 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00003727 if (getLexer().getKind() != AsmToken::LParen)
3728 return true;
3729 } else
3730 break;
3731 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003732 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00003733 return true;
3734
3735 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00003736 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003737
3738 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00003739 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003740
Jack Carterd0bd6422013-04-18 00:41:53 +00003741 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00003742 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003743}
3744
Jack Carterb4dbc172012-09-05 23:34:03 +00003745bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
3746 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003747 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00003748 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003749 if (ResTy == MatchOperand_Success) {
3750 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00003751 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003752 StartLoc = Operand.getStartLoc();
3753 EndLoc = Operand.getEndLoc();
3754
3755 // AFAIK, we only support numeric registers and named GPR's in CFI
3756 // directives.
3757 // Don't worry about eating tokens before failing. Using an unrecognised
3758 // register is a parse error.
3759 if (Operand.isGPRAsmReg()) {
3760 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003761 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003762 }
3763
3764 return (RegNo == (unsigned)-1);
3765 }
3766
3767 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00003768 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00003769}
3770
Jack Carterb5cf5902013-04-17 00:18:04 +00003771bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003772 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00003773 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003774 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003775 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00003776
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003777 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003778 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003779 ++NumOfLParen;
3780 }
Jack Carter873c7242013-01-12 01:03:14 +00003781
Jack Carterd0bd6422013-04-18 00:41:53 +00003782 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003783 default:
3784 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00003785 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00003786 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00003787 case AsmToken::Integer:
3788 case AsmToken::Minus:
3789 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00003790 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003791 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00003792 else
3793 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00003794 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00003795 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003796 break;
Jack Carter873c7242013-01-12 01:03:14 +00003797 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00003798 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003799 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003800 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003801}
3802
David Blaikie960ea3f2014-06-08 16:18:35 +00003803MipsAsmParser::OperandMatchResultTy
3804MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003805 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003806 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00003807 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00003808 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003809 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003810 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00003811 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00003812 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00003813
Jack Carterb5cf5902013-04-17 00:18:04 +00003814 if (getLexer().getKind() == AsmToken::LParen) {
3815 Parser.Lex();
3816 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003817 }
3818
Jack Carterb5cf5902013-04-17 00:18:04 +00003819 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003820 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00003821 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003822
Jack Carterd0bd6422013-04-18 00:41:53 +00003823 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003824 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003825 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003826 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003827 SMLoc E =
3828 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003829 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003830 return MatchOperand_Success;
3831 }
3832 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003833 SMLoc E =
3834 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00003835
Jack Carterd0bd6422013-04-18 00:41:53 +00003836 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003837 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00003838 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003839 S, E, *this);
3840 Operands.push_back(
3841 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003842 return MatchOperand_Success;
3843 }
3844 Error(Parser.getTok().getLoc(), "'(' expected");
3845 return MatchOperand_ParseFail;
3846 }
3847
Jack Carterd0bd6422013-04-18 00:41:53 +00003848 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003849 }
3850
Toma Tabacu13964452014-09-04 13:23:44 +00003851 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003852 if (Res != MatchOperand_Success)
3853 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003854
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003855 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003856 Error(Parser.getTok().getLoc(), "')' expected");
3857 return MatchOperand_ParseFail;
3858 }
3859
Jack Carter873c7242013-01-12 01:03:14 +00003860 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3861
Jack Carterd0bd6422013-04-18 00:41:53 +00003862 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003863
Craig Topper062a2ba2014-04-25 05:30:21 +00003864 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003865 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003866
Jack Carterd0bd6422013-04-18 00:41:53 +00003867 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00003868 std::unique_ptr<MipsOperand> op(
3869 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00003870 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003871 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003872 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00003873 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003874 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
3875 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003876 if (IdVal->evaluateAsAbsolute(Imm))
3877 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003878 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003879 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00003880 getContext());
3881 }
3882
David Blaikie960ea3f2014-06-08 16:18:35 +00003883 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003884 return MatchOperand_Success;
3885}
3886
David Blaikie960ea3f2014-06-08 16:18:35 +00003887bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003888 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00003889 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00003890 if (Sym) {
3891 SMLoc S = Parser.getTok().getLoc();
3892 const MCExpr *Expr;
3893 if (Sym->isVariable())
3894 Expr = Sym->getVariableValue();
3895 else
3896 return false;
3897 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003898 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00003899 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00003900 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003901 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003902 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00003903 if (ResTy == MatchOperand_Success) {
3904 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00003905 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00003906 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003907 llvm_unreachable("Should never ParseFail");
3908 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00003909 }
3910 } else if (Expr->getKind() == MCExpr::Constant) {
3911 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00003912 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00003913 Operands.push_back(
3914 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00003915 return true;
3916 }
3917 }
3918 return false;
3919}
Jack Carterd0bd6422013-04-18 00:41:53 +00003920
Jack Carter873c7242013-01-12 01:03:14 +00003921MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003922MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00003923 StringRef Identifier,
3924 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003925 int Index = matchCPURegisterName(Identifier);
3926 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003927 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003928 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3929 return MatchOperand_Success;
3930 }
3931
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003932 Index = matchHWRegsRegisterName(Identifier);
3933 if (Index != -1) {
3934 Operands.push_back(MipsOperand::createHWRegsReg(
3935 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3936 return MatchOperand_Success;
3937 }
3938
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003939 Index = matchFPURegisterName(Identifier);
3940 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003941 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003942 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3943 return MatchOperand_Success;
3944 }
3945
3946 Index = matchFCCRegisterName(Identifier);
3947 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003948 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003949 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3950 return MatchOperand_Success;
3951 }
3952
3953 Index = matchACRegisterName(Identifier);
3954 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003955 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003956 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3957 return MatchOperand_Success;
3958 }
3959
3960 Index = matchMSA128RegisterName(Identifier);
3961 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003962 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003963 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3964 return MatchOperand_Success;
3965 }
3966
3967 Index = matchMSA128CtrlRegisterName(Identifier);
3968 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003969 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003970 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3971 return MatchOperand_Success;
3972 }
3973
3974 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00003975}
3976
3977MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003978MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003979 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00003980 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003981
3982 if (Token.is(AsmToken::Identifier)) {
3983 DEBUG(dbgs() << ".. identifier\n");
3984 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00003985 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003986 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00003987 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003988 } else if (Token.is(AsmToken::Integer)) {
3989 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003990 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003991 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
3992 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003993 return MatchOperand_Success;
3994 }
3995
3996 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
3997
3998 return MatchOperand_NoMatch;
3999}
4000
David Blaikie960ea3f2014-06-08 16:18:35 +00004001MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004002MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004003 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004004 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004005
4006 auto Token = Parser.getTok();
4007
4008 SMLoc S = Token.getLoc();
4009
4010 if (Token.isNot(AsmToken::Dollar)) {
4011 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4012 if (Token.is(AsmToken::Identifier)) {
4013 if (searchSymbolAlias(Operands))
4014 return MatchOperand_Success;
4015 }
4016 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4017 return MatchOperand_NoMatch;
4018 }
4019 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004020
Toma Tabacu13964452014-09-04 13:23:44 +00004021 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004022 if (ResTy == MatchOperand_Success) {
4023 Parser.Lex(); // $
4024 Parser.Lex(); // identifier
4025 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004026 return ResTy;
4027}
4028
4029MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004030MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004031 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004032 switch (getLexer().getKind()) {
4033 default:
4034 return MatchOperand_NoMatch;
4035 case AsmToken::LParen:
4036 case AsmToken::Minus:
4037 case AsmToken::Plus:
4038 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004039 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004040 case AsmToken::String:
4041 break;
4042 }
4043
4044 const MCExpr *IdVal;
4045 SMLoc S = Parser.getTok().getLoc();
4046 if (getParser().parseExpression(IdVal))
4047 return MatchOperand_ParseFail;
4048
4049 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4050 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4051 return MatchOperand_Success;
4052}
4053
David Blaikie960ea3f2014-06-08 16:18:35 +00004054MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004055MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004056 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004057 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004058
4059 SMLoc S = getLexer().getLoc();
4060
4061 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00004062 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004063 if (ResTy != MatchOperand_NoMatch)
4064 return ResTy;
4065
Daniel Sanders315386c2014-04-01 10:40:14 +00004066 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00004067 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00004068 if (ResTy != MatchOperand_NoMatch)
4069 return ResTy;
4070
Daniel Sandersffd84362014-04-01 10:41:48 +00004071 const MCExpr *Expr = nullptr;
4072 if (Parser.parseExpression(Expr)) {
4073 // We have no way of knowing if a symbol was consumed so we must ParseFail
4074 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004075 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004076 Operands.push_back(
4077 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004078 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004079}
4080
Vladimir Medic2b953d02013-10-01 09:48:56 +00004081MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004082MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004083 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004084 const MCExpr *IdVal;
4085 // If the first token is '$' we may have register operand.
4086 if (Parser.getTok().is(AsmToken::Dollar))
4087 return MatchOperand_NoMatch;
4088 SMLoc S = Parser.getTok().getLoc();
4089 if (getParser().parseExpression(IdVal))
4090 return MatchOperand_ParseFail;
4091 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004092 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004093 int64_t Val = MCE->getValue();
4094 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4095 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004096 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004097 return MatchOperand_Success;
4098}
4099
Matheus Almeida779c5932013-11-18 12:32:49 +00004100MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004101MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004102 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00004103 switch (getLexer().getKind()) {
4104 default:
4105 return MatchOperand_NoMatch;
4106 case AsmToken::LParen:
4107 case AsmToken::Plus:
4108 case AsmToken::Minus:
4109 case AsmToken::Integer:
4110 break;
4111 }
4112
4113 const MCExpr *Expr;
4114 SMLoc S = Parser.getTok().getLoc();
4115
4116 if (getParser().parseExpression(Expr))
4117 return MatchOperand_ParseFail;
4118
4119 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004120 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00004121 Error(S, "expected immediate value");
4122 return MatchOperand_ParseFail;
4123 }
4124
4125 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
4126 // and because the CPU always adds one to the immediate field, the allowed
4127 // range becomes 1..4. We'll only check the range here and will deal
4128 // with the addition/subtraction when actually decoding/encoding
4129 // the instruction.
4130 if (Val < 1 || Val > 4) {
4131 Error(S, "immediate not in range (1..4)");
4132 return MatchOperand_ParseFail;
4133 }
4134
Jack Carter3b2c96e2014-01-22 23:31:38 +00004135 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004136 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00004137 return MatchOperand_Success;
4138}
4139
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004140MipsAsmParser::OperandMatchResultTy
4141MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4142 MCAsmParser &Parser = getParser();
4143 SmallVector<unsigned, 10> Regs;
4144 unsigned RegNo;
4145 unsigned PrevReg = Mips::NoRegister;
4146 bool RegRange = false;
4147 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4148
4149 if (Parser.getTok().isNot(AsmToken::Dollar))
4150 return MatchOperand_ParseFail;
4151
4152 SMLoc S = Parser.getTok().getLoc();
4153 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4154 SMLoc E = getLexer().getLoc();
4155 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4156 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4157 if (RegRange) {
4158 // Remove last register operand because registers from register range
4159 // should be inserted first.
4160 if (RegNo == Mips::RA) {
4161 Regs.push_back(RegNo);
4162 } else {
4163 unsigned TmpReg = PrevReg + 1;
4164 while (TmpReg <= RegNo) {
4165 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
4166 Error(E, "invalid register operand");
4167 return MatchOperand_ParseFail;
4168 }
4169
4170 PrevReg = TmpReg;
4171 Regs.push_back(TmpReg++);
4172 }
4173 }
4174
4175 RegRange = false;
4176 } else {
4177 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
4178 (RegNo != Mips::RA)) {
4179 Error(E, "$16 or $31 expected");
4180 return MatchOperand_ParseFail;
4181 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
4182 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
4183 Error(E, "invalid register operand");
4184 return MatchOperand_ParseFail;
4185 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
4186 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
4187 Error(E, "consecutive register numbers expected");
4188 return MatchOperand_ParseFail;
4189 }
4190
4191 Regs.push_back(RegNo);
4192 }
4193
4194 if (Parser.getTok().is(AsmToken::Minus))
4195 RegRange = true;
4196
4197 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4198 !Parser.getTok().isNot(AsmToken::Comma)) {
4199 Error(E, "',' or '-' expected");
4200 return MatchOperand_ParseFail;
4201 }
4202
4203 Lex(); // Consume comma or minus
4204 if (Parser.getTok().isNot(AsmToken::Dollar))
4205 break;
4206
4207 PrevReg = RegNo;
4208 }
4209
4210 SMLoc E = Parser.getTok().getLoc();
4211 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4212 parseMemOperand(Operands);
4213 return MatchOperand_Success;
4214}
4215
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004216MipsAsmParser::OperandMatchResultTy
4217MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4218 MCAsmParser &Parser = getParser();
4219
4220 SMLoc S = Parser.getTok().getLoc();
4221 if (parseAnyRegister(Operands) != MatchOperand_Success)
4222 return MatchOperand_ParseFail;
4223
4224 SMLoc E = Parser.getTok().getLoc();
4225 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
4226 unsigned Reg = Op.getGPR32Reg();
4227 Operands.pop_back();
4228 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
4229 return MatchOperand_Success;
4230}
4231
Zoran Jovanovic41688672015-02-10 16:36:20 +00004232MipsAsmParser::OperandMatchResultTy
4233MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4234 MCAsmParser &Parser = getParser();
4235 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4236 SmallVector<unsigned, 10> Regs;
4237
4238 if (Parser.getTok().isNot(AsmToken::Dollar))
4239 return MatchOperand_ParseFail;
4240
4241 SMLoc S = Parser.getTok().getLoc();
4242
4243 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4244 return MatchOperand_ParseFail;
4245
4246 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4247 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4248 Regs.push_back(RegNo);
4249
4250 SMLoc E = Parser.getTok().getLoc();
4251 if (Parser.getTok().isNot(AsmToken::Comma)) {
4252 Error(E, "',' expected");
4253 return MatchOperand_ParseFail;
4254 }
4255
4256 // Remove comma.
4257 Parser.Lex();
4258
4259 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4260 return MatchOperand_ParseFail;
4261
4262 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4263 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4264 Regs.push_back(RegNo);
4265
4266 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4267
4268 return MatchOperand_Success;
4269}
4270
Jack Carterdc1e35d2012-09-06 20:00:02 +00004271MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
4272
Vladimir Medic4c299852013-11-06 11:27:05 +00004273 MCSymbolRefExpr::VariantKind VK =
4274 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
4275 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
4276 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
4277 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
4278 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
4279 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
4280 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
4281 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
4282 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
4283 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
4284 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
4285 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
4286 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
4287 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
4288 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
4289 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
4290 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
4291 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00004292 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
4293 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
4294 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
4295 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
4296 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
4297 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00004298 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
4299 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00004300 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004301
Matheus Almeida2852af82014-04-22 10:15:54 +00004302 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00004303
Jack Carterdc1e35d2012-09-06 20:00:02 +00004304 return VK;
4305}
Jack Cartera63b16a2012-09-07 00:23:42 +00004306
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004307/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4308/// either this.
4309/// ::= '(', register, ')'
4310/// handle it before we iterate so we don't get tripped up by the lack of
4311/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004312bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004313 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004314 if (getLexer().is(AsmToken::LParen)) {
4315 Operands.push_back(
4316 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4317 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004318 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004319 SMLoc Loc = getLexer().getLoc();
4320 Parser.eatToEndOfStatement();
4321 return Error(Loc, "unexpected token in argument list");
4322 }
4323 if (Parser.getTok().isNot(AsmToken::RParen)) {
4324 SMLoc Loc = getLexer().getLoc();
4325 Parser.eatToEndOfStatement();
4326 return Error(Loc, "unexpected token, expected ')'");
4327 }
4328 Operands.push_back(
4329 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4330 Parser.Lex();
4331 }
4332 return false;
4333}
4334
4335/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4336/// either one of these.
4337/// ::= '[', register, ']'
4338/// ::= '[', integer, ']'
4339/// handle it before we iterate so we don't get tripped up by the lack of
4340/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004341bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004342 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004343 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004344 if (getLexer().is(AsmToken::LBrac)) {
4345 Operands.push_back(
4346 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4347 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004348 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004349 SMLoc Loc = getLexer().getLoc();
4350 Parser.eatToEndOfStatement();
4351 return Error(Loc, "unexpected token in argument list");
4352 }
4353 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4354 SMLoc Loc = getLexer().getLoc();
4355 Parser.eatToEndOfStatement();
4356 return Error(Loc, "unexpected token, expected ']'");
4357 }
4358 Operands.push_back(
4359 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4360 Parser.Lex();
4361 }
4362 return false;
4363}
4364
David Blaikie960ea3f2014-06-08 16:18:35 +00004365bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4366 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004367 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004368 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004369
4370 // We have reached first instruction, module directive are now forbidden.
4371 getTargetStreamer().forbidModuleDirective();
4372
Vladimir Medic74593e62013-07-17 15:00:42 +00004373 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004374 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004375 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004376 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004377 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004378 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004379 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004380
4381 // Read the remaining operands.
4382 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4383 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004384 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004385 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004386 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004387 return Error(Loc, "unexpected token in argument list");
4388 }
Toma Tabacu13964452014-09-04 13:23:44 +00004389 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004390 return true;
4391 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004392
Jack Carterd0bd6422013-04-18 00:41:53 +00004393 while (getLexer().is(AsmToken::Comma)) {
4394 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004395 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004396 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004397 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004398 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004399 return Error(Loc, "unexpected token in argument list");
4400 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004401 // Parse bracket and parenthesis suffixes before we iterate
4402 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004403 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004404 return true;
4405 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004406 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004407 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004408 }
4409 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004410 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4411 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004412 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004413 return Error(Loc, "unexpected token in argument list");
4414 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004415 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004416 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004417}
4418
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004419bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004420 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004421 SMLoc Loc = getLexer().getLoc();
4422 Parser.eatToEndOfStatement();
4423 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004424}
4425
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004426bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004427 return Error(Loc, ErrorMsg);
4428}
4429
Jack Carter0b744b32012-10-04 02:29:46 +00004430bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004431 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004432 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004433
4434 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004435 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004436
4437 Parser.Lex(); // Eat "noat".
4438
Jack Carterd0bd6422013-04-18 00:41:53 +00004439 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004440 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004441 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004442 return false;
4443 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004444
4445 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004446 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004447 return false;
4448}
Jack Carterd0bd6422013-04-18 00:41:53 +00004449
Jack Carter0b744b32012-10-04 02:29:46 +00004450bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004451 // Line can be: ".set at", which sets $at to $1
4452 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004453 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004454 Parser.Lex(); // Eat "at".
4455
Jack Carter0b744b32012-10-04 02:29:46 +00004456 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004457 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004458 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004459
4460 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004461 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004462 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004463 }
4464
4465 if (getLexer().isNot(AsmToken::Equal)) {
4466 reportParseError("unexpected token, expected equals sign");
4467 return false;
4468 }
4469 Parser.Lex(); // Eat "=".
4470
4471 if (getLexer().isNot(AsmToken::Dollar)) {
4472 if (getLexer().is(AsmToken::EndOfStatement)) {
4473 reportParseError("no register specified");
4474 return false;
4475 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004476 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004477 return false;
4478 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004479 }
4480 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004481
Toma Tabacu16a74492015-02-13 10:30:57 +00004482 // Find out what "reg" is.
4483 unsigned AtRegNo;
4484 const AsmToken &Reg = Parser.getTok();
4485 if (Reg.is(AsmToken::Identifier)) {
4486 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4487 } else if (Reg.is(AsmToken::Integer)) {
4488 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004489 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004490 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004491 return false;
4492 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004493
4494 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004495 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004496 reportParseError("invalid register");
4497 return false;
4498 }
4499 Parser.Lex(); // Eat "reg".
4500
4501 // If this is not the end of the statement, report an error.
4502 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4503 reportParseError("unexpected token, expected end of statement");
4504 return false;
4505 }
4506
4507 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4508
4509 Parser.Lex(); // Consume the EndOfStatement.
4510 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004511}
4512
4513bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004514 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004515 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004516 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004517 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004518 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004519 return false;
4520 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004521 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004522 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004523 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004524 return false;
4525}
4526
4527bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004528 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004529 Parser.Lex();
4530 // If this is not the end of the statement, report an error.
4531 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004532 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004533 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00004534 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004535 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00004536 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004537 Parser.Lex(); // Consume the EndOfStatement.
4538 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004539}
4540
4541bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004542 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004543 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004544 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004545 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004546 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004547 return false;
4548 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004549 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004550 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004551 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004552 return false;
4553}
4554
4555bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004556 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004557 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004558 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004559 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004560 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004561 return false;
4562 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004563 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00004564 reportParseError("`noreorder' must be set before `nomacro'");
4565 return false;
4566 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004567 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004568 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004569 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004570 return false;
4571}
Jack Carterd76b2372013-03-21 21:44:16 +00004572
Daniel Sanders44934432014-08-07 12:03:36 +00004573bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004574 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004575 Parser.Lex();
4576
4577 // If this is not the end of the statement, report an error.
4578 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004579 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004580
4581 setFeatureBits(Mips::FeatureMSA, "msa");
4582 getTargetStreamer().emitDirectiveSetMsa();
4583 return false;
4584}
4585
4586bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004587 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004588 Parser.Lex();
4589
4590 // If this is not the end of the statement, report an error.
4591 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004592 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004593
4594 clearFeatureBits(Mips::FeatureMSA, "msa");
4595 getTargetStreamer().emitDirectiveSetNoMsa();
4596 return false;
4597}
4598
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004599bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004600 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004601 Parser.Lex(); // Eat "nodsp".
4602
4603 // If this is not the end of the statement, report an error.
4604 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4605 reportParseError("unexpected token, expected end of statement");
4606 return false;
4607 }
4608
4609 clearFeatureBits(Mips::FeatureDSP, "dsp");
4610 getTargetStreamer().emitDirectiveSetNoDsp();
4611 return false;
4612}
4613
Toma Tabacucc2502d2014-11-04 17:18:07 +00004614bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004615 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004616 Parser.Lex(); // Eat "mips16".
4617
Jack Carter39536722014-01-22 23:08:42 +00004618 // If this is not the end of the statement, report an error.
4619 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004620 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00004621 return false;
4622 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00004623
4624 setFeatureBits(Mips::FeatureMips16, "mips16");
4625 getTargetStreamer().emitDirectiveSetMips16();
4626 Parser.Lex(); // Consume the EndOfStatement.
4627 return false;
4628}
4629
4630bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004631 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004632 Parser.Lex(); // Eat "nomips16".
4633
4634 // If this is not the end of the statement, report an error.
4635 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4636 reportParseError("unexpected token, expected end of statement");
4637 return false;
4638 }
4639
4640 clearFeatureBits(Mips::FeatureMips16, "mips16");
4641 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00004642 Parser.Lex(); // Consume the EndOfStatement.
4643 return false;
4644}
4645
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004646bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004647 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004648 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004649 // Line can be: .set fp=32
4650 // .set fp=xx
4651 // .set fp=64
4652 Parser.Lex(); // Eat fp token
4653 AsmToken Tok = Parser.getTok();
4654 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004655 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004656 return false;
4657 }
4658 Parser.Lex(); // Eat '=' token.
4659 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004660
4661 if (!parseFpABIValue(FpAbiVal, ".set"))
4662 return false;
4663
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004664 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004665 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004666 return false;
4667 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004668 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004669 Parser.Lex(); // Consume the EndOfStatement.
4670 return false;
4671}
4672
Toma Tabacu32c72aa2015-06-30 09:36:50 +00004673bool MipsAsmParser::parseSetOddSPRegDirective() {
4674 MCAsmParser &Parser = getParser();
4675
4676 Parser.Lex(); // Eat "oddspreg".
4677 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4678 reportParseError("unexpected token, expected end of statement");
4679 return false;
4680 }
4681
4682 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4683 getTargetStreamer().emitDirectiveSetOddSPReg();
4684 return false;
4685}
4686
4687bool MipsAsmParser::parseSetNoOddSPRegDirective() {
4688 MCAsmParser &Parser = getParser();
4689
4690 Parser.Lex(); // Eat "nooddspreg".
4691 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4692 reportParseError("unexpected token, expected end of statement");
4693 return false;
4694 }
4695
4696 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4697 getTargetStreamer().emitDirectiveSetNoOddSPReg();
4698 return false;
4699}
4700
Toma Tabacu9db22db2014-09-09 10:15:38 +00004701bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004702 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004703 SMLoc Loc = getLexer().getLoc();
4704
4705 Parser.Lex();
4706 if (getLexer().isNot(AsmToken::EndOfStatement))
4707 return reportParseError("unexpected token, expected end of statement");
4708
4709 // Always keep an element on the options "stack" to prevent the user
4710 // from changing the initial options. This is how we remember them.
4711 if (AssemblerOptions.size() == 2)
4712 return reportParseError(Loc, ".set pop with no .set push");
4713
4714 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00004715 setAvailableFeatures(
4716 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
4717 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00004718
4719 getTargetStreamer().emitDirectiveSetPop();
4720 return false;
4721}
4722
4723bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004724 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004725 Parser.Lex();
4726 if (getLexer().isNot(AsmToken::EndOfStatement))
4727 return reportParseError("unexpected token, expected end of statement");
4728
4729 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00004730 AssemblerOptions.push_back(
4731 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00004732
4733 getTargetStreamer().emitDirectiveSetPush();
4734 return false;
4735}
4736
Toma Tabacu29696502015-06-02 09:48:04 +00004737bool MipsAsmParser::parseSetSoftFloatDirective() {
4738 MCAsmParser &Parser = getParser();
4739 Parser.Lex();
4740 if (getLexer().isNot(AsmToken::EndOfStatement))
4741 return reportParseError("unexpected token, expected end of statement");
4742
4743 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4744 getTargetStreamer().emitDirectiveSetSoftFloat();
4745 return false;
4746}
4747
4748bool MipsAsmParser::parseSetHardFloatDirective() {
4749 MCAsmParser &Parser = getParser();
4750 Parser.Lex();
4751 if (getLexer().isNot(AsmToken::EndOfStatement))
4752 return reportParseError("unexpected token, expected end of statement");
4753
4754 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4755 getTargetStreamer().emitDirectiveSetHardFloat();
4756 return false;
4757}
4758
Jack Carterd76b2372013-03-21 21:44:16 +00004759bool MipsAsmParser::parseSetAssignment() {
4760 StringRef Name;
4761 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00004762 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00004763
4764 if (Parser.parseIdentifier(Name))
4765 reportParseError("expected identifier after .set");
4766
4767 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004768 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00004769 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00004770
Jack Carter3b2c96e2014-01-22 23:31:38 +00004771 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00004772 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00004773
Jim Grosbach6f482002015-05-18 18:43:14 +00004774 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00004775 Sym->setVariableValue(Value);
4776
4777 return false;
4778}
Jack Carterd0bd6422013-04-18 00:41:53 +00004779
Toma Tabacu26647792014-09-09 12:52:14 +00004780bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004781 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00004782 Parser.Lex();
4783 if (getLexer().isNot(AsmToken::EndOfStatement))
4784 return reportParseError("unexpected token, expected end of statement");
4785
4786 // Reset assembler options to their initial values.
Toma Tabacu465acfd2015-06-09 13:33:26 +00004787 setAvailableFeatures(
4788 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
4789 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00004790 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
4791
4792 getTargetStreamer().emitDirectiveSetMips0();
4793 return false;
4794}
4795
Toma Tabacu85618b32014-08-19 14:22:52 +00004796bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004797 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00004798 Parser.Lex();
4799 if (getLexer().isNot(AsmToken::Equal))
4800 return reportParseError("unexpected token, expected equals sign");
4801
4802 Parser.Lex();
4803 StringRef Arch;
4804 if (Parser.parseIdentifier(Arch))
4805 return reportParseError("expected arch identifier");
4806
4807 StringRef ArchFeatureName =
4808 StringSwitch<StringRef>(Arch)
4809 .Case("mips1", "mips1")
4810 .Case("mips2", "mips2")
4811 .Case("mips3", "mips3")
4812 .Case("mips4", "mips4")
4813 .Case("mips5", "mips5")
4814 .Case("mips32", "mips32")
4815 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004816 .Case("mips32r3", "mips32r3")
4817 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004818 .Case("mips32r6", "mips32r6")
4819 .Case("mips64", "mips64")
4820 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004821 .Case("mips64r3", "mips64r3")
4822 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004823 .Case("mips64r6", "mips64r6")
4824 .Case("cnmips", "cnmips")
4825 .Case("r4000", "mips3") // This is an implementation of Mips3.
4826 .Default("");
4827
4828 if (ArchFeatureName.empty())
4829 return reportParseError("unsupported architecture");
4830
4831 selectArch(ArchFeatureName);
4832 getTargetStreamer().emitDirectiveSetArch(Arch);
4833 return false;
4834}
4835
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004836bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004837 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004838 Parser.Lex();
4839 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004840 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004841
Matheus Almeida2852af82014-04-22 10:15:54 +00004842 switch (Feature) {
4843 default:
4844 llvm_unreachable("Unimplemented feature");
4845 case Mips::FeatureDSP:
4846 setFeatureBits(Mips::FeatureDSP, "dsp");
4847 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004848 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004849 case Mips::FeatureMicroMips:
4850 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004851 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004852 case Mips::FeatureMips1:
4853 selectArch("mips1");
4854 getTargetStreamer().emitDirectiveSetMips1();
4855 break;
4856 case Mips::FeatureMips2:
4857 selectArch("mips2");
4858 getTargetStreamer().emitDirectiveSetMips2();
4859 break;
4860 case Mips::FeatureMips3:
4861 selectArch("mips3");
4862 getTargetStreamer().emitDirectiveSetMips3();
4863 break;
4864 case Mips::FeatureMips4:
4865 selectArch("mips4");
4866 getTargetStreamer().emitDirectiveSetMips4();
4867 break;
4868 case Mips::FeatureMips5:
4869 selectArch("mips5");
4870 getTargetStreamer().emitDirectiveSetMips5();
4871 break;
4872 case Mips::FeatureMips32:
4873 selectArch("mips32");
4874 getTargetStreamer().emitDirectiveSetMips32();
4875 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004876 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004877 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004878 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004879 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004880 case Mips::FeatureMips32r3:
4881 selectArch("mips32r3");
4882 getTargetStreamer().emitDirectiveSetMips32R3();
4883 break;
4884 case Mips::FeatureMips32r5:
4885 selectArch("mips32r5");
4886 getTargetStreamer().emitDirectiveSetMips32R5();
4887 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004888 case Mips::FeatureMips32r6:
4889 selectArch("mips32r6");
4890 getTargetStreamer().emitDirectiveSetMips32R6();
4891 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004892 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004893 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00004894 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00004895 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004896 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004897 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004898 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00004899 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004900 case Mips::FeatureMips64r3:
4901 selectArch("mips64r3");
4902 getTargetStreamer().emitDirectiveSetMips64R3();
4903 break;
4904 case Mips::FeatureMips64r5:
4905 selectArch("mips64r5");
4906 getTargetStreamer().emitDirectiveSetMips64R5();
4907 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004908 case Mips::FeatureMips64r6:
4909 selectArch("mips64r6");
4910 getTargetStreamer().emitDirectiveSetMips64R6();
4911 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004912 }
4913 return false;
4914}
4915
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004916bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004917 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004918 if (getLexer().isNot(AsmToken::Comma)) {
4919 SMLoc Loc = getLexer().getLoc();
4920 Parser.eatToEndOfStatement();
4921 return Error(Loc, ErrorStr);
4922 }
4923
Matheus Almeida2852af82014-04-22 10:15:54 +00004924 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004925 return true;
4926}
4927
Daniel Sanderse2982ad2015-09-17 16:08:39 +00004928// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
4929// In this class, it is only used for .cprestore.
4930// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
4931// MipsTargetELFStreamer and MipsAsmParser.
4932bool MipsAsmParser::isPicAndNotNxxAbi() {
4933 return inPicMode() && !(isABI_N32() || isABI_N64());
4934}
4935
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004936bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00004937 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00004938 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004939
Toma Tabacudde4c462014-11-06 10:02:45 +00004940 if (inMips16Mode()) {
4941 reportParseError(".cpload is not supported in Mips16 mode");
4942 return false;
4943 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004944
David Blaikie960ea3f2014-06-08 16:18:35 +00004945 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00004946 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004947 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4948 reportParseError("expected register containing function address");
4949 return false;
4950 }
4951
David Blaikie960ea3f2014-06-08 16:18:35 +00004952 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
4953 if (!RegOpnd.isGPRAsmReg()) {
4954 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004955 return false;
4956 }
4957
Toma Tabacudde4c462014-11-06 10:02:45 +00004958 // If this is not the end of the statement, report an error.
4959 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4960 reportParseError("unexpected token, expected end of statement");
4961 return false;
4962 }
4963
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004964 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004965 return false;
4966}
4967
Daniel Sanderse2982ad2015-09-17 16:08:39 +00004968bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
4969 MCAsmParser &Parser = getParser();
4970
4971 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
4972 // is used in non-PIC mode.
4973
4974 if (inMips16Mode()) {
4975 reportParseError(".cprestore is not supported in Mips16 mode");
4976 return false;
4977 }
4978
4979 // Get the stack offset value.
4980 const MCExpr *StackOffset;
4981 int64_t StackOffsetVal;
4982 if (Parser.parseExpression(StackOffset)) {
4983 reportParseError("expected stack offset value");
4984 return false;
4985 }
4986
4987 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
4988 reportParseError("stack offset is not an absolute expression");
4989 return false;
4990 }
4991
4992 if (StackOffsetVal < 0) {
4993 Warning(Loc, ".cprestore with negative stack offset has no effect");
4994 IsCpRestoreSet = false;
4995 } else {
4996 IsCpRestoreSet = true;
4997 CpRestoreOffset = StackOffsetVal;
4998 }
4999
5000 // If this is not the end of the statement, report an error.
5001 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5002 reportParseError("unexpected token, expected end of statement");
5003 return false;
5004 }
5005
5006 // Store the $gp on the stack.
5007 SmallVector<MCInst, 3> StoreInsts;
5008 createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc,
5009 StoreInsts);
5010
5011 getTargetStreamer().emitDirectiveCpRestore(StoreInsts, CpRestoreOffset);
5012 Parser.Lex(); // Consume the EndOfStatement.
5013 return false;
5014}
5015
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005016bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005017 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005018 unsigned FuncReg;
5019 unsigned Save;
5020 bool SaveIsReg = true;
5021
Matheus Almeida7e815762014-06-18 13:08:59 +00005022 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005023 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005024 if (ResTy == MatchOperand_NoMatch) {
5025 reportParseError("expected register containing function address");
5026 Parser.eatToEndOfStatement();
5027 return false;
5028 }
5029
5030 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5031 if (!FuncRegOpnd.isGPRAsmReg()) {
5032 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
5033 Parser.eatToEndOfStatement();
5034 return false;
5035 }
5036
5037 FuncReg = FuncRegOpnd.getGPR32Reg();
5038 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005039
Toma Tabacu65f10572014-09-16 15:00:52 +00005040 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005041 return true;
5042
Toma Tabacu13964452014-09-04 13:23:44 +00005043 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005044 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005045 const MCExpr *OffsetExpr;
5046 int64_t OffsetVal;
5047 SMLoc ExprLoc = getLexer().getLoc();
5048
5049 if (Parser.parseExpression(OffsetExpr) ||
5050 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5051 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005052 Parser.eatToEndOfStatement();
5053 return false;
5054 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005055
5056 Save = OffsetVal;
5057 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005058 } else {
5059 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5060 if (!SaveOpnd.isGPRAsmReg()) {
5061 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5062 Parser.eatToEndOfStatement();
5063 return false;
5064 }
5065 Save = SaveOpnd.getGPR32Reg();
5066 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005067
Toma Tabacu65f10572014-09-16 15:00:52 +00005068 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005069 return true;
5070
Toma Tabacu8874eac2015-02-18 13:46:53 +00005071 const MCExpr *Expr;
5072 if (Parser.parseExpression(Expr)) {
5073 reportParseError("expected expression");
5074 return false;
5075 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005076
Toma Tabacu8874eac2015-02-18 13:46:53 +00005077 if (Expr->getKind() != MCExpr::SymbolRef) {
5078 reportParseError("expected symbol");
5079 return false;
5080 }
5081 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5082
Daniel Sandersf173dda2015-09-22 10:50:09 +00005083 CpSaveLocation = Save;
5084 CpSaveLocationIsRegister = SaveIsReg;
5085
Toma Tabacu8874eac2015-02-18 13:46:53 +00005086 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5087 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005088 return false;
5089}
5090
Daniel Sandersf173dda2015-09-22 10:50:09 +00005091bool MipsAsmParser::parseDirectiveCPReturn() {
5092 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5093 CpSaveLocationIsRegister);
5094 return false;
5095}
5096
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005097bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005098 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005099 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5100 const AsmToken &Tok = Parser.getTok();
5101
5102 if (Tok.getString() == "2008") {
5103 Parser.Lex();
5104 getTargetStreamer().emitDirectiveNaN2008();
5105 return false;
5106 } else if (Tok.getString() == "legacy") {
5107 Parser.Lex();
5108 getTargetStreamer().emitDirectiveNaNLegacy();
5109 return false;
5110 }
5111 }
5112 // If we don't recognize the option passed to the .nan
5113 // directive (e.g. no option or unknown option), emit an error.
5114 reportParseError("invalid option in .nan directive");
5115 return false;
5116}
5117
Jack Carter0b744b32012-10-04 02:29:46 +00005118bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005119 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005120 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005121 const AsmToken &Tok = Parser.getTok();
5122
5123 if (Tok.getString() == "noat") {
5124 return parseSetNoAtDirective();
5125 } else if (Tok.getString() == "at") {
5126 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005127 } else if (Tok.getString() == "arch") {
5128 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005129 } else if (Tok.getString() == "fp") {
5130 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005131 } else if (Tok.getString() == "oddspreg") {
5132 return parseSetOddSPRegDirective();
5133 } else if (Tok.getString() == "nooddspreg") {
5134 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005135 } else if (Tok.getString() == "pop") {
5136 return parseSetPopDirective();
5137 } else if (Tok.getString() == "push") {
5138 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005139 } else if (Tok.getString() == "reorder") {
5140 return parseSetReorderDirective();
5141 } else if (Tok.getString() == "noreorder") {
5142 return parseSetNoReorderDirective();
5143 } else if (Tok.getString() == "macro") {
5144 return parseSetMacroDirective();
5145 } else if (Tok.getString() == "nomacro") {
5146 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005147 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005148 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005149 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005150 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005151 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005152 getTargetStreamer().emitDirectiveSetNoMicroMips();
5153 Parser.eatToEndOfStatement();
5154 return false;
5155 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005156 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005157 } else if (Tok.getString() == "mips0") {
5158 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005159 } else if (Tok.getString() == "mips1") {
5160 return parseSetFeature(Mips::FeatureMips1);
5161 } else if (Tok.getString() == "mips2") {
5162 return parseSetFeature(Mips::FeatureMips2);
5163 } else if (Tok.getString() == "mips3") {
5164 return parseSetFeature(Mips::FeatureMips3);
5165 } else if (Tok.getString() == "mips4") {
5166 return parseSetFeature(Mips::FeatureMips4);
5167 } else if (Tok.getString() == "mips5") {
5168 return parseSetFeature(Mips::FeatureMips5);
5169 } else if (Tok.getString() == "mips32") {
5170 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005171 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005172 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005173 } else if (Tok.getString() == "mips32r3") {
5174 return parseSetFeature(Mips::FeatureMips32r3);
5175 } else if (Tok.getString() == "mips32r5") {
5176 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005177 } else if (Tok.getString() == "mips32r6") {
5178 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005179 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005180 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005181 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005182 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005183 } else if (Tok.getString() == "mips64r3") {
5184 return parseSetFeature(Mips::FeatureMips64r3);
5185 } else if (Tok.getString() == "mips64r5") {
5186 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005187 } else if (Tok.getString() == "mips64r6") {
5188 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005189 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005190 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005191 } else if (Tok.getString() == "nodsp") {
5192 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005193 } else if (Tok.getString() == "msa") {
5194 return parseSetMsaDirective();
5195 } else if (Tok.getString() == "nomsa") {
5196 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005197 } else if (Tok.getString() == "softfloat") {
5198 return parseSetSoftFloatDirective();
5199 } else if (Tok.getString() == "hardfloat") {
5200 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005201 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005202 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005203 parseSetAssignment();
5204 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005205 }
Jack Carter07c818d2013-01-25 01:31:34 +00005206
Jack Carter0b744b32012-10-04 02:29:46 +00005207 return true;
5208}
5209
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005210/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005211/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005212bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005213 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005214 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5215 for (;;) {
5216 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005217 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005218 return true;
5219
5220 getParser().getStreamer().EmitValue(Value, Size);
5221
5222 if (getLexer().is(AsmToken::EndOfStatement))
5223 break;
5224
Jack Carter07c818d2013-01-25 01:31:34 +00005225 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005226 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005227 Parser.Lex();
5228 }
5229 }
5230
5231 Parser.Lex();
5232 return false;
5233}
5234
Vladimir Medic4c299852013-11-06 11:27:05 +00005235/// parseDirectiveGpWord
5236/// ::= .gpword local_sym
5237bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005238 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005239 const MCExpr *Value;
5240 // EmitGPRel32Value requires an expression, so we are using base class
5241 // method to evaluate the expression.
5242 if (getParser().parseExpression(Value))
5243 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005244 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005245
Vladimir Medice10c1122013-11-13 13:18:04 +00005246 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005247 return Error(getLexer().getLoc(),
5248 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005249 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005250 return false;
5251}
5252
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005253/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005254/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005255bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005256 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005257 const MCExpr *Value;
5258 // EmitGPRel64Value requires an expression, so we are using base class
5259 // method to evaluate the expression.
5260 if (getParser().parseExpression(Value))
5261 return true;
5262 getParser().getStreamer().EmitGPRel64Value(Value);
5263
5264 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005265 return Error(getLexer().getLoc(),
5266 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005267 Parser.Lex(); // Eat EndOfStatement token.
5268 return false;
5269}
5270
Jack Carter0cd3c192014-01-06 23:27:31 +00005271bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005272 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005273 // Get the option token.
5274 AsmToken Tok = Parser.getTok();
5275 // At the moment only identifiers are supported.
5276 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005277 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005278 Parser.eatToEndOfStatement();
5279 return false;
5280 }
5281
5282 StringRef Option = Tok.getIdentifier();
5283
5284 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005285 // MipsAsmParser needs to know if the current PIC mode changes.
5286 IsPicEnabled = false;
5287
Jack Carter0cd3c192014-01-06 23:27:31 +00005288 getTargetStreamer().emitDirectiveOptionPic0();
5289 Parser.Lex();
5290 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5291 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005292 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005293 Parser.eatToEndOfStatement();
5294 }
5295 return false;
5296 }
5297
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005298 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005299 // MipsAsmParser needs to know if the current PIC mode changes.
5300 IsPicEnabled = true;
5301
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005302 getTargetStreamer().emitDirectiveOptionPic2();
5303 Parser.Lex();
5304 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5305 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005306 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005307 Parser.eatToEndOfStatement();
5308 }
5309 return false;
5310 }
5311
Jack Carter0cd3c192014-01-06 23:27:31 +00005312 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005313 Warning(Parser.getTok().getLoc(),
5314 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005315 Parser.eatToEndOfStatement();
5316 return false;
5317}
5318
Toma Tabacu9ca50962015-04-16 09:53:47 +00005319/// parseInsnDirective
5320/// ::= .insn
5321bool MipsAsmParser::parseInsnDirective() {
5322 // If this is not the end of the statement, report an error.
5323 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5324 reportParseError("unexpected token, expected end of statement");
5325 return false;
5326 }
5327
5328 // The actual label marking happens in
5329 // MipsELFStreamer::createPendingLabelRelocs().
5330 getTargetStreamer().emitDirectiveInsn();
5331
5332 getParser().Lex(); // Eat EndOfStatement token.
5333 return false;
5334}
5335
Daniel Sanders7e527422014-07-10 13:38:23 +00005336/// parseDirectiveModule
5337/// ::= .module oddspreg
5338/// ::= .module nooddspreg
5339/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005340/// ::= .module softfloat
5341/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005342bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005343 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005344 MCAsmLexer &Lexer = getLexer();
5345 SMLoc L = Lexer.getLoc();
5346
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005347 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005348 // TODO : get a better message.
5349 reportParseError(".module directive must appear before any code");
5350 return false;
5351 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005352
Toma Tabacuc405c822015-01-23 10:40:19 +00005353 StringRef Option;
5354 if (Parser.parseIdentifier(Option)) {
5355 reportParseError("expected .module option identifier");
5356 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005357 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005358
Toma Tabacuc405c822015-01-23 10:40:19 +00005359 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005360 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005361
Toma Tabacu3c499582015-06-25 10:56:57 +00005362 // Synchronize the abiflags information with the FeatureBits information we
5363 // changed above.
5364 getTargetStreamer().updateABIInfo(*this);
5365
5366 // If printing assembly, use the recently updated abiflags information.
5367 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5368 // emitted at the end).
5369 getTargetStreamer().emitDirectiveModuleOddSPReg();
5370
Toma Tabacuc405c822015-01-23 10:40:19 +00005371 // If this is not the end of the statement, report an error.
5372 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5373 reportParseError("unexpected token, expected end of statement");
5374 return false;
5375 }
5376
5377 return false; // parseDirectiveModule has finished successfully.
5378 } else if (Option == "nooddspreg") {
5379 if (!isABI_O32()) {
5380 Error(L, "'.module nooddspreg' requires the O32 ABI");
5381 return false;
5382 }
5383
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005384 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005385
Toma Tabacu3c499582015-06-25 10:56:57 +00005386 // Synchronize the abiflags information with the FeatureBits information we
5387 // changed above.
5388 getTargetStreamer().updateABIInfo(*this);
5389
5390 // If printing assembly, use the recently updated abiflags information.
5391 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5392 // emitted at the end).
5393 getTargetStreamer().emitDirectiveModuleOddSPReg();
5394
Toma Tabacuc405c822015-01-23 10:40:19 +00005395 // If this is not the end of the statement, report an error.
5396 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5397 reportParseError("unexpected token, expected end of statement");
5398 return false;
5399 }
5400
5401 return false; // parseDirectiveModule has finished successfully.
5402 } else if (Option == "fp") {
5403 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005404 } else if (Option == "softfloat") {
5405 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5406
5407 // Synchronize the ABI Flags information with the FeatureBits information we
5408 // updated above.
5409 getTargetStreamer().updateABIInfo(*this);
5410
5411 // If printing assembly, use the recently updated ABI Flags information.
5412 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5413 // emitted later).
5414 getTargetStreamer().emitDirectiveModuleSoftFloat();
5415
5416 // If this is not the end of the statement, report an error.
5417 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5418 reportParseError("unexpected token, expected end of statement");
5419 return false;
5420 }
5421
5422 return false; // parseDirectiveModule has finished successfully.
5423 } else if (Option == "hardfloat") {
5424 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5425
5426 // Synchronize the ABI Flags information with the FeatureBits information we
5427 // updated above.
5428 getTargetStreamer().updateABIInfo(*this);
5429
5430 // If printing assembly, use the recently updated ABI Flags information.
5431 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5432 // emitted later).
5433 getTargetStreamer().emitDirectiveModuleHardFloat();
5434
5435 // If this is not the end of the statement, report an error.
5436 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5437 reportParseError("unexpected token, expected end of statement");
5438 return false;
5439 }
5440
5441 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005442 } else {
5443 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5444 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005445}
5446
5447/// parseDirectiveModuleFP
5448/// ::= =32
5449/// ::= =xx
5450/// ::= =64
5451bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005452 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005453 MCAsmLexer &Lexer = getLexer();
5454
5455 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005456 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005457 return false;
5458 }
5459 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005460
Daniel Sanders7e527422014-07-10 13:38:23 +00005461 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005462 if (!parseFpABIValue(FpABI, ".module"))
5463 return false;
5464
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005465 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005466 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005467 return false;
5468 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005469
Toma Tabacua64e5402015-06-25 12:44:38 +00005470 // Synchronize the abiflags information with the FeatureBits information we
5471 // changed above.
5472 getTargetStreamer().updateABIInfo(*this);
5473
5474 // If printing assembly, use the recently updated abiflags information.
5475 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5476 // emitted at the end).
5477 getTargetStreamer().emitDirectiveModuleFP();
5478
Daniel Sanders7e527422014-07-10 13:38:23 +00005479 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005480 return false;
5481}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005482
Daniel Sanders7e527422014-07-10 13:38:23 +00005483bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005484 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005485 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005486 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005487 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005488
5489 if (Lexer.is(AsmToken::Identifier)) {
5490 StringRef Value = Parser.getTok().getString();
5491 Parser.Lex();
5492
5493 if (Value != "xx") {
5494 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5495 return false;
5496 }
5497
5498 if (!isABI_O32()) {
5499 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5500 return false;
5501 }
5502
Daniel Sanders7e527422014-07-10 13:38:23 +00005503 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005504 if (ModuleLevelOptions) {
5505 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5506 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5507 } else {
5508 setFeatureBits(Mips::FeatureFPXX, "fpxx");
5509 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5510 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005511 return true;
5512 }
5513
5514 if (Lexer.is(AsmToken::Integer)) {
5515 unsigned Value = Parser.getTok().getIntVal();
5516 Parser.Lex();
5517
5518 if (Value != 32 && Value != 64) {
5519 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5520 return false;
5521 }
5522
5523 if (Value == 32) {
5524 if (!isABI_O32()) {
5525 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
5526 return false;
5527 }
5528
Daniel Sanders7e527422014-07-10 13:38:23 +00005529 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005530 if (ModuleLevelOptions) {
5531 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5532 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5533 } else {
5534 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5535 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5536 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005537 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00005538 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005539 if (ModuleLevelOptions) {
5540 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5541 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5542 } else {
5543 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5544 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
5545 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005546 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005547
Daniel Sanders7e527422014-07-10 13:38:23 +00005548 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005549 }
5550
5551 return false;
5552}
5553
Jack Carter0b744b32012-10-04 02:29:46 +00005554bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005555 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005556 StringRef IDVal = DirectiveID.getString();
5557
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005558 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005559 return parseDirectiveCpLoad(DirectiveID.getLoc());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005560 if (IDVal == ".cprestore")
5561 return parseDirectiveCpRestore(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00005562 if (IDVal == ".dword") {
5563 parseDataDirective(8, DirectiveID.getLoc());
5564 return false;
5565 }
Jack Carterd0bd6422013-04-18 00:41:53 +00005566 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005567 StringRef SymbolName;
5568
5569 if (Parser.parseIdentifier(SymbolName)) {
5570 reportParseError("expected identifier after .ent");
5571 return false;
5572 }
5573
5574 // There's an undocumented extension that allows an integer to
5575 // follow the name of the procedure which AFAICS is ignored by GAS.
5576 // Example: .ent foo,2
5577 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5578 if (getLexer().isNot(AsmToken::Comma)) {
5579 // Even though we accept this undocumented extension for compatibility
5580 // reasons, the additional integer argument does not actually change
5581 // the behaviour of the '.ent' directive, so we would like to discourage
5582 // its use. We do this by not referring to the extended version in
5583 // error messages which are not directly related to its use.
5584 reportParseError("unexpected token, expected end of statement");
5585 return false;
5586 }
5587 Parser.Lex(); // Eat the comma.
5588 const MCExpr *DummyNumber;
5589 int64_t DummyNumberVal;
5590 // If the user was explicitly trying to use the extended version,
5591 // we still give helpful extension-related error messages.
5592 if (Parser.parseExpression(DummyNumber)) {
5593 reportParseError("expected number after comma");
5594 return false;
5595 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00005596 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005597 reportParseError("expected an absolute expression after comma");
5598 return false;
5599 }
5600 }
5601
5602 // If this is not the end of the statement, report an error.
5603 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5604 reportParseError("unexpected token, expected end of statement");
5605 return false;
5606 }
5607
Jim Grosbach6f482002015-05-18 18:43:14 +00005608 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005609
5610 getTargetStreamer().emitDirectiveEnt(*Sym);
5611 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005612 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005613 return false;
5614 }
5615
Jack Carter07c818d2013-01-25 01:31:34 +00005616 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005617 StringRef SymbolName;
5618
5619 if (Parser.parseIdentifier(SymbolName)) {
5620 reportParseError("expected identifier after .end");
5621 return false;
5622 }
5623
5624 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5625 reportParseError("unexpected token, expected end of statement");
5626 return false;
5627 }
5628
5629 if (CurrentFn == nullptr) {
5630 reportParseError(".end used without .ent");
5631 return false;
5632 }
5633
5634 if ((SymbolName != CurrentFn->getName())) {
5635 reportParseError(".end symbol does not match .ent symbol");
5636 return false;
5637 }
5638
5639 getTargetStreamer().emitDirectiveEnd(SymbolName);
5640 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005641 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005642 return false;
5643 }
5644
Jack Carter07c818d2013-01-25 01:31:34 +00005645 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005646 // .frame $stack_reg, frame_size_in_bytes, $return_reg
5647 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005648 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005649 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5650 reportParseError("expected stack register");
5651 return false;
5652 }
5653
5654 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5655 if (!StackRegOpnd.isGPRAsmReg()) {
5656 reportParseError(StackRegOpnd.getStartLoc(),
5657 "expected general purpose register");
5658 return false;
5659 }
5660 unsigned StackReg = StackRegOpnd.getGPR32Reg();
5661
5662 if (Parser.getTok().is(AsmToken::Comma))
5663 Parser.Lex();
5664 else {
5665 reportParseError("unexpected token, expected comma");
5666 return false;
5667 }
5668
5669 // Parse the frame size.
5670 const MCExpr *FrameSize;
5671 int64_t FrameSizeVal;
5672
5673 if (Parser.parseExpression(FrameSize)) {
5674 reportParseError("expected frame size value");
5675 return false;
5676 }
5677
Jim Grosbach13760bd2015-05-30 01:25:56 +00005678 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005679 reportParseError("frame size not an absolute expression");
5680 return false;
5681 }
5682
5683 if (Parser.getTok().is(AsmToken::Comma))
5684 Parser.Lex();
5685 else {
5686 reportParseError("unexpected token, expected comma");
5687 return false;
5688 }
5689
5690 // Parse the return register.
5691 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00005692 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005693 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5694 reportParseError("expected return register");
5695 return false;
5696 }
5697
5698 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5699 if (!ReturnRegOpnd.isGPRAsmReg()) {
5700 reportParseError(ReturnRegOpnd.getStartLoc(),
5701 "expected general purpose register");
5702 return false;
5703 }
5704
5705 // If this is not the end of the statement, report an error.
5706 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5707 reportParseError("unexpected token, expected end of statement");
5708 return false;
5709 }
5710
5711 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
5712 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005713 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005714 return false;
5715 }
5716
Jack Carter07c818d2013-01-25 01:31:34 +00005717 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00005718 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00005719 }
5720
Daniel Sandersd97a6342014-08-13 10:07:34 +00005721 if (IDVal == ".mask" || IDVal == ".fmask") {
5722 // .mask bitmask, frame_offset
5723 // bitmask: One bit for each register used.
5724 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
5725 // first register is expected to be saved.
5726 // Examples:
5727 // .mask 0x80000000, -4
5728 // .fmask 0x80000000, -4
5729 //
Jack Carterbe332172012-09-07 00:48:02 +00005730
Daniel Sandersd97a6342014-08-13 10:07:34 +00005731 // Parse the bitmask
5732 const MCExpr *BitMask;
5733 int64_t BitMaskVal;
5734
5735 if (Parser.parseExpression(BitMask)) {
5736 reportParseError("expected bitmask value");
5737 return false;
5738 }
5739
Jim Grosbach13760bd2015-05-30 01:25:56 +00005740 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005741 reportParseError("bitmask not an absolute expression");
5742 return false;
5743 }
5744
5745 if (Parser.getTok().is(AsmToken::Comma))
5746 Parser.Lex();
5747 else {
5748 reportParseError("unexpected token, expected comma");
5749 return false;
5750 }
5751
5752 // Parse the frame_offset
5753 const MCExpr *FrameOffset;
5754 int64_t FrameOffsetVal;
5755
5756 if (Parser.parseExpression(FrameOffset)) {
5757 reportParseError("expected frame offset value");
5758 return false;
5759 }
5760
Jim Grosbach13760bd2015-05-30 01:25:56 +00005761 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005762 reportParseError("frame offset not an absolute expression");
5763 return false;
5764 }
5765
5766 // If this is not the end of the statement, report an error.
5767 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5768 reportParseError("unexpected token, expected end of statement");
5769 return false;
5770 }
5771
5772 if (IDVal == ".mask")
5773 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
5774 else
5775 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00005776 return false;
5777 }
5778
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005779 if (IDVal == ".nan")
5780 return parseDirectiveNaN();
5781
Jack Carter07c818d2013-01-25 01:31:34 +00005782 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005783 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00005784 return false;
5785 }
5786
Rafael Espindolab59fb732014-03-28 18:50:26 +00005787 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005788 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005789 return false;
5790 }
5791
Jack Carter07c818d2013-01-25 01:31:34 +00005792 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005793 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00005794 return false;
5795 }
5796
Jack Carter0cd3c192014-01-06 23:27:31 +00005797 if (IDVal == ".option")
5798 return parseDirectiveOption();
5799
5800 if (IDVal == ".abicalls") {
5801 getTargetStreamer().emitDirectiveAbiCalls();
5802 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005803 Error(Parser.getTok().getLoc(),
5804 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005805 // Clear line
5806 Parser.eatToEndOfStatement();
5807 }
5808 return false;
5809 }
5810
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005811 if (IDVal == ".cpsetup")
5812 return parseDirectiveCPSetup();
5813
Daniel Sandersf173dda2015-09-22 10:50:09 +00005814 if (IDVal == ".cpreturn")
5815 return parseDirectiveCPReturn();
5816
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005817 if (IDVal == ".module")
5818 return parseDirectiveModule();
5819
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005820 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
5821 return parseInternalDirectiveReallowModule();
5822
Toma Tabacu9ca50962015-04-16 09:53:47 +00005823 if (IDVal == ".insn")
5824 return parseInsnDirective();
5825
Rafael Espindola870c4e92012-01-11 03:56:41 +00005826 return true;
5827}
5828
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005829bool MipsAsmParser::parseInternalDirectiveReallowModule() {
5830 // If this is not the end of the statement, report an error.
5831 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5832 reportParseError("unexpected token, expected end of statement");
5833 return false;
5834 }
5835
5836 getTargetStreamer().reallowModuleDirective();
5837
5838 getParser().Lex(); // Eat EndOfStatement token.
5839 return false;
5840}
5841
Rafael Espindola870c4e92012-01-11 03:56:41 +00005842extern "C" void LLVMInitializeMipsAsmParser() {
5843 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
5844 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
5845 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
5846 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
5847}
Jack Carterb4dbc172012-09-05 23:34:03 +00005848
5849#define GET_REGISTER_MATCHER
5850#define GET_MATCHER_IMPLEMENTATION
5851#include "MipsGenAsmMatcher.inc"