blob: 70cc6a614e2c9a1f7e3930efaa7ced41e2f59ea9 [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]; }
Zoran Jovanovic2e386d32015-10-12 16:07:25 +0000486 bool hasDSPR3() const { return STI.getFeatureBits()[Mips::FeatureDSPR3]; }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000487 bool hasMSA() const { return STI.getFeatureBits()[Mips::FeatureMSA]; }
Kai Nackee0245392015-01-27 19:11:28 +0000488 bool hasCnMips() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000489 return (STI.getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000490 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000491
Daniel Sandersa6994442015-08-18 12:33:54 +0000492 bool inPicMode() {
493 return IsPicEnabled;
494 }
495
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000496 bool inMips16Mode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000497 return STI.getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000498 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000499
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000500 bool useTraps() const {
501 return STI.getFeatureBits()[Mips::FeatureUseTCCInDIV];
502 }
503
Eric Christophere8ae3e32015-05-07 23:10:21 +0000504 bool useSoftFloat() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000505 return STI.getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000506 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000507
Toma Tabacud9d344b2015-04-27 14:05:04 +0000508 /// Warn if RegIndex is the same as the current AT.
509 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000510
511 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000512
513 bool isLittle() const { return IsLittleEndian; }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000514};
515}
516
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000517namespace {
518
519/// MipsOperand - Instances of this class represent a parsed Mips machine
520/// instruction.
521class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000522public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000523 /// Broad categories of register classes
524 /// The exact class is finalized by the render method.
525 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000526 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000527 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000528 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000529 RegKind_FCC = 4, /// FCC
530 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
531 RegKind_MSACtrl = 16, /// MSA control registers
532 RegKind_COP2 = 32, /// COP2
533 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
534 /// context).
535 RegKind_CCR = 128, /// CCR
536 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000537 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000538 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000539 /// Potentially any (e.g. $1)
540 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
541 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000542 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000543 };
544
545private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000546 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000547 k_Immediate, /// An immediate (possibly involving symbol references)
548 k_Memory, /// Base + Offset Memory Address
549 k_PhysRegister, /// A physical register from the Mips namespace
550 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000551 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000552 k_RegList, /// A physical register list
553 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000554 } Kind;
555
David Blaikie960ea3f2014-06-08 16:18:35 +0000556public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000557 MipsOperand(KindTy K, MipsAsmParser &Parser)
558 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
559
David Blaikie960ea3f2014-06-08 16:18:35 +0000560private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000561 /// For diagnostics, and checking the assembler temporary
562 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000563
Eric Christopher8996c5d2013-03-15 00:42:55 +0000564 struct Token {
565 const char *Data;
566 unsigned Length;
567 };
568
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000569 struct PhysRegOp {
570 unsigned Num; /// Register Number
571 };
572
573 struct RegIdxOp {
574 unsigned Index; /// Index into the register class
575 RegKind Kind; /// Bitfield of the kinds it could possibly be
576 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000577 };
578
579 struct ImmOp {
580 const MCExpr *Val;
581 };
582
583 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000584 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000585 const MCExpr *Off;
586 };
587
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000588 struct RegListOp {
589 SmallVector<unsigned, 10> *List;
590 };
591
Jack Carterb4dbc172012-09-05 23:34:03 +0000592 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000593 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000594 struct PhysRegOp PhysReg;
595 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000596 struct ImmOp Imm;
597 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000598 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000599 };
600
601 SMLoc StartLoc, EndLoc;
602
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000603 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000604 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
605 const MCRegisterInfo *RegInfo,
606 SMLoc S, SMLoc E,
607 MipsAsmParser &Parser) {
608 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000609 Op->RegIdx.Index = Index;
610 Op->RegIdx.RegInfo = RegInfo;
611 Op->RegIdx.Kind = RegKind;
612 Op->StartLoc = S;
613 Op->EndLoc = E;
614 return Op;
615 }
616
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000617public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000618 /// Coerce the register to GPR32 and return the real register for the current
619 /// target.
620 unsigned getGPR32Reg() const {
621 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000622 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000623 unsigned ClassID = Mips::GPR32RegClassID;
624 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000625 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000626
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000627 /// Coerce the register to GPR32 and return the real register for the current
628 /// target.
629 unsigned getGPRMM16Reg() const {
630 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
631 unsigned ClassID = Mips::GPR32RegClassID;
632 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
633 }
634
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000635 /// Coerce the register to GPR64 and return the real register for the current
636 /// target.
637 unsigned getGPR64Reg() const {
638 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
639 unsigned ClassID = Mips::GPR64RegClassID;
640 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000641 }
642
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000643private:
644 /// Coerce the register to AFGR64 and return the real register for the current
645 /// target.
646 unsigned getAFGR64Reg() const {
647 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
648 if (RegIdx.Index % 2 != 0)
649 AsmParser.Warning(StartLoc, "Float register should be even.");
650 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
651 .getRegister(RegIdx.Index / 2);
652 }
653
654 /// Coerce the register to FGR64 and return the real register for the current
655 /// target.
656 unsigned getFGR64Reg() const {
657 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
658 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
659 .getRegister(RegIdx.Index);
660 }
661
662 /// Coerce the register to FGR32 and return the real register for the current
663 /// target.
664 unsigned getFGR32Reg() const {
665 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
666 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
667 .getRegister(RegIdx.Index);
668 }
669
670 /// Coerce the register to FGRH32 and return the real register for the current
671 /// target.
672 unsigned getFGRH32Reg() const {
673 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
674 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
675 .getRegister(RegIdx.Index);
676 }
677
678 /// Coerce the register to FCC and return the real register for the current
679 /// target.
680 unsigned getFCCReg() const {
681 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
682 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
683 .getRegister(RegIdx.Index);
684 }
685
686 /// Coerce the register to MSA128 and return the real register for the current
687 /// target.
688 unsigned getMSA128Reg() const {
689 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
690 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
691 // identical
692 unsigned ClassID = Mips::MSA128BRegClassID;
693 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
694 }
695
696 /// Coerce the register to MSACtrl and return the real register for the
697 /// current target.
698 unsigned getMSACtrlReg() const {
699 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
700 unsigned ClassID = Mips::MSACtrlRegClassID;
701 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
702 }
703
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000704 /// Coerce the register to COP0 and return the real register for the
705 /// current target.
706 unsigned getCOP0Reg() const {
707 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
708 unsigned ClassID = Mips::COP0RegClassID;
709 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
710 }
711
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000712 /// Coerce the register to COP2 and return the real register for the
713 /// current target.
714 unsigned getCOP2Reg() const {
715 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
716 unsigned ClassID = Mips::COP2RegClassID;
717 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
718 }
719
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000720 /// Coerce the register to COP3 and return the real register for the
721 /// current target.
722 unsigned getCOP3Reg() const {
723 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
724 unsigned ClassID = Mips::COP3RegClassID;
725 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
726 }
727
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000728 /// Coerce the register to ACC64DSP and return the real register for the
729 /// current target.
730 unsigned getACC64DSPReg() const {
731 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
732 unsigned ClassID = Mips::ACC64DSPRegClassID;
733 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
734 }
735
736 /// Coerce the register to HI32DSP and return the real register for the
737 /// current target.
738 unsigned getHI32DSPReg() const {
739 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
740 unsigned ClassID = Mips::HI32DSPRegClassID;
741 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
742 }
743
744 /// Coerce the register to LO32DSP and return the real register for the
745 /// current target.
746 unsigned getLO32DSPReg() const {
747 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
748 unsigned ClassID = Mips::LO32DSPRegClassID;
749 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
750 }
751
752 /// Coerce the register to CCR and return the real register for the
753 /// current target.
754 unsigned getCCRReg() const {
755 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
756 unsigned ClassID = Mips::CCRRegClassID;
757 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
758 }
759
760 /// Coerce the register to HWRegs and return the real register for the
761 /// current target.
762 unsigned getHWRegsReg() const {
763 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
764 unsigned ClassID = Mips::HWRegsRegClassID;
765 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
766 }
767
768public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000769 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000770 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000771 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000772 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000773 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000774 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000775 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000776 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000777 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000778
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000779 void addRegOperands(MCInst &Inst, unsigned N) const {
780 llvm_unreachable("Use a custom parser instead");
781 }
782
Daniel Sanders21bce302014-04-01 12:35:23 +0000783 /// Render the operand to an MCInst as a GPR32
784 /// Asserts if the wrong number of operands are requested, or the operand
785 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000786 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
787 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000788 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000789 }
790
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000791 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
792 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000793 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000794 }
795
Jozef Kolek1904fa22014-11-24 14:25:53 +0000796 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
797 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000798 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000799 }
800
Zoran Jovanovic41688672015-02-10 16:36:20 +0000801 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
802 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000803 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000804 }
805
Daniel Sanders21bce302014-04-01 12:35:23 +0000806 /// Render the operand to an MCInst as a GPR64
807 /// Asserts if the wrong number of operands are requested, or the operand
808 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000809 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
810 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000811 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000812 }
813
814 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
815 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000816 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000817 }
818
819 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
820 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000821 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000822 }
823
824 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
825 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000826 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000827 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000828 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000829 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
830 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000831 }
832
833 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
834 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000835 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000836 }
837
838 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
839 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000840 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000841 }
842
843 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
844 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000845 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000846 }
847
848 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
849 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000850 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000851 }
852
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000853 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
854 assert(N == 1 && "Invalid number of operands!");
855 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
856 }
857
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000858 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
859 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000860 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000861 }
862
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000863 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
864 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000865 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000866 }
867
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000868 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
869 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000870 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000871 }
872
873 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
874 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000875 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000876 }
877
878 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
879 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000880 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000881 }
882
883 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
884 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000885 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000886 }
887
888 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
889 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000890 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000891 }
892
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000893 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000894 assert(N == 1 && "Invalid number of operands!");
895 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000896 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000897 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000898
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000899 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000900 assert(N == 2 && "Invalid number of operands!");
901
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000902 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
903 ? getMemBase()->getGPR64Reg()
904 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000905
906 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000907 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000908 }
909
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000910 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
911 assert(N == 2 && "Invalid number of operands!");
912
Jim Grosbache9119e42015-05-13 18:37:00 +0000913 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000914
915 const MCExpr *Expr = getMemOff();
916 addExpr(Inst, Expr);
917 }
918
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000919 void addRegListOperands(MCInst &Inst, unsigned N) const {
920 assert(N == 1 && "Invalid number of operands!");
921
922 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000923 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000924 }
925
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000926 void addRegPairOperands(MCInst &Inst, unsigned N) const {
927 assert(N == 2 && "Invalid number of operands!");
928 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +0000929 Inst.addOperand(MCOperand::createReg(RegNo++));
930 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000931 }
932
Zoran Jovanovic41688672015-02-10 16:36:20 +0000933 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
934 assert(N == 2 && "Invalid number of operands!");
935 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000936 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000937 }
938
Craig Topper56c590a2014-04-29 07:58:02 +0000939 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000940 // As a special case until we sort out the definition of div/divu, pretend
941 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
942 if (isGPRAsmReg() && RegIdx.Index == 0)
943 return true;
944
945 return Kind == k_PhysRegister;
946 }
947 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000948 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000949 bool isConstantImm() const {
950 return isImm() && dyn_cast<MCConstantExpr>(getImm());
951 }
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +0000952 template <unsigned Bits> bool isUImm() const {
953 return isImm() && isConstantImm() && isUInt<Bits>(getConstantImm());
954 }
Craig Topper56c590a2014-04-29 07:58:02 +0000955 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000956 // Note: It's not possible to pretend that other operand kinds are tokens.
957 // The matcher emitter checks tokens first.
958 return Kind == k_Token;
959 }
Craig Topper56c590a2014-04-29 07:58:02 +0000960 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000961 bool isConstantMemOff() const {
962 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
963 }
964 template <unsigned Bits> bool isMemWithSimmOffset() const {
Zoran Jovanovica6593ff2015-08-18 12:53:08 +0000965 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
966 && getMemBase()->isGPRAsmReg();
967 }
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +0000968 template <unsigned Bits> bool isMemWithSimmOffsetGPR() const {
969 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) &&
970 getMemBase()->isGPRAsmReg();
971 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000972 bool isMemWithGRPMM16Base() const {
973 return isMem() && getMemBase()->isMM16AsmReg();
974 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000975 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
976 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
977 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
978 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000979 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
980 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
981 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
982 && (getMemBase()->getGPR32Reg() == Mips::SP);
983 }
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +0000984 bool isUImm5Lsl2() const {
985 return (isImm() && isConstantImm() && isShiftedUInt<5, 2>(getConstantImm()));
986 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000987 bool isRegList16() const {
988 if (!isRegList())
989 return false;
990
991 int Size = RegList.List->size();
992 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
993 RegList.List->back() != Mips::RA)
994 return false;
995
996 int PrevReg = *RegList.List->begin();
997 for (int i = 1; i < Size - 1; i++) {
998 int Reg = (*(RegList.List))[i];
999 if ( Reg != PrevReg + 1)
1000 return false;
1001 PrevReg = Reg;
1002 }
1003
1004 return true;
1005 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001006 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001007 bool isLSAImm() const {
1008 if (!isConstantImm())
1009 return false;
1010 int64_t Val = getConstantImm();
1011 return 1 <= Val && Val <= 4;
1012 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001013 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001014 bool isMovePRegPair() const {
1015 if (Kind != k_RegList || RegList.List->size() != 2)
1016 return false;
1017
1018 unsigned R0 = RegList.List->front();
1019 unsigned R1 = RegList.List->back();
1020
1021 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1022 (R0 == Mips::A1 && R1 == Mips::A3) ||
1023 (R0 == Mips::A2 && R1 == Mips::A3) ||
1024 (R0 == Mips::A0 && R1 == Mips::S5) ||
1025 (R0 == Mips::A0 && R1 == Mips::S6) ||
1026 (R0 == Mips::A0 && R1 == Mips::A1) ||
1027 (R0 == Mips::A0 && R1 == Mips::A2) ||
1028 (R0 == Mips::A0 && R1 == Mips::A3))
1029 return true;
1030
1031 return false;
1032 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001033
1034 StringRef getToken() const {
1035 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001036 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001037 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001038 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001039
Craig Topper56c590a2014-04-29 07:58:02 +00001040 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001041 // As a special case until we sort out the definition of div/divu, pretend
1042 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1043 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1044 RegIdx.Kind & RegKind_GPR)
1045 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001046
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001047 assert(Kind == k_PhysRegister && "Invalid access!");
1048 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001049 }
1050
Jack Carterb4dbc172012-09-05 23:34:03 +00001051 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001052 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001053 return Imm.Val;
1054 }
1055
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001056 int64_t getConstantImm() const {
1057 const MCExpr *Val = getImm();
1058 return static_cast<const MCConstantExpr *>(Val)->getValue();
1059 }
1060
1061 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001062 assert((Kind == k_Memory) && "Invalid access!");
1063 return Mem.Base;
1064 }
1065
1066 const MCExpr *getMemOff() const {
1067 assert((Kind == k_Memory) && "Invalid access!");
1068 return Mem.Off;
1069 }
1070
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001071 int64_t getConstantMemOff() const {
1072 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1073 }
1074
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001075 const SmallVectorImpl<unsigned> &getRegList() const {
1076 assert((Kind == k_RegList) && "Invalid access!");
1077 return *(RegList.List);
1078 }
1079
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001080 unsigned getRegPair() const {
1081 assert((Kind == k_RegPair) && "Invalid access!");
1082 return RegIdx.Index;
1083 }
1084
David Blaikie960ea3f2014-06-08 16:18:35 +00001085 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1086 MipsAsmParser &Parser) {
1087 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001088 Op->Tok.Data = Str.data();
1089 Op->Tok.Length = Str.size();
1090 Op->StartLoc = S;
1091 Op->EndLoc = S;
1092 return Op;
1093 }
1094
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001095 /// Create a numeric register (e.g. $1). The exact register remains
1096 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001097 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001098 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001099 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001100 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001101 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001102 }
1103
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001104 /// Create a register that is definitely a GPR.
1105 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001106 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001107 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001108 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001109 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001110 }
1111
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001112 /// Create a register that is definitely a FGR.
1113 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001114 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001115 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001116 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001117 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1118 }
1119
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001120 /// Create a register that is definitely a HWReg.
1121 /// This is typically only used for named registers such as $hwr_cpunum.
1122 static std::unique_ptr<MipsOperand>
1123 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1124 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1125 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1126 }
1127
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001128 /// Create a register that is definitely an FCC.
1129 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001130 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001131 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001132 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001133 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1134 }
1135
1136 /// Create a register that is definitely an ACC.
1137 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001138 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001139 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001140 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001141 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1142 }
1143
1144 /// Create a register that is definitely an MSA128.
1145 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001146 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001147 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001148 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001149 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1150 }
1151
1152 /// Create a register that is definitely an MSACtrl.
1153 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001154 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001155 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001156 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001157 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1158 }
1159
David Blaikie960ea3f2014-06-08 16:18:35 +00001160 static std::unique_ptr<MipsOperand>
1161 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1162 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001163 Op->Imm.Val = Val;
1164 Op->StartLoc = S;
1165 Op->EndLoc = E;
1166 return Op;
1167 }
1168
David Blaikie960ea3f2014-06-08 16:18:35 +00001169 static std::unique_ptr<MipsOperand>
1170 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1171 SMLoc E, MipsAsmParser &Parser) {
1172 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1173 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001174 Op->Mem.Off = Off;
1175 Op->StartLoc = S;
1176 Op->EndLoc = E;
1177 return Op;
1178 }
1179
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001180 static std::unique_ptr<MipsOperand>
1181 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1182 MipsAsmParser &Parser) {
1183 assert (Regs.size() > 0 && "Empty list not allowed");
1184
1185 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001186 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001187 Op->StartLoc = StartLoc;
1188 Op->EndLoc = EndLoc;
1189 return Op;
1190 }
1191
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001192 static std::unique_ptr<MipsOperand>
1193 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1194 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1195 Op->RegIdx.Index = RegNo;
1196 Op->StartLoc = S;
1197 Op->EndLoc = E;
1198 return Op;
1199 }
1200
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001201 bool isGPRAsmReg() const {
1202 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001203 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001204 bool isMM16AsmReg() const {
1205 if (!(isRegIdx() && RegIdx.Kind))
1206 return false;
1207 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1208 || RegIdx.Index == 16 || RegIdx.Index == 17);
1209 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001210 bool isMM16AsmRegZero() const {
1211 if (!(isRegIdx() && RegIdx.Kind))
1212 return false;
1213 return (RegIdx.Index == 0 ||
1214 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1215 RegIdx.Index == 17);
1216 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001217 bool isMM16AsmRegMoveP() const {
1218 if (!(isRegIdx() && RegIdx.Kind))
1219 return false;
1220 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1221 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1222 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001223 bool isFGRAsmReg() const {
1224 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1225 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001226 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001227 bool isHWRegsAsmReg() const {
1228 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001229 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001230 bool isCCRAsmReg() const {
1231 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001232 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001233 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001234 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1235 return false;
1236 if (!AsmParser.hasEightFccRegisters())
1237 return RegIdx.Index == 0;
1238 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001239 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001240 bool isACCAsmReg() const {
1241 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001242 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001243 bool isCOP0AsmReg() const {
1244 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1245 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001246 bool isCOP2AsmReg() const {
1247 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001248 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001249 bool isCOP3AsmReg() const {
1250 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1251 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001252 bool isMSA128AsmReg() const {
1253 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001254 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001255 bool isMSACtrlAsmReg() const {
1256 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001257 }
1258
Jack Carterb4dbc172012-09-05 23:34:03 +00001259 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001260 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001261 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001262 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001263
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001264 virtual ~MipsOperand() {
1265 switch (Kind) {
1266 case k_Immediate:
1267 break;
1268 case k_Memory:
1269 delete Mem.Base;
1270 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001271 case k_RegList:
1272 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001273 case k_PhysRegister:
1274 case k_RegisterIndex:
1275 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001276 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001277 break;
1278 }
1279 }
1280
Craig Topper56c590a2014-04-29 07:58:02 +00001281 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001282 switch (Kind) {
1283 case k_Immediate:
1284 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001285 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001286 OS << ">";
1287 break;
1288 case k_Memory:
1289 OS << "Mem<";
1290 Mem.Base->print(OS);
1291 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001292 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001293 OS << ">";
1294 break;
1295 case k_PhysRegister:
1296 OS << "PhysReg<" << PhysReg.Num << ">";
1297 break;
1298 case k_RegisterIndex:
1299 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1300 break;
1301 case k_Token:
1302 OS << Tok.Data;
1303 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001304 case k_RegList:
1305 OS << "RegList< ";
1306 for (auto Reg : (*RegList.List))
1307 OS << Reg << " ";
1308 OS << ">";
1309 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001310 case k_RegPair:
1311 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1312 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001313 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001314 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001315}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001316} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001317
Jack Carter9e65aa32013-03-22 00:05:30 +00001318namespace llvm {
1319extern const MCInstrDesc MipsInsts[];
1320}
1321static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1322 return MipsInsts[Opcode];
1323}
1324
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001325static bool hasShortDelaySlot(unsigned Opcode) {
1326 switch (Opcode) {
1327 case Mips::JALS_MM:
1328 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001329 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001330 case Mips::BGEZALS_MM:
1331 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001332 return true;
1333 default:
1334 return false;
1335 }
1336}
1337
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001338static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1339 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1340 return &SRExpr->getSymbol();
1341 }
1342
1343 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1344 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1345 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1346
1347 if (LHSSym)
1348 return LHSSym;
1349
1350 if (RHSSym)
1351 return RHSSym;
1352
1353 return nullptr;
1354 }
1355
1356 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1357 return getSingleMCSymbol(UExpr->getSubExpr());
1358
1359 return nullptr;
1360}
1361
1362static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1363 if (isa<MCSymbolRefExpr>(Expr))
1364 return 1;
1365
1366 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1367 return countMCSymbolRefExpr(BExpr->getLHS()) +
1368 countMCSymbolRefExpr(BExpr->getRHS());
1369
1370 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1371 return countMCSymbolRefExpr(UExpr->getSubExpr());
1372
1373 return 0;
1374}
1375
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001376namespace {
1377void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc,
1378 SmallVectorImpl<MCInst> &Instructions) {
1379 MCInst tmpInst;
1380 tmpInst.setOpcode(Opcode);
1381 tmpInst.addOperand(MCOperand::createReg(Reg0));
1382 tmpInst.addOperand(Op1);
1383 tmpInst.setLoc(IDLoc);
1384 Instructions.push_back(tmpInst);
1385}
1386
1387void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc,
1388 SmallVectorImpl<MCInst> &Instructions) {
1389 emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions);
1390}
1391
1392void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc,
1393 SmallVectorImpl<MCInst> &Instructions) {
1394 emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, Instructions);
1395}
1396
1397void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc,
1398 SmallVectorImpl<MCInst> &Instructions) {
1399 MCInst tmpInst;
1400 tmpInst.setOpcode(Opcode);
1401 tmpInst.addOperand(MCOperand::createImm(Imm1));
1402 tmpInst.addOperand(MCOperand::createImm(Imm2));
1403 tmpInst.setLoc(IDLoc);
1404 Instructions.push_back(tmpInst);
1405}
1406
1407void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
1408 SmallVectorImpl<MCInst> &Instructions) {
1409 MCInst tmpInst;
1410 tmpInst.setOpcode(Opcode);
1411 tmpInst.addOperand(MCOperand::createReg(Reg0));
1412 tmpInst.setLoc(IDLoc);
1413 Instructions.push_back(tmpInst);
1414}
1415
1416void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2,
1417 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1418 MCInst tmpInst;
1419 tmpInst.setOpcode(Opcode);
1420 tmpInst.addOperand(MCOperand::createReg(Reg0));
1421 tmpInst.addOperand(MCOperand::createReg(Reg1));
1422 tmpInst.addOperand(Op2);
1423 tmpInst.setLoc(IDLoc);
1424 Instructions.push_back(tmpInst);
1425}
1426
1427void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
1428 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1429 emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc,
1430 Instructions);
1431}
1432
1433void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
1434 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1435 emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc,
1436 Instructions);
1437}
1438
1439void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount,
1440 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1441 if (ShiftAmount >= 32) {
1442 emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc,
1443 Instructions);
1444 return;
1445 }
1446
1447 emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions);
1448}
1449} // end anonymous namespace.
1450
Jack Carter9e65aa32013-03-22 00:05:30 +00001451bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001452 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001453 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001454 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001455
Jack Carter9e65aa32013-03-22 00:05:30 +00001456 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001457
1458 if (MCID.isBranch() || MCID.isCall()) {
1459 const unsigned Opcode = Inst.getOpcode();
1460 MCOperand Offset;
1461
1462 switch (Opcode) {
1463 default:
1464 break;
Kai Nackee0245392015-01-27 19:11:28 +00001465 case Mips::BBIT0:
1466 case Mips::BBIT032:
1467 case Mips::BBIT1:
1468 case Mips::BBIT132:
1469 assert(hasCnMips() && "instruction only valid for octeon cpus");
1470 // Fall through
1471
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001472 case Mips::BEQ:
1473 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001474 case Mips::BEQ_MM:
1475 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001476 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001477 Offset = Inst.getOperand(2);
1478 if (!Offset.isImm())
1479 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001480 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001481 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001482 if (OffsetToAlignment(Offset.getImm(),
1483 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001484 return Error(IDLoc, "branch to misaligned address");
1485 break;
1486 case Mips::BGEZ:
1487 case Mips::BGTZ:
1488 case Mips::BLEZ:
1489 case Mips::BLTZ:
1490 case Mips::BGEZAL:
1491 case Mips::BLTZAL:
1492 case Mips::BC1F:
1493 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001494 case Mips::BGEZ_MM:
1495 case Mips::BGTZ_MM:
1496 case Mips::BLEZ_MM:
1497 case Mips::BLTZ_MM:
1498 case Mips::BGEZAL_MM:
1499 case Mips::BLTZAL_MM:
1500 case Mips::BC1F_MM:
1501 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001502 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001503 Offset = Inst.getOperand(1);
1504 if (!Offset.isImm())
1505 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001506 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001507 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001508 if (OffsetToAlignment(Offset.getImm(),
1509 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001510 return Error(IDLoc, "branch to misaligned address");
1511 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001512 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001513 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001514 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001515 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001516 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1517 Offset = Inst.getOperand(1);
1518 if (!Offset.isImm())
1519 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001520 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001521 return Error(IDLoc, "branch target out of range");
1522 if (OffsetToAlignment(Offset.getImm(), 2LL))
1523 return Error(IDLoc, "branch to misaligned address");
1524 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001525 }
1526 }
1527
Daniel Sandersa84989a2014-06-16 13:25:35 +00001528 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1529 // We still accept it but it is a normal nop.
1530 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1531 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1532 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1533 "nop instruction");
1534 }
1535
Kai Nackee0245392015-01-27 19:11:28 +00001536 if (hasCnMips()) {
1537 const unsigned Opcode = Inst.getOpcode();
1538 MCOperand Opnd;
1539 int Imm;
1540
1541 switch (Opcode) {
1542 default:
1543 break;
1544
1545 case Mips::BBIT0:
1546 case Mips::BBIT032:
1547 case Mips::BBIT1:
1548 case Mips::BBIT132:
1549 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1550 // The offset is handled above
1551 Opnd = Inst.getOperand(1);
1552 if (!Opnd.isImm())
1553 return Error(IDLoc, "expected immediate operand kind");
1554 Imm = Opnd.getImm();
1555 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1556 Opcode == Mips::BBIT1 ? 63 : 31))
1557 return Error(IDLoc, "immediate operand value out of range");
1558 if (Imm > 31) {
1559 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1560 : Mips::BBIT132);
1561 Inst.getOperand(1).setImm(Imm - 32);
1562 }
1563 break;
1564
1565 case Mips::CINS:
1566 case Mips::CINS32:
1567 case Mips::EXTS:
1568 case Mips::EXTS32:
1569 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1570 // Check length
1571 Opnd = Inst.getOperand(3);
1572 if (!Opnd.isImm())
1573 return Error(IDLoc, "expected immediate operand kind");
1574 Imm = Opnd.getImm();
1575 if (Imm < 0 || Imm > 31)
1576 return Error(IDLoc, "immediate operand value out of range");
1577 // Check position
1578 Opnd = Inst.getOperand(2);
1579 if (!Opnd.isImm())
1580 return Error(IDLoc, "expected immediate operand kind");
1581 Imm = Opnd.getImm();
1582 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1583 Opcode == Mips::EXTS ? 63 : 31))
1584 return Error(IDLoc, "immediate operand value out of range");
1585 if (Imm > 31) {
1586 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1587 Inst.getOperand(2).setImm(Imm - 32);
1588 }
1589 break;
1590
1591 case Mips::SEQi:
1592 case Mips::SNEi:
1593 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1594 Opnd = Inst.getOperand(2);
1595 if (!Opnd.isImm())
1596 return Error(IDLoc, "expected immediate operand kind");
1597 Imm = Opnd.getImm();
1598 if (!isInt<10>(Imm))
1599 return Error(IDLoc, "immediate operand value out of range");
1600 break;
1601 }
1602 }
1603
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001604 // This expansion is not in a function called by expandInstruction() because
1605 // the pseudo-instruction doesn't have a distinct opcode.
1606 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1607 inPicMode()) {
1608 warnIfNoMacro(IDLoc);
1609
1610 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1611
1612 // We can do this expansion if there's only 1 symbol in the argument
1613 // expression.
1614 if (countMCSymbolRefExpr(JalExpr) > 1)
1615 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1616
1617 // FIXME: This is checking the expression can be handled by the later stages
1618 // of the assembler. We ought to leave it to those later stages but
1619 // we can't do that until we stop evaluateRelocExpr() rewriting the
1620 // expressions into non-equivalent forms.
1621 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1622
1623 // FIXME: Add support for label+offset operands (currently causes an error).
1624 // FIXME: Add support for forward-declared local symbols.
1625 // FIXME: Add expansion for when the LargeGOT option is enabled.
1626 if (JalSym->isInSection() || JalSym->isTemporary()) {
1627 if (isABI_O32()) {
1628 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001629 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001630 // R_(MICRO)MIPS_GOT16 label
1631 // addiu $25, $25, 0
1632 // R_(MICRO)MIPS_LO16 label
1633 // jalr $25
1634 const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
1635 const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
1636
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001637 emitRRX(Mips::LW, Mips::T9, Mips::GP,
1638 MCOperand::createExpr(Got16RelocExpr), IDLoc, Instructions);
1639 emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1640 MCOperand::createExpr(Lo16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001641 } else if (isABI_N32() || isABI_N64()) {
1642 // If it's a local symbol and the N32/N64 ABIs are being used,
1643 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001644 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001645 // R_(MICRO)MIPS_GOT_DISP label
1646 // jalr $25
1647 const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
1648
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001649 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1650 MCOperand::createExpr(GotDispRelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001651 }
1652 } else {
1653 // If it's an external/weak symbol, we expand to:
1654 // lw/ld $25, 0($gp)
1655 // R_(MICRO)MIPS_CALL16 label
1656 // jalr $25
1657 const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
1658
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001659 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1660 MCOperand::createExpr(Call16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001661 }
1662
1663 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001664 if (IsCpRestoreSet && inMicroMipsMode())
1665 JalrInst.setOpcode(Mips::JALRS_MM);
1666 else
1667 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001668 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1669 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1670
1671 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1672 // This relocation is supposed to be an optimization hint for the linker
1673 // and is not necessary for correctness.
1674
1675 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001676 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001677 }
1678
Jack Carter9e65aa32013-03-22 00:05:30 +00001679 if (MCID.mayLoad() || MCID.mayStore()) {
1680 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001681 // reference or immediate we may have to expand instructions.
1682 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001683 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001684 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1685 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001686 MCOperand &Op = Inst.getOperand(i);
1687 if (Op.isImm()) {
1688 int MemOffset = Op.getImm();
1689 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001690 // Offset can't exceed 16bit value.
1691 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001692 return false;
1693 }
1694 } else if (Op.isExpr()) {
1695 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001696 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001697 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001698 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001699 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001700 // Expand symbol.
1701 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001702 return false;
1703 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001704 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001705 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001706 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001707 }
1708 }
1709 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001710 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001711 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001712
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001713 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001714 if (MCID.mayLoad()) {
1715 // Try to create 16-bit GP relative load instruction.
1716 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1717 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1718 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1719 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1720 MCOperand &Op = Inst.getOperand(i);
1721 if (Op.isImm()) {
1722 int MemOffset = Op.getImm();
1723 MCOperand &DstReg = Inst.getOperand(0);
1724 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00001725 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00001726 getContext().getRegisterInfo()->getRegClass(
1727 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001728 (BaseReg.getReg() == Mips::GP ||
1729 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001730
1731 emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
1732 IDLoc, Instructions);
Jozef Koleke10a02e2015-01-28 17:27:26 +00001733 return false;
1734 }
1735 }
1736 }
1737 } // for
1738 } // if load
1739
1740 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1741
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001742 MCOperand Opnd;
1743 int Imm;
1744
1745 switch (Inst.getOpcode()) {
1746 default:
1747 break;
1748 case Mips::ADDIUS5_MM:
1749 Opnd = Inst.getOperand(2);
1750 if (!Opnd.isImm())
1751 return Error(IDLoc, "expected immediate operand kind");
1752 Imm = Opnd.getImm();
1753 if (Imm < -8 || Imm > 7)
1754 return Error(IDLoc, "immediate operand value out of range");
1755 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001756 case Mips::ADDIUSP_MM:
1757 Opnd = Inst.getOperand(0);
1758 if (!Opnd.isImm())
1759 return Error(IDLoc, "expected immediate operand kind");
1760 Imm = Opnd.getImm();
1761 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1762 Imm % 4 != 0)
1763 return Error(IDLoc, "immediate operand value out of range");
1764 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001765 case Mips::SLL16_MM:
1766 case Mips::SRL16_MM:
1767 Opnd = Inst.getOperand(2);
1768 if (!Opnd.isImm())
1769 return Error(IDLoc, "expected immediate operand kind");
1770 Imm = Opnd.getImm();
1771 if (Imm < 1 || Imm > 8)
1772 return Error(IDLoc, "immediate operand value out of range");
1773 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001774 case Mips::LI16_MM:
1775 Opnd = Inst.getOperand(1);
1776 if (!Opnd.isImm())
1777 return Error(IDLoc, "expected immediate operand kind");
1778 Imm = Opnd.getImm();
1779 if (Imm < -1 || Imm > 126)
1780 return Error(IDLoc, "immediate operand value out of range");
1781 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001782 case Mips::ADDIUR2_MM:
1783 Opnd = Inst.getOperand(2);
1784 if (!Opnd.isImm())
1785 return Error(IDLoc, "expected immediate operand kind");
1786 Imm = Opnd.getImm();
1787 if (!(Imm == 1 || Imm == -1 ||
1788 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1789 return Error(IDLoc, "immediate operand value out of range");
1790 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001791 case Mips::ADDIUR1SP_MM:
1792 Opnd = Inst.getOperand(1);
1793 if (!Opnd.isImm())
1794 return Error(IDLoc, "expected immediate operand kind");
1795 Imm = Opnd.getImm();
1796 if (OffsetToAlignment(Imm, 4LL))
1797 return Error(IDLoc, "misaligned immediate operand value");
1798 if (Imm < 0 || Imm > 255)
1799 return Error(IDLoc, "immediate operand value out of range");
1800 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001801 case Mips::ANDI16_MM:
1802 Opnd = Inst.getOperand(2);
1803 if (!Opnd.isImm())
1804 return Error(IDLoc, "expected immediate operand kind");
1805 Imm = Opnd.getImm();
1806 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1807 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1808 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1809 return Error(IDLoc, "immediate operand value out of range");
1810 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001811 case Mips::LBU16_MM:
1812 Opnd = Inst.getOperand(2);
1813 if (!Opnd.isImm())
1814 return Error(IDLoc, "expected immediate operand kind");
1815 Imm = Opnd.getImm();
1816 if (Imm < -1 || Imm > 14)
1817 return Error(IDLoc, "immediate operand value out of range");
1818 break;
Zoran Jovanovic7ba636c2015-09-17 10:14:09 +00001819 case Mips::TEQ_MM:
1820 case Mips::TGE_MM:
1821 case Mips::TGEU_MM:
1822 case Mips::TLT_MM:
1823 case Mips::TLTU_MM:
1824 case Mips::TNE_MM:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001825 case Mips::SB16_MM:
1826 Opnd = Inst.getOperand(2);
1827 if (!Opnd.isImm())
1828 return Error(IDLoc, "expected immediate operand kind");
1829 Imm = Opnd.getImm();
1830 if (Imm < 0 || Imm > 15)
1831 return Error(IDLoc, "immediate operand value out of range");
1832 break;
1833 case Mips::LHU16_MM:
1834 case Mips::SH16_MM:
1835 Opnd = Inst.getOperand(2);
1836 if (!Opnd.isImm())
1837 return Error(IDLoc, "expected immediate operand kind");
1838 Imm = Opnd.getImm();
1839 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1840 return Error(IDLoc, "immediate operand value out of range");
1841 break;
1842 case Mips::LW16_MM:
1843 case Mips::SW16_MM:
1844 Opnd = Inst.getOperand(2);
1845 if (!Opnd.isImm())
1846 return Error(IDLoc, "expected immediate operand kind");
1847 Imm = Opnd.getImm();
1848 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1849 return Error(IDLoc, "immediate operand value out of range");
1850 break;
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +00001851 case Mips::PREFX_MM:
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001852 case Mips::CACHE:
1853 case Mips::PREF:
1854 Opnd = Inst.getOperand(2);
1855 if (!Opnd.isImm())
1856 return Error(IDLoc, "expected immediate operand kind");
1857 Imm = Opnd.getImm();
1858 if (!isUInt<5>(Imm))
1859 return Error(IDLoc, "immediate operand value out of range");
1860 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001861 case Mips::ADDIUPC_MM:
1862 MCOperand Opnd = Inst.getOperand(1);
1863 if (!Opnd.isImm())
1864 return Error(IDLoc, "expected immediate operand kind");
1865 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00001866 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001867 return Error(IDLoc, "immediate operand value out of range");
1868 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001869 }
1870 }
1871
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001872 if (needsExpansion(Inst)) {
1873 if (expandInstruction(Inst, IDLoc, Instructions))
1874 return true;
1875 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001876 Instructions.push_back(Inst);
1877
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001878 // If this instruction has a delay slot and .set reorder is active,
1879 // emit a NOP after it.
1880 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1881 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1882
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001883 if ((Inst.getOpcode() == Mips::JalOneReg ||
1884 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
1885 isPicAndNotNxxAbi()) {
1886 if (IsCpRestoreSet) {
1887 // We need a NOP between the JALR and the LW:
1888 // If .set reorder has been used, we've already emitted a NOP.
1889 // If .set noreorder has been used, we need to emit a NOP at this point.
1890 if (!AssemblerOptions.back()->isReorder())
1891 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1892
1893 // Load the $gp from the stack.
1894 SmallVector<MCInst, 3> LoadInsts;
1895 createCpRestoreMemOp(true /*IsLoad*/, CpRestoreOffset /*StackOffset*/,
1896 IDLoc, LoadInsts);
1897
1898 for (const MCInst &Inst : LoadInsts)
1899 Instructions.push_back(Inst);
1900
1901 } else
1902 Warning(IDLoc, "no .cprestore used in PIC mode");
1903 }
1904
Jack Carter9e65aa32013-03-22 00:05:30 +00001905 return false;
1906}
1907
Jack Carter30a59822012-10-04 04:03:53 +00001908bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1909
Jack Carterd0bd6422013-04-18 00:41:53 +00001910 switch (Inst.getOpcode()) {
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001911 case Mips::LoadImm32:
1912 case Mips::LoadImm64:
1913 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001914 case Mips::LoadAddrImm64:
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001915 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001916 case Mips::LoadAddrReg64:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001917 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001918 case Mips::B_MMR6_Pseudo:
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001919 case Mips::LWM_MM:
1920 case Mips::SWM_MM:
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001921 case Mips::JalOneReg:
1922 case Mips::JalTwoReg:
Toma Tabacue1e460d2015-06-11 10:36:10 +00001923 case Mips::BneImm:
1924 case Mips::BeqImm:
Toma Tabacu1a108322015-06-17 13:20:24 +00001925 case Mips::BLT:
1926 case Mips::BLE:
1927 case Mips::BGE:
1928 case Mips::BGT:
1929 case Mips::BLTU:
1930 case Mips::BLEU:
1931 case Mips::BGEU:
1932 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00001933 case Mips::BLTL:
1934 case Mips::BLEL:
1935 case Mips::BGEL:
1936 case Mips::BGTL:
1937 case Mips::BLTUL:
1938 case Mips::BLEUL:
1939 case Mips::BGEUL:
1940 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00001941 case Mips::BLTImmMacro:
1942 case Mips::BLEImmMacro:
1943 case Mips::BGEImmMacro:
1944 case Mips::BGTImmMacro:
1945 case Mips::BLTUImmMacro:
1946 case Mips::BLEUImmMacro:
1947 case Mips::BGEUImmMacro:
1948 case Mips::BGTUImmMacro:
1949 case Mips::BLTLImmMacro:
1950 case Mips::BLELImmMacro:
1951 case Mips::BGELImmMacro:
1952 case Mips::BGTLImmMacro:
1953 case Mips::BLTULImmMacro:
1954 case Mips::BLEULImmMacro:
1955 case Mips::BGEULImmMacro:
1956 case Mips::BGTULImmMacro:
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00001957 case Mips::SDivMacro:
1958 case Mips::UDivMacro:
1959 case Mips::DSDivMacro:
1960 case Mips::DUDivMacro:
Toma Tabacud88d79c2015-06-23 14:39:42 +00001961 case Mips::Ulhu:
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00001962 case Mips::Ulw:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00001963 case Mips::NORImm:
Jack Carterd0bd6422013-04-18 00:41:53 +00001964 return true;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00001965 case Mips::ADDi:
1966 case Mips::ADDiu:
1967 case Mips::SLTi:
1968 case Mips::SLTiu:
1969 if ((Inst.getNumOperands() == 3) &&
1970 Inst.getOperand(0).isReg() &&
1971 Inst.getOperand(1).isReg() &&
1972 Inst.getOperand(2).isImm()) {
1973 int64_t ImmValue = Inst.getOperand(2).getImm();
1974 return !isInt<16>(ImmValue);
1975 }
1976 return false;
1977 case Mips::ANDi:
1978 case Mips::ORi:
1979 case Mips::XORi:
1980 if ((Inst.getNumOperands() == 3) &&
1981 Inst.getOperand(0).isReg() &&
1982 Inst.getOperand(1).isReg() &&
1983 Inst.getOperand(2).isImm()) {
1984 int64_t ImmValue = Inst.getOperand(2).getImm();
1985 return !isUInt<16>(ImmValue);
1986 }
1987 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001988 default:
1989 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001990 }
1991}
Jack Carter92995f12012-10-06 00:53:28 +00001992
Matheus Almeida3813d572014-06-19 14:39:14 +00001993bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001994 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001995 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001996 default: llvm_unreachable("unimplemented expansion");
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001997 case Mips::LoadImm32:
Toma Tabacu00e98672015-05-01 12:19:27 +00001998 return expandLoadImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001999 case Mips::LoadImm64:
Toma Tabacu00e98672015-05-01 12:19:27 +00002000 return expandLoadImm(Inst, false, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002001 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002002 case Mips::LoadAddrImm64:
2003 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2004 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
2005 "expected immediate operand kind");
2006
2007 return expandLoadAddress(
2008 Inst.getOperand(0).getReg(), Mips::NoRegister, Inst.getOperand(1),
2009 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002010 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002011 case Mips::LoadAddrReg64:
2012 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2013 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2014 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
2015 "expected immediate operand kind");
2016
2017 return expandLoadAddress(
2018 Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(), Inst.getOperand(2),
2019 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002020 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002021 case Mips::B_MMR6_Pseudo:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002022 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002023 case Mips::SWM_MM:
2024 case Mips::LWM_MM:
2025 return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002026 case Mips::JalOneReg:
2027 case Mips::JalTwoReg:
2028 return expandJalWithRegs(Inst, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002029 case Mips::BneImm:
2030 case Mips::BeqImm:
2031 return expandBranchImm(Inst, IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002032 case Mips::BLT:
2033 case Mips::BLE:
2034 case Mips::BGE:
2035 case Mips::BGT:
2036 case Mips::BLTU:
2037 case Mips::BLEU:
2038 case Mips::BGEU:
2039 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002040 case Mips::BLTL:
2041 case Mips::BLEL:
2042 case Mips::BGEL:
2043 case Mips::BGTL:
2044 case Mips::BLTUL:
2045 case Mips::BLEUL:
2046 case Mips::BGEUL:
2047 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002048 case Mips::BLTImmMacro:
2049 case Mips::BLEImmMacro:
2050 case Mips::BGEImmMacro:
2051 case Mips::BGTImmMacro:
2052 case Mips::BLTUImmMacro:
2053 case Mips::BLEUImmMacro:
2054 case Mips::BGEUImmMacro:
2055 case Mips::BGTUImmMacro:
2056 case Mips::BLTLImmMacro:
2057 case Mips::BLELImmMacro:
2058 case Mips::BGELImmMacro:
2059 case Mips::BGTLImmMacro:
2060 case Mips::BLTULImmMacro:
2061 case Mips::BLEULImmMacro:
2062 case Mips::BGEULImmMacro:
2063 case Mips::BGTULImmMacro:
Toma Tabacu1a108322015-06-17 13:20:24 +00002064 return expandCondBranches(Inst, IDLoc, Instructions);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002065 case Mips::SDivMacro:
2066 return expandDiv(Inst, IDLoc, Instructions, false, true);
2067 case Mips::DSDivMacro:
2068 return expandDiv(Inst, IDLoc, Instructions, true, true);
2069 case Mips::UDivMacro:
2070 return expandDiv(Inst, IDLoc, Instructions, false, false);
2071 case Mips::DUDivMacro:
2072 return expandDiv(Inst, IDLoc, Instructions, true, false);
Toma Tabacud88d79c2015-06-23 14:39:42 +00002073 case Mips::Ulhu:
2074 return expandUlhu(Inst, IDLoc, Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00002075 case Mips::Ulw:
2076 return expandUlw(Inst, IDLoc, Instructions);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002077 case Mips::ADDi:
2078 case Mips::ADDiu:
2079 case Mips::ANDi:
2080 case Mips::NORImm:
2081 case Mips::ORi:
2082 case Mips::SLTi:
2083 case Mips::SLTiu:
2084 case Mips::XORi:
2085 return expandAliasImmediate(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00002086 }
Jack Carter30a59822012-10-04 04:03:53 +00002087}
Jack Carter92995f12012-10-06 00:53:28 +00002088
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002089bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
2090 SmallVectorImpl<MCInst> &Instructions) {
2091 // Create a JALR instruction which is going to replace the pseudo-JAL.
2092 MCInst JalrInst;
2093 JalrInst.setLoc(IDLoc);
2094 const MCOperand FirstRegOp = Inst.getOperand(0);
2095 const unsigned Opcode = Inst.getOpcode();
2096
2097 if (Opcode == Mips::JalOneReg) {
2098 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002099 if (IsCpRestoreSet && inMicroMipsMode()) {
2100 JalrInst.setOpcode(Mips::JALRS16_MM);
2101 JalrInst.addOperand(FirstRegOp);
2102 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002103 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002104 JalrInst.addOperand(FirstRegOp);
2105 } else {
2106 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002107 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002108 JalrInst.addOperand(FirstRegOp);
2109 }
2110 } else if (Opcode == Mips::JalTwoReg) {
2111 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002112 if (IsCpRestoreSet && inMicroMipsMode())
2113 JalrInst.setOpcode(Mips::JALRS_MM);
2114 else
2115 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002116 JalrInst.addOperand(FirstRegOp);
2117 const MCOperand SecondRegOp = Inst.getOperand(1);
2118 JalrInst.addOperand(SecondRegOp);
2119 }
2120 Instructions.push_back(JalrInst);
2121
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002122 // If .set reorder is active and branch instruction has a delay slot,
2123 // emit a NOP after it.
2124 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
2125 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002126 createNop(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, Instructions);
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002127 }
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002128
2129 return false;
2130}
2131
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002132/// Can the value be represented by a unsigned N-bit value and a shift left?
2133template<unsigned N>
2134bool isShiftedUIntAtAnyPosition(uint64_t x) {
2135 unsigned BitNum = findFirstSet(x);
2136
2137 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2138}
2139
2140/// Load (or add) an immediate into a register.
2141///
2142/// @param ImmValue The immediate to load.
2143/// @param DstReg The register that will hold the immediate.
2144/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2145/// for a simple initialization.
2146/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2147/// @param IsAddress True if the immediate represents an address. False if it
2148/// is an integer.
2149/// @param IDLoc Location of the immediate in the source file.
2150/// @param Instructions The instructions emitted by this expansion.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002151bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002152 unsigned SrcReg, bool Is32BitImm,
2153 bool IsAddress, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00002154 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00002155 if (!Is32BitImm && !isGP64bit()) {
2156 Error(IDLoc, "instruction requires a 64-bit architecture");
2157 return true;
2158 }
2159
Daniel Sanders03f9c012015-07-14 12:24:22 +00002160 if (Is32BitImm) {
2161 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2162 // Sign extend up to 64-bit so that the predicates match the hardware
2163 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2164 // true.
2165 ImmValue = SignExtend64<32>(ImmValue);
2166 } else {
2167 Error(IDLoc, "instruction requires a 32-bit immediate");
2168 return true;
2169 }
2170 }
2171
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002172 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2173 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2174
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002175 bool UseSrcReg = false;
2176 if (SrcReg != Mips::NoRegister)
2177 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002178
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002179 unsigned TmpReg = DstReg;
2180 if (UseSrcReg && (DstReg == SrcReg)) {
2181 // At this point we need AT to perform the expansions and we exit if it is
2182 // not available.
2183 unsigned ATReg = getATReg(IDLoc);
2184 if (!ATReg)
2185 return true;
2186 TmpReg = ATReg;
2187 }
2188
Daniel Sanders03f9c012015-07-14 12:24:22 +00002189 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002190 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002191 SrcReg = ZeroReg;
2192
2193 // This doesn't quite follow the usual ABI expectations for N32 but matches
2194 // traditional assembler behaviour. N32 would normally use addiu for both
2195 // integers and addresses.
2196 if (IsAddress && !Is32BitImm) {
2197 emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2198 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002199 }
2200
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002201 emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2202 return false;
2203 }
2204
2205 if (isUInt<16>(ImmValue)) {
2206 unsigned TmpReg = DstReg;
2207 if (SrcReg == DstReg) {
2208 TmpReg = getATReg(IDLoc);
2209 if (!TmpReg)
2210 return true;
2211 }
2212
2213 emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002214 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002215 emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2216 return false;
2217 }
2218
2219 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002220 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002221
Toma Tabacu79588102015-04-29 10:19:56 +00002222 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2223 uint16_t Bits15To0 = ImmValue & 0xffff;
2224
Toma Tabacua3d056f2015-05-15 09:42:11 +00002225 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002226 // Traditional behaviour seems to special case this particular value. It's
2227 // not clear why other masks are handled differently.
2228 if (ImmValue == 0xffffffff) {
Daniel Sandersf1ae3672015-08-18 09:55:57 +00002229 emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002230 emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, Instructions);
2231 if (UseSrcReg)
2232 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2233 return false;
2234 }
2235
2236 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002237 // upper 32 bits.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002238 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002239 emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002240 if (Bits15To0)
2241 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
2242 if (UseSrcReg)
2243 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2244 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002245 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002246
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002247 emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions);
2248 if (Bits15To0)
2249 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002250 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002251 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2252 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002253 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002254
2255 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2256 if (Is32BitImm) {
2257 Error(IDLoc, "instruction requires a 32-bit immediate");
2258 return true;
2259 }
2260
2261 // Traditionally, these immediates are shifted as little as possible and as
2262 // such we align the most significant bit to bit 15 of our temporary.
2263 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2264 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2265 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2266 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
2267 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, Instructions);
2268 emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, Instructions);
2269
2270 if (UseSrcReg)
2271 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2272
2273 return false;
2274 }
2275
2276 warnIfNoMacro(IDLoc);
2277
2278 // The remaining case is packed with a sequence of dsll and ori with zeros
2279 // being omitted and any neighbouring dsll's being coalesced.
2280 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2281
2282 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2283 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
2284 IDLoc, Instructions))
2285 return false;
2286
2287 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2288 // skip it and defer the shift to the next chunk.
2289 unsigned ShiftCarriedForwards = 16;
2290 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2291 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2292
2293 if (ImmChunk != 0) {
2294 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2295 Instructions);
2296 emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, Instructions);
2297 ShiftCarriedForwards = 0;
2298 }
2299
2300 ShiftCarriedForwards += 16;
2301 }
2302 ShiftCarriedForwards -= 16;
2303
2304 // Finish any remaining shifts left by trailing zeros.
2305 if (ShiftCarriedForwards)
2306 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2307 Instructions);
2308
2309 if (UseSrcReg)
2310 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2311
Matheus Almeida3813d572014-06-19 14:39:14 +00002312 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002313}
Jack Carter92995f12012-10-06 00:53:28 +00002314
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002315bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
2316 SmallVectorImpl<MCInst> &Instructions) {
2317 const MCOperand &ImmOp = Inst.getOperand(1);
2318 assert(ImmOp.isImm() && "expected immediate operand kind");
2319 const MCOperand &DstRegOp = Inst.getOperand(0);
2320 assert(DstRegOp.isReg() && "expected register operand kind");
2321
2322 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002323 Is32BitImm, false, IDLoc, Instructions))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002324 return true;
2325
2326 return false;
2327}
2328
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002329bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2330 const MCOperand &Offset,
2331 bool Is32BitAddress, SMLoc IDLoc,
2332 SmallVectorImpl<MCInst> &Instructions) {
2333 // la can't produce a usable address when addresses are 64-bit.
2334 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2335 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2336 // We currently can't do this because we depend on the equality
2337 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2338 Error(IDLoc, "la used to load 64-bit address");
2339 // Continue as if we had 'dla' instead.
2340 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002341 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002342
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002343 // dla requires 64-bit addresses.
2344 if (!Is32BitAddress && !ABI.ArePtrs64bit()) {
2345 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002346 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002347 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002348
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002349 if (!Offset.isImm())
2350 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
2351 Is32BitAddress, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002352
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002353 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
2354 IDLoc, Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +00002355}
2356
Toma Tabacuf712ede2015-06-17 14:31:51 +00002357bool MipsAsmParser::loadAndAddSymbolAddress(
2358 const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
2359 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002360 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002361
Daniel Sandersd5a89412015-10-05 13:19:29 +00002362 const MCExpr *Symbol = cast<MCExpr>(SymExpr);
2363 const MipsMCExpr *HiExpr = MipsMCExpr::create(
2364 MCSymbolRefExpr::VK_Mips_ABS_HI, Symbol, getContext());
2365 const MipsMCExpr *LoExpr = MipsMCExpr::create(
2366 MCSymbolRefExpr::VK_Mips_ABS_LO, Symbol, getContext());
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002367
Toma Tabacufb9d1252015-06-22 12:08:39 +00002368 bool UseSrcReg = SrcReg != Mips::NoRegister;
2369
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002370 // This is the 64-bit symbol address expansion.
2371 if (ABI.ArePtrs64bit() && isGP64bit()) {
2372 // We always need AT for the 64-bit expansion.
2373 // If it is not available we exit.
2374 unsigned ATReg = getATReg(IDLoc);
2375 if (!ATReg)
2376 return true;
2377
Daniel Sandersd5a89412015-10-05 13:19:29 +00002378 const MipsMCExpr *HighestExpr = MipsMCExpr::create(
2379 MCSymbolRefExpr::VK_Mips_HIGHEST, Symbol, getContext());
2380 const MipsMCExpr *HigherExpr = MipsMCExpr::create(
2381 MCSymbolRefExpr::VK_Mips_HIGHER, Symbol, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002382
2383 if (UseSrcReg && (DstReg == SrcReg)) {
2384 // If $rs is the same as $rd:
2385 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2386 // daddiu $at, $at, %higher(sym)
2387 // dsll $at, $at, 16
2388 // daddiu $at, $at, %hi(sym)
2389 // dsll $at, $at, 16
2390 // daddiu $at, $at, %lo(sym)
2391 // daddu $rd, $at, $rd
2392 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2393 Instructions);
2394 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr),
2395 IDLoc, Instructions);
2396 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2397 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2398 Instructions);
2399 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2400 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2401 Instructions);
2402 emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions);
2403
2404 return false;
2405 }
2406
2407 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2408 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2409 // lui $at, %hi(sym)
2410 // daddiu $rd, $rd, %higher(sym)
2411 // daddiu $at, $at, %lo(sym)
2412 // dsll32 $rd, $rd, 0
2413 // daddu $rd, $rd, $at
2414 // (daddu $rd, $rd, $rs)
2415 emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2416 Instructions);
2417 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2418 Instructions);
2419 emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr),
2420 IDLoc, Instructions);
2421 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2422 Instructions);
2423 emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions);
2424 emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions);
2425 if (UseSrcReg)
2426 emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions);
2427
2428 return false;
2429 }
2430
2431 // And now, the 32-bit symbol address expansion:
2432 // If $rs is the same as $rd:
2433 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2434 // ori $at, $at, %lo(sym)
2435 // addu $rd, $at, $rd
2436 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2437 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2438 // ori $rd, $rd, %lo(sym)
2439 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002440 unsigned TmpReg = DstReg;
2441 if (UseSrcReg && (DstReg == SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002442 // If $rs is the same as $rd, we need to use AT.
2443 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002444 unsigned ATReg = getATReg(IDLoc);
2445 if (!ATReg)
2446 return true;
2447 TmpReg = ATReg;
2448 }
2449
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002450 emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions);
2451 emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc,
2452 Instructions);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002453
Toma Tabacufb9d1252015-06-22 12:08:39 +00002454 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002455 emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2456 else
2457 assert(DstReg == TmpReg);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002458
Toma Tabacu674825c2015-06-16 12:16:24 +00002459 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002460}
2461
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002462bool MipsAsmParser::expandUncondBranchMMPseudo(
2463 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002464 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2465 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002466
2467 MCOperand Offset = Inst.getOperand(0);
2468 if (Offset.isExpr()) {
2469 Inst.clear();
2470 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002471 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2472 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2473 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002474 } else {
2475 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002476 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002477 // If offset fits into 11 bits then this instruction becomes microMIPS
2478 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002479 if (inMicroMipsMode())
2480 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002481 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002482 if (!isInt<17>(Offset.getImm()))
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002483 Error(IDLoc, "branch target out of range");
2484 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2485 Error(IDLoc, "branch to misaligned address");
2486 Inst.clear();
2487 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002488 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2489 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2490 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002491 }
2492 }
2493 Instructions.push_back(Inst);
2494
Zoran Jovanovicada70912015-09-07 11:56:37 +00002495 // If .set reorder is active and branch instruction has a delay slot,
2496 // emit a NOP after it.
2497 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2498 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Toma Tabacu234482a2015-03-16 12:03:39 +00002499 createNop(true, IDLoc, Instructions);
2500
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002501 return false;
2502}
2503
Toma Tabacue1e460d2015-06-11 10:36:10 +00002504bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2505 SmallVectorImpl<MCInst> &Instructions) {
2506 const MCOperand &DstRegOp = Inst.getOperand(0);
2507 assert(DstRegOp.isReg() && "expected register operand kind");
2508
2509 const MCOperand &ImmOp = Inst.getOperand(1);
2510 assert(ImmOp.isImm() && "expected immediate operand kind");
2511
2512 const MCOperand &MemOffsetOp = Inst.getOperand(2);
2513 assert(MemOffsetOp.isImm() && "expected immediate operand kind");
2514
2515 unsigned OpCode = 0;
2516 switch(Inst.getOpcode()) {
2517 case Mips::BneImm:
2518 OpCode = Mips::BNE;
2519 break;
2520 case Mips::BeqImm:
2521 OpCode = Mips::BEQ;
2522 break;
2523 default:
2524 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2525 break;
2526 }
2527
2528 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002529 if (ImmValue == 0)
2530 emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2531 Instructions);
2532 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002533 warnIfNoMacro(IDLoc);
2534
2535 unsigned ATReg = getATReg(IDLoc);
2536 if (!ATReg)
2537 return true;
2538
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002539 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
2540 IDLoc, Instructions))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002541 return true;
2542
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002543 emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002544 }
2545 return false;
2546}
2547
Jack Carter9e65aa32013-03-22 00:05:30 +00002548void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002549 SmallVectorImpl<MCInst> &Instructions,
2550 bool isLoad, bool isImmOpnd) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002551 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002552 const MCExpr *ExprOffset;
2553 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002554 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002555 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2556 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002557 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002558 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2559 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002560 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002561 if (isImmOpnd) {
2562 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2563 ImmOffset = Inst.getOperand(2).getImm();
2564 LoOffset = ImmOffset & 0x0000ffff;
2565 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002566 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002567 if (LoOffset & 0x8000)
2568 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002569 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002570 ExprOffset = Inst.getOperand(2).getExpr();
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002571 // These are some of the types of expansions we perform here:
2572 // 1) lw $8, sym => lui $8, %hi(sym)
2573 // lw $8, %lo(sym)($8)
2574 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2575 // add $8, $8, $9
2576 // lw $8, %lo(offset)($9)
2577 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2578 // add $at, $at, $8
2579 // lw $8, %lo(offset)($at)
2580 // 4) sw $8, sym => lui $at, %hi(sym)
2581 // sw $8, %lo(sym)($at)
2582 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2583 // add $at, $at, $8
2584 // sw $8, %lo(offset)($at)
2585 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2586 // ldc1 $f0, %lo(sym)($at)
2587 //
2588 // For load instructions we can use the destination register as a temporary
2589 // if base and dst are different (examples 1 and 2) and if the base register
2590 // is general purpose otherwise we must use $at (example 6) and error if it's
2591 // not available. For stores we must use $at (examples 4 and 5) because we
2592 // must not clobber the source register setting up the offset.
2593 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2594 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2595 unsigned RegClassIDOp0 =
2596 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2597 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2598 (RegClassIDOp0 == Mips::GPR64RegClassID);
2599 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002600 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002601 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002602 // At this point we need AT to perform the expansions and we exit if it is
2603 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002604 TmpRegNum = getATReg(IDLoc);
2605 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002606 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002607 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002608
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002609 emitRX(Mips::LUi, TmpRegNum,
2610 isImmOpnd ? MCOperand::createImm(HiOffset)
2611 : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "hi")),
2612 IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00002613 // Add temp register to base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002614 if (BaseRegNum != Mips::ZERO)
2615 emitRRR(Mips::ADDu, TmpRegNum, TmpRegNum, BaseRegNum, IDLoc, Instructions);
Alp Tokercb402912014-01-24 17:20:08 +00002616 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002617 // of offset and new base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002618 emitRRX(Inst.getOpcode(), RegOpNum, TmpRegNum,
2619 isImmOpnd
2620 ? MCOperand::createImm(LoOffset)
2621 : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "lo")),
2622 IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00002623}
2624
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002625bool
2626MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2627 SmallVectorImpl<MCInst> &Instructions) {
2628 unsigned OpNum = Inst.getNumOperands();
2629 unsigned Opcode = Inst.getOpcode();
2630 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2631
2632 assert (Inst.getOperand(OpNum - 1).isImm() &&
2633 Inst.getOperand(OpNum - 2).isReg() &&
2634 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2635
2636 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2637 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2638 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2639 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2640 // It can be implemented as SWM16 or LWM16 instruction.
2641 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2642
2643 Inst.setOpcode(NewOpcode);
2644 Instructions.push_back(Inst);
2645 return false;
2646}
2647
Toma Tabacu1a108322015-06-17 13:20:24 +00002648bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2649 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002650 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00002651 unsigned PseudoOpcode = Inst.getOpcode();
2652 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002653 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00002654 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2655
2656 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002657 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002658
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002659 unsigned TrgReg;
2660 if (TrgOp.isReg())
2661 TrgReg = TrgOp.getReg();
2662 else if (TrgOp.isImm()) {
2663 warnIfNoMacro(IDLoc);
2664 EmittedNoMacroWarning = true;
2665
2666 TrgReg = getATReg(IDLoc);
2667 if (!TrgReg)
2668 return true;
2669
2670 switch(PseudoOpcode) {
2671 default:
2672 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2673 case Mips::BLTImmMacro:
2674 PseudoOpcode = Mips::BLT;
2675 break;
2676 case Mips::BLEImmMacro:
2677 PseudoOpcode = Mips::BLE;
2678 break;
2679 case Mips::BGEImmMacro:
2680 PseudoOpcode = Mips::BGE;
2681 break;
2682 case Mips::BGTImmMacro:
2683 PseudoOpcode = Mips::BGT;
2684 break;
2685 case Mips::BLTUImmMacro:
2686 PseudoOpcode = Mips::BLTU;
2687 break;
2688 case Mips::BLEUImmMacro:
2689 PseudoOpcode = Mips::BLEU;
2690 break;
2691 case Mips::BGEUImmMacro:
2692 PseudoOpcode = Mips::BGEU;
2693 break;
2694 case Mips::BGTUImmMacro:
2695 PseudoOpcode = Mips::BGTU;
2696 break;
2697 case Mips::BLTLImmMacro:
2698 PseudoOpcode = Mips::BLTL;
2699 break;
2700 case Mips::BLELImmMacro:
2701 PseudoOpcode = Mips::BLEL;
2702 break;
2703 case Mips::BGELImmMacro:
2704 PseudoOpcode = Mips::BGEL;
2705 break;
2706 case Mips::BGTLImmMacro:
2707 PseudoOpcode = Mips::BGTL;
2708 break;
2709 case Mips::BLTULImmMacro:
2710 PseudoOpcode = Mips::BLTUL;
2711 break;
2712 case Mips::BLEULImmMacro:
2713 PseudoOpcode = Mips::BLEUL;
2714 break;
2715 case Mips::BGEULImmMacro:
2716 PseudoOpcode = Mips::BGEUL;
2717 break;
2718 case Mips::BGTULImmMacro:
2719 PseudoOpcode = Mips::BGTUL;
2720 break;
2721 }
2722
2723 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
2724 false, IDLoc, Instructions))
2725 return true;
2726 }
2727
Toma Tabacu1a108322015-06-17 13:20:24 +00002728 switch (PseudoOpcode) {
2729 case Mips::BLT:
2730 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002731 case Mips::BLTL:
2732 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002733 AcceptsEquality = false;
2734 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002735 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2736 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002737 ZeroSrcOpcode = Mips::BGTZ;
2738 ZeroTrgOpcode = Mips::BLTZ;
2739 break;
2740 case Mips::BLE:
2741 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002742 case Mips::BLEL:
2743 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002744 AcceptsEquality = true;
2745 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002746 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2747 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002748 ZeroSrcOpcode = Mips::BGEZ;
2749 ZeroTrgOpcode = Mips::BLEZ;
2750 break;
2751 case Mips::BGE:
2752 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002753 case Mips::BGEL:
2754 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002755 AcceptsEquality = true;
2756 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002757 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2758 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002759 ZeroSrcOpcode = Mips::BLEZ;
2760 ZeroTrgOpcode = Mips::BGEZ;
2761 break;
2762 case Mips::BGT:
2763 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002764 case Mips::BGTL:
2765 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002766 AcceptsEquality = false;
2767 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002768 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2769 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002770 ZeroSrcOpcode = Mips::BLTZ;
2771 ZeroTrgOpcode = Mips::BGTZ;
2772 break;
2773 default:
2774 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2775 }
2776
Toma Tabacu1a108322015-06-17 13:20:24 +00002777 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2778 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2779 if (IsSrcRegZero && IsTrgRegZero) {
2780 // FIXME: All of these Opcode-specific if's are needed for compatibility
2781 // with GAS' behaviour. However, they may not generate the most efficient
2782 // code in some circumstances.
2783 if (PseudoOpcode == Mips::BLT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002784 emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2785 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002786 return false;
2787 }
2788 if (PseudoOpcode == Mips::BLE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002789 emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2790 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002791 Warning(IDLoc, "branch is always taken");
2792 return false;
2793 }
2794 if (PseudoOpcode == Mips::BGE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002795 emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2796 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002797 Warning(IDLoc, "branch is always taken");
2798 return false;
2799 }
2800 if (PseudoOpcode == Mips::BGT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002801 emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2802 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002803 return false;
2804 }
2805 if (PseudoOpcode == Mips::BGTU) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002806 emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
2807 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002808 return false;
2809 }
2810 if (AcceptsEquality) {
2811 // If both registers are $0 and the pseudo-branch accepts equality, it
2812 // will always be taken, so we emit an unconditional branch.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002813 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2814 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002815 Warning(IDLoc, "branch is always taken");
2816 return false;
2817 }
2818 // If both registers are $0 and the pseudo-branch does not accept
2819 // equality, it will never be taken, so we don't have to emit anything.
2820 return false;
2821 }
2822 if (IsSrcRegZero || IsTrgRegZero) {
2823 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2824 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2825 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2826 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2827 // the pseudo-branch will never be taken, so we don't emit anything.
2828 // This only applies to unsigned pseudo-branches.
2829 return false;
2830 }
2831 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2832 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2833 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2834 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2835 // the pseudo-branch will always be taken, so we emit an unconditional
2836 // branch.
2837 // This only applies to unsigned pseudo-branches.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002838 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2839 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002840 Warning(IDLoc, "branch is always taken");
2841 return false;
2842 }
2843 if (IsUnsigned) {
2844 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2845 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2846 // the pseudo-branch will be taken only when the non-zero register is
2847 // different from 0, so we emit a BNEZ.
2848 //
2849 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2850 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2851 // the pseudo-branch will be taken only when the non-zero register is
2852 // equal to 0, so we emit a BEQZ.
2853 //
2854 // Because only BLEU and BGEU branch on equality, we can use the
2855 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002856 emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
2857 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
2858 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002859 return false;
2860 }
2861 // If we have a signed pseudo-branch and one of the registers is $0,
2862 // we can use an appropriate compare-to-zero branch. We select which one
2863 // to use in the switch statement above.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002864 emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
2865 IsSrcRegZero ? TrgReg : SrcReg, MCOperand::createExpr(OffsetExpr),
2866 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002867 return false;
2868 }
2869
2870 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2871 // expansions. If it is not available, we return.
2872 unsigned ATRegNum = getATReg(IDLoc);
2873 if (!ATRegNum)
2874 return true;
2875
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002876 if (!EmittedNoMacroWarning)
2877 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00002878
2879 // SLT fits well with 2 of our 4 pseudo-branches:
2880 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2881 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2882 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2883 // This is accomplished by using a BNEZ with the result of the SLT.
2884 //
2885 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2886 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2887 // Because only BGE and BLE branch on equality, we can use the
2888 // AcceptsEquality variable to decide when to emit the BEQZ.
2889 // Note that the order of the SLT arguments doesn't change between
2890 // opposites.
2891 //
2892 // The same applies to the unsigned variants, except that SLTu is used
2893 // instead of SLT.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002894 emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
2895 ReverseOrderSLT ? TrgReg : SrcReg, ReverseOrderSLT ? SrcReg : TrgReg,
2896 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002897
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002898 emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
2899 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
2900 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2901 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002902 return false;
2903}
2904
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002905bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
2906 SmallVectorImpl<MCInst> &Instructions,
2907 const bool IsMips64, const bool Signed) {
2908 if (hasMips32r6()) {
2909 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2910 return false;
2911 }
2912
2913 warnIfNoMacro(IDLoc);
2914
2915 const MCOperand &RsRegOp = Inst.getOperand(0);
2916 assert(RsRegOp.isReg() && "expected register operand kind");
2917 unsigned RsReg = RsRegOp.getReg();
2918
2919 const MCOperand &RtRegOp = Inst.getOperand(1);
2920 assert(RtRegOp.isReg() && "expected register operand kind");
2921 unsigned RtReg = RtRegOp.getReg();
2922 unsigned DivOp;
2923 unsigned ZeroReg;
2924
2925 if (IsMips64) {
2926 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2927 ZeroReg = Mips::ZERO_64;
2928 } else {
2929 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2930 ZeroReg = Mips::ZERO;
2931 }
2932
2933 bool UseTraps = useTraps();
2934
2935 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2936 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2937 Warning(IDLoc, "dividing zero by zero");
2938 if (IsMips64) {
2939 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2940 if (UseTraps) {
2941 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2942 return false;
2943 }
2944
2945 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2946 return false;
2947 }
2948 } else {
2949 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2950 return false;
2951 }
2952 }
2953
2954 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
2955 Warning(IDLoc, "division by zero");
2956 if (Signed) {
2957 if (UseTraps) {
2958 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2959 return false;
2960 }
2961
2962 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2963 return false;
2964 }
2965 }
2966
2967 // FIXME: The values for these two BranchTarget variables may be different in
2968 // micromips. These magic numbers need to be removed.
2969 unsigned BranchTargetNoTraps;
2970 unsigned BranchTarget;
2971
2972 if (UseTraps) {
2973 BranchTarget = IsMips64 ? 12 : 8;
2974 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2975 } else {
2976 BranchTarget = IsMips64 ? 20 : 16;
2977 BranchTargetNoTraps = 8;
2978 // Branch to the li instruction.
2979 emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc,
2980 Instructions);
2981 }
2982
2983 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2984
2985 if (!UseTraps)
2986 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2987
2988 if (!Signed) {
2989 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
2990 return false;
2991 }
2992
2993 unsigned ATReg = getATReg(IDLoc);
2994 if (!ATReg)
2995 return true;
2996
2997 emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, Instructions);
2998 if (IsMips64) {
2999 // Branch to the mflo instruction.
3000 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
3001 emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, Instructions);
3002 emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, Instructions);
3003 } else {
3004 // Branch to the mflo instruction.
3005 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
3006 emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, Instructions);
3007 }
3008
3009 if (UseTraps)
3010 emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, Instructions);
3011 else {
3012 // Branch to the mflo instruction.
3013 emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, Instructions);
3014 emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, Instructions);
3015 emitII(Mips::BREAK, 0x6, 0, IDLoc, Instructions);
3016 }
3017 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
3018 return false;
3019}
3020
Toma Tabacud88d79c2015-06-23 14:39:42 +00003021bool MipsAsmParser::expandUlhu(MCInst &Inst, SMLoc IDLoc,
3022 SmallVectorImpl<MCInst> &Instructions) {
3023 if (hasMips32r6() || hasMips64r6()) {
3024 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3025 return false;
3026 }
3027
3028 warnIfNoMacro(IDLoc);
3029
3030 const MCOperand &DstRegOp = Inst.getOperand(0);
3031 assert(DstRegOp.isReg() && "expected register operand kind");
3032
3033 const MCOperand &SrcRegOp = Inst.getOperand(1);
3034 assert(SrcRegOp.isReg() && "expected register operand kind");
3035
3036 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3037 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3038
3039 unsigned DstReg = DstRegOp.getReg();
3040 unsigned SrcReg = SrcRegOp.getReg();
3041 int64_t OffsetValue = OffsetImmOp.getImm();
3042
3043 // NOTE: We always need AT for ULHU, as it is always used as the source
3044 // register for one of the LBu's.
3045 unsigned ATReg = getATReg(IDLoc);
3046 if (!ATReg)
3047 return true;
3048
3049 // When the value of offset+1 does not fit in 16 bits, we have to load the
3050 // offset in AT, (D)ADDu the original source register (if there was one), and
3051 // then use AT as the source register for the 2 generated LBu's.
3052 bool LoadedOffsetInAT = false;
3053 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3054 LoadedOffsetInAT = true;
3055
3056 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003057 true, IDLoc, Instructions))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003058 return true;
3059
3060 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3061 // because it will make our output more similar to GAS'. For example,
3062 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3063 // instead of just an "ori $1, $9, 32768".
3064 // NOTE: If there is no source register specified in the ULHU, the parser
3065 // will interpret it as $0.
3066 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3067 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3068 }
3069
3070 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3071 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3072 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3073
3074 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3075 if (isLittle()) {
3076 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3077 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3078 } else {
3079 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3080 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3081 }
3082
3083 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3084
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003085 emitRRI(Mips::LBu, FirstLbuDstReg, LbuSrcReg, FirstLbuOffset, IDLoc,
3086 Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003087
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003088 emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
3089 Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003090
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003091 emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003092
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003093 emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003094
3095 return false;
3096}
3097
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003098bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
3099 SmallVectorImpl<MCInst> &Instructions) {
3100 if (hasMips32r6() || hasMips64r6()) {
3101 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3102 return false;
3103 }
3104
3105 const MCOperand &DstRegOp = Inst.getOperand(0);
3106 assert(DstRegOp.isReg() && "expected register operand kind");
3107
3108 const MCOperand &SrcRegOp = Inst.getOperand(1);
3109 assert(SrcRegOp.isReg() && "expected register operand kind");
3110
3111 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3112 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3113
3114 unsigned SrcReg = SrcRegOp.getReg();
3115 int64_t OffsetValue = OffsetImmOp.getImm();
3116 unsigned ATReg = 0;
3117
3118 // When the value of offset+3 does not fit in 16 bits, we have to load the
3119 // offset in AT, (D)ADDu the original source register (if there was one), and
3120 // then use AT as the source register for the generated LWL and LWR.
3121 bool LoadedOffsetInAT = false;
3122 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3123 ATReg = getATReg(IDLoc);
3124 if (!ATReg)
3125 return true;
3126 LoadedOffsetInAT = true;
3127
3128 warnIfNoMacro(IDLoc);
3129
3130 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003131 true, IDLoc, Instructions))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003132 return true;
3133
3134 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3135 // because it will make our output more similar to GAS'. For example,
3136 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3137 // instead of just an "ori $1, $9, 32768".
3138 // NOTE: If there is no source register specified in the ULW, the parser
3139 // will interpret it as $0.
3140 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3141 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3142 }
3143
3144 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3145 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3146 if (isLittle()) {
3147 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3148 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3149 } else {
3150 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3151 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3152 }
3153
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003154 emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
3155 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003156
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003157 emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset, IDLoc,
3158 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003159
3160 return false;
3161}
3162
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003163bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
3164 SmallVectorImpl<MCInst> &Instructions) {
3165
3166 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3167 assert (Inst.getOperand(0).isReg() &&
3168 Inst.getOperand(1).isReg() &&
3169 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3170
3171 unsigned ATReg = Mips::NoRegister;
3172 unsigned FinalDstReg = Mips::NoRegister;
3173 unsigned DstReg = Inst.getOperand(0).getReg();
3174 unsigned SrcReg = Inst.getOperand(1).getReg();
3175 int64_t ImmValue = Inst.getOperand(2).getImm();
3176
3177 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3178
3179 unsigned FinalOpcode = Inst.getOpcode();
3180
3181 if (DstReg == SrcReg) {
3182 ATReg = getATReg(Inst.getLoc());
3183 if (!ATReg)
3184 return true;
3185 FinalDstReg = DstReg;
3186 DstReg = ATReg;
3187 }
3188
3189 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Instructions)) {
3190 switch (FinalOpcode) {
3191 default:
3192 llvm_unreachable("unimplemented expansion");
3193 case (Mips::ADDi):
3194 FinalOpcode = Mips::ADD;
3195 break;
3196 case (Mips::ADDiu):
3197 FinalOpcode = Mips::ADDu;
3198 break;
3199 case (Mips::ANDi):
3200 FinalOpcode = Mips::AND;
3201 break;
3202 case (Mips::NORImm):
3203 FinalOpcode = Mips::NOR;
3204 break;
3205 case (Mips::ORi):
3206 FinalOpcode = Mips::OR;
3207 break;
3208 case (Mips::SLTi):
3209 FinalOpcode = Mips::SLT;
3210 break;
3211 case (Mips::SLTiu):
3212 FinalOpcode = Mips::SLTu;
3213 break;
3214 case (Mips::XORi):
3215 FinalOpcode = Mips::XOR;
3216 break;
3217 }
3218
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003219 if (FinalDstReg == Mips::NoRegister)
3220 emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, Instructions);
3221 else
3222 emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc,
3223 Instructions);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003224 return false;
3225 }
3226 return true;
3227}
3228
Toma Tabacu234482a2015-03-16 12:03:39 +00003229void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
3230 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003231 if (hasShortDelaySlot)
3232 emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, Instructions);
3233 else
3234 emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, Instructions);
Toma Tabacu234482a2015-03-16 12:03:39 +00003235}
3236
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003237void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +00003238 unsigned TrgReg, bool Is64Bit,
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003239 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders03f9c012015-07-14 12:24:22 +00003240 emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
3241 Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003242}
3243
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003244void MipsAsmParser::createCpRestoreMemOp(
3245 bool IsLoad, int StackOffset, SMLoc IDLoc,
3246 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003247 // If the offset can not fit into 16 bits, we need to expand.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003248 if (!isInt<16>(StackOffset)) {
3249 MCInst MemInst;
3250 MemInst.setOpcode(IsLoad ? Mips::LW : Mips::SW);
3251 MemInst.addOperand(MCOperand::createReg(Mips::GP));
3252 MemInst.addOperand(MCOperand::createReg(Mips::SP));
3253 MemInst.addOperand(MCOperand::createImm(StackOffset));
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003254 expandMemInst(MemInst, IDLoc, Instructions, IsLoad, true /*HasImmOpnd*/);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003255 return;
3256 }
3257
3258 emitRRI(IsLoad ? Mips::LW : Mips::SW, Mips::GP, Mips::SP, StackOffset, IDLoc,
3259 Instructions);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003260}
3261
Matheus Almeida595fcab2014-06-11 15:05:56 +00003262unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3263 // As described by the Mips32r2 spec, the registers Rd and Rs for
3264 // jalr.hb must be different.
3265 unsigned Opcode = Inst.getOpcode();
3266
3267 if (Opcode == Mips::JALR_HB &&
3268 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3269 return Match_RequiresDifferentSrcAndDst;
3270
3271 return Match_Success;
3272}
3273
David Blaikie960ea3f2014-06-08 16:18:35 +00003274bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3275 OperandVector &Operands,
3276 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003277 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003278 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003279
Jack Carterb4dbc172012-09-05 23:34:03 +00003280 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00003281 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00003282 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003283 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003284
3285 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003286 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003287 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00003288 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00003289 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00003290 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00003291 return false;
3292 }
3293 case Match_MissingFeature:
3294 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3295 return true;
3296 case Match_InvalidOperand: {
3297 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003298 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003299 if (ErrorInfo >= Operands.size())
3300 return Error(IDLoc, "too few operands for instruction");
3301
David Blaikie960ea3f2014-06-08 16:18:35 +00003302 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003303 if (ErrorLoc == SMLoc())
3304 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003305 }
3306
3307 return Error(ErrorLoc, "invalid operand for instruction");
3308 }
3309 case Match_MnemonicFail:
3310 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003311 case Match_RequiresDifferentSrcAndDst:
3312 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00003313 }
Craig Topper589ceee2015-01-03 08:16:34 +00003314
3315 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003316}
3317
Toma Tabacud9d344b2015-04-27 14:05:04 +00003318void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3319 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3320 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3321 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003322}
3323
Toma Tabacu81496c12015-05-20 08:54:45 +00003324void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3325 if (!AssemblerOptions.back()->isMacro())
3326 Warning(Loc, "macro instruction expanded into multiple instructions");
3327}
3328
Daniel Sandersef638fe2014-10-03 15:37:37 +00003329void
3330MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3331 SMRange Range, bool ShowColors) {
3332 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003333 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003334 ShowColors);
3335}
3336
Jack Carter1ac53222013-02-20 23:11:17 +00003337int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003338 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003339
Vladimir Medic4c299852013-11-06 11:27:05 +00003340 CC = StringSwitch<unsigned>(Name)
3341 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003342 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003343 .Case("a0", 4)
3344 .Case("a1", 5)
3345 .Case("a2", 6)
3346 .Case("a3", 7)
3347 .Case("v0", 2)
3348 .Case("v1", 3)
3349 .Case("s0", 16)
3350 .Case("s1", 17)
3351 .Case("s2", 18)
3352 .Case("s3", 19)
3353 .Case("s4", 20)
3354 .Case("s5", 21)
3355 .Case("s6", 22)
3356 .Case("s7", 23)
3357 .Case("k0", 26)
3358 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003359 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003360 .Case("sp", 29)
3361 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003362 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003363 .Case("ra", 31)
3364 .Case("t0", 8)
3365 .Case("t1", 9)
3366 .Case("t2", 10)
3367 .Case("t3", 11)
3368 .Case("t4", 12)
3369 .Case("t5", 13)
3370 .Case("t6", 14)
3371 .Case("t7", 15)
3372 .Case("t8", 24)
3373 .Case("t9", 25)
3374 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003375
Toma Tabacufda445c2014-09-15 15:33:01 +00003376 if (!(isABI_N32() || isABI_N64()))
3377 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003378
Daniel Sandersef638fe2014-10-03 15:37:37 +00003379 if (12 <= CC && CC <= 15) {
3380 // Name is one of t4-t7
3381 AsmToken RegTok = getLexer().peekTok();
3382 SMRange RegRange = RegTok.getLocRange();
3383
3384 StringRef FixedName = StringSwitch<StringRef>(Name)
3385 .Case("t4", "t0")
3386 .Case("t5", "t1")
3387 .Case("t6", "t2")
3388 .Case("t7", "t3")
3389 .Default("");
3390 assert(FixedName != "" && "Register name is not one of t4-t7.");
3391
3392 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3393 "Did you mean $" + FixedName + "?", RegRange);
3394 }
3395
Toma Tabacufda445c2014-09-15 15:33:01 +00003396 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3397 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3398 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3399 if (8 <= CC && CC <= 11)
3400 CC += 4;
3401
3402 if (CC == -1)
3403 CC = StringSwitch<unsigned>(Name)
3404 .Case("a4", 8)
3405 .Case("a5", 9)
3406 .Case("a6", 10)
3407 .Case("a7", 11)
3408 .Case("kt0", 26)
3409 .Case("kt1", 27)
3410 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003411
3412 return CC;
3413}
Jack Carterd0bd6422013-04-18 00:41:53 +00003414
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003415int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3416 int CC;
3417
3418 CC = StringSwitch<unsigned>(Name)
3419 .Case("hwr_cpunum", 0)
3420 .Case("hwr_synci_step", 1)
3421 .Case("hwr_cc", 2)
3422 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003423 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003424 .Default(-1);
3425
3426 return CC;
3427}
3428
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003429int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003430
Jack Cartera63b16a2012-09-07 00:23:42 +00003431 if (Name[0] == 'f') {
3432 StringRef NumString = Name.substr(1);
3433 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003434 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003435 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003436 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003437 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003438 return IntVal;
3439 }
3440 return -1;
3441}
Jack Cartera63b16a2012-09-07 00:23:42 +00003442
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003443int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3444
3445 if (Name.startswith("fcc")) {
3446 StringRef NumString = Name.substr(3);
3447 unsigned IntVal;
3448 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003449 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003450 if (IntVal > 7) // There are only 8 fcc registers.
3451 return -1;
3452 return IntVal;
3453 }
3454 return -1;
3455}
3456
3457int MipsAsmParser::matchACRegisterName(StringRef Name) {
3458
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003459 if (Name.startswith("ac")) {
3460 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003461 unsigned IntVal;
3462 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003463 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003464 if (IntVal > 3) // There are only 3 acc registers.
3465 return -1;
3466 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003467 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003468 return -1;
3469}
Jack Carterd0bd6422013-04-18 00:41:53 +00003470
Jack Carter5dc8ac92013-09-25 23:50:44 +00003471int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3472 unsigned IntVal;
3473
3474 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3475 return -1;
3476
3477 if (IntVal > 31)
3478 return -1;
3479
3480 return IntVal;
3481}
3482
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003483int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3484 int CC;
3485
3486 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003487 .Case("msair", 0)
3488 .Case("msacsr", 1)
3489 .Case("msaaccess", 2)
3490 .Case("msasave", 3)
3491 .Case("msamodify", 4)
3492 .Case("msarequest", 5)
3493 .Case("msamap", 6)
3494 .Case("msaunmap", 7)
3495 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003496
3497 return CC;
3498}
3499
Toma Tabacu89a712b2015-04-15 10:48:56 +00003500unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00003501 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00003502 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00003503 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00003504 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00003505 return 0;
3506 }
3507 unsigned AT = getReg(
3508 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00003509 return AT;
3510}
Jack Carter0b744b32012-10-04 02:29:46 +00003511
Jack Carterd0bd6422013-04-18 00:41:53 +00003512unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00003513 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00003514}
3515
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003516unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003517 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00003518 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003519}
3520
Jack Carter873c7242013-01-12 01:03:14 +00003521int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003522 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00003523 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00003524 return -1;
3525
Jack Carter873c7242013-01-12 01:03:14 +00003526 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00003527}
3528
Toma Tabacu13964452014-09-04 13:23:44 +00003529bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003530 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003531 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003532
Jack Carter30a59822012-10-04 04:03:53 +00003533 // Check if the current operand has a custom associated parser, if so, try to
3534 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00003535 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3536 if (ResTy == MatchOperand_Success)
3537 return false;
3538 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3539 // there was a match, but an error occurred, in which case, just return that
3540 // the operand parsing failed.
3541 if (ResTy == MatchOperand_ParseFail)
3542 return true;
3543
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003544 DEBUG(dbgs() << ".. Generic Parser\n");
3545
Jack Carterb4dbc172012-09-05 23:34:03 +00003546 switch (getLexer().getKind()) {
3547 default:
3548 Error(Parser.getTok().getLoc(), "unexpected token in operand");
3549 return true;
3550 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003551 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00003552 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00003553
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003554 // Almost all registers have been parsed by custom parsers. There is only
3555 // one exception to this. $zero (and it's alias $0) will reach this point
3556 // for div, divu, and similar instructions because it is not an operand
3557 // to the instruction definition but an explicit register. Special case
3558 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00003559 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00003560 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003561
Jack Carterd0bd6422013-04-18 00:41:53 +00003562 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00003563 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003564 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00003565 return true;
3566
Jack Carter873c7242013-01-12 01:03:14 +00003567 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00003568 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00003569 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00003570 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003571 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00003572
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003573 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003574 return false;
3575 }
Vladimir Medic4c299852013-11-06 11:27:05 +00003576 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00003577 case AsmToken::LParen:
3578 case AsmToken::Minus:
3579 case AsmToken::Plus:
3580 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003581 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00003582 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003583 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003584 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003585 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00003586 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00003587 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003588 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003589 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003590 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00003591 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00003592 return true;
3593
Jack Carter873c7242013-01-12 01:03:14 +00003594 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3595
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003596 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00003597 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003598 } // case AsmToken::Percent
3599 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00003600 return true;
3601}
3602
Vladimir Medic4c299852013-11-06 11:27:05 +00003603const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00003604 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003605 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00003606 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003607 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00003608 // It's a constant, evaluate reloc value.
3609 int16_t Val;
3610 switch (getVariantKind(RelocStr)) {
3611 case MCSymbolRefExpr::VK_Mips_ABS_LO:
3612 // Get the 1st 16-bits.
3613 Val = MCE->getValue() & 0xffff;
3614 break;
3615 case MCSymbolRefExpr::VK_Mips_ABS_HI:
3616 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
3617 // 16 bits being negative.
3618 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
3619 break;
3620 case MCSymbolRefExpr::VK_Mips_HIGHER:
3621 // Get the 3rd 16-bits.
3622 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
3623 break;
3624 case MCSymbolRefExpr::VK_Mips_HIGHEST:
3625 // Get the 4th 16-bits.
3626 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
3627 break;
3628 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00003629 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00003630 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00003631 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003632 }
3633
Jack Carterb5cf5902013-04-17 00:18:04 +00003634 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003635 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00003636 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00003637 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003638 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003639 return Res;
3640 }
3641
3642 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00003643 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
3644
Sasa Stankovic06c47802014-04-03 10:37:45 +00003645 // Try to create target expression.
3646 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00003647 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003648
Jack Carterd0bd6422013-04-18 00:41:53 +00003649 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
3650 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003651 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003652 return Res;
3653 }
3654
3655 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003656 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003657 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00003658 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00003659 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003660 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003661 return Expr;
3662}
3663
3664bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
3665
3666 switch (Expr->getKind()) {
3667 case MCExpr::Constant:
3668 return true;
3669 case MCExpr::SymbolRef:
3670 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
3671 case MCExpr::Binary:
3672 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
3673 if (!isEvaluated(BE->getLHS()))
3674 return false;
3675 return isEvaluated(BE->getRHS());
3676 }
3677 case MCExpr::Unary:
3678 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003679 case MCExpr::Target:
3680 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003681 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003682 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00003683}
Jack Carterd0bd6422013-04-18 00:41:53 +00003684
Jack Carterb5cf5902013-04-17 00:18:04 +00003685bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003686 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003687 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00003688 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00003689 if (Tok.isNot(AsmToken::Identifier))
3690 return true;
3691
Yaron Keren075759a2015-03-30 15:42:36 +00003692 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00003693
Jack Carterd0bd6422013-04-18 00:41:53 +00003694 Parser.Lex(); // Eat the identifier.
3695 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003696 const MCExpr *IdVal;
3697 SMLoc EndLoc;
3698
3699 if (getLexer().getKind() == AsmToken::LParen) {
3700 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003701 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003702 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003703 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003704 const AsmToken &nextTok = Parser.getTok();
3705 if (nextTok.isNot(AsmToken::Identifier))
3706 return true;
3707 Str += "(%";
3708 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00003709 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00003710 if (getLexer().getKind() != AsmToken::LParen)
3711 return true;
3712 } else
3713 break;
3714 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003715 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00003716 return true;
3717
3718 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00003719 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003720
3721 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00003722 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003723
Jack Carterd0bd6422013-04-18 00:41:53 +00003724 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00003725 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003726}
3727
Jack Carterb4dbc172012-09-05 23:34:03 +00003728bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
3729 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003730 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00003731 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003732 if (ResTy == MatchOperand_Success) {
3733 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00003734 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003735 StartLoc = Operand.getStartLoc();
3736 EndLoc = Operand.getEndLoc();
3737
3738 // AFAIK, we only support numeric registers and named GPR's in CFI
3739 // directives.
3740 // Don't worry about eating tokens before failing. Using an unrecognised
3741 // register is a parse error.
3742 if (Operand.isGPRAsmReg()) {
3743 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003744 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003745 }
3746
3747 return (RegNo == (unsigned)-1);
3748 }
3749
3750 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00003751 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00003752}
3753
Jack Carterb5cf5902013-04-17 00:18:04 +00003754bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003755 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00003756 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003757 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003758 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00003759
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003760 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003761 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003762 ++NumOfLParen;
3763 }
Jack Carter873c7242013-01-12 01:03:14 +00003764
Jack Carterd0bd6422013-04-18 00:41:53 +00003765 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003766 default:
3767 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00003768 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00003769 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00003770 case AsmToken::Integer:
3771 case AsmToken::Minus:
3772 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00003773 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003774 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00003775 else
3776 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00003777 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00003778 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003779 break;
Jack Carter873c7242013-01-12 01:03:14 +00003780 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00003781 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003782 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003783 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003784}
3785
David Blaikie960ea3f2014-06-08 16:18:35 +00003786MipsAsmParser::OperandMatchResultTy
3787MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003788 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003789 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00003790 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00003791 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003792 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003793 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00003794 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00003795 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00003796
Jack Carterb5cf5902013-04-17 00:18:04 +00003797 if (getLexer().getKind() == AsmToken::LParen) {
3798 Parser.Lex();
3799 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003800 }
3801
Jack Carterb5cf5902013-04-17 00:18:04 +00003802 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003803 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00003804 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003805
Jack Carterd0bd6422013-04-18 00:41:53 +00003806 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003807 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003808 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003809 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003810 SMLoc E =
3811 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003812 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003813 return MatchOperand_Success;
3814 }
3815 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003816 SMLoc E =
3817 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00003818
Jack Carterd0bd6422013-04-18 00:41:53 +00003819 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003820 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00003821 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003822 S, E, *this);
3823 Operands.push_back(
3824 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003825 return MatchOperand_Success;
3826 }
3827 Error(Parser.getTok().getLoc(), "'(' expected");
3828 return MatchOperand_ParseFail;
3829 }
3830
Jack Carterd0bd6422013-04-18 00:41:53 +00003831 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003832 }
3833
Toma Tabacu13964452014-09-04 13:23:44 +00003834 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003835 if (Res != MatchOperand_Success)
3836 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003837
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003838 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003839 Error(Parser.getTok().getLoc(), "')' expected");
3840 return MatchOperand_ParseFail;
3841 }
3842
Jack Carter873c7242013-01-12 01:03:14 +00003843 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3844
Jack Carterd0bd6422013-04-18 00:41:53 +00003845 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003846
Craig Topper062a2ba2014-04-25 05:30:21 +00003847 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003848 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003849
Jack Carterd0bd6422013-04-18 00:41:53 +00003850 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00003851 std::unique_ptr<MipsOperand> op(
3852 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00003853 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003854 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003855 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00003856 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003857 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
3858 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003859 if (IdVal->evaluateAsAbsolute(Imm))
3860 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003861 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003862 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00003863 getContext());
3864 }
3865
David Blaikie960ea3f2014-06-08 16:18:35 +00003866 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003867 return MatchOperand_Success;
3868}
3869
David Blaikie960ea3f2014-06-08 16:18:35 +00003870bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003871 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00003872 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00003873 if (Sym) {
3874 SMLoc S = Parser.getTok().getLoc();
3875 const MCExpr *Expr;
3876 if (Sym->isVariable())
3877 Expr = Sym->getVariableValue();
3878 else
3879 return false;
3880 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003881 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00003882 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00003883 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003884 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003885 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00003886 if (ResTy == MatchOperand_Success) {
3887 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00003888 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00003889 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003890 llvm_unreachable("Should never ParseFail");
3891 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00003892 }
3893 } else if (Expr->getKind() == MCExpr::Constant) {
3894 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00003895 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00003896 Operands.push_back(
3897 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00003898 return true;
3899 }
3900 }
3901 return false;
3902}
Jack Carterd0bd6422013-04-18 00:41:53 +00003903
Jack Carter873c7242013-01-12 01:03:14 +00003904MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003905MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00003906 StringRef Identifier,
3907 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003908 int Index = matchCPURegisterName(Identifier);
3909 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003910 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003911 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3912 return MatchOperand_Success;
3913 }
3914
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003915 Index = matchHWRegsRegisterName(Identifier);
3916 if (Index != -1) {
3917 Operands.push_back(MipsOperand::createHWRegsReg(
3918 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3919 return MatchOperand_Success;
3920 }
3921
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003922 Index = matchFPURegisterName(Identifier);
3923 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003924 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003925 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3926 return MatchOperand_Success;
3927 }
3928
3929 Index = matchFCCRegisterName(Identifier);
3930 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003931 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003932 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3933 return MatchOperand_Success;
3934 }
3935
3936 Index = matchACRegisterName(Identifier);
3937 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003938 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003939 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3940 return MatchOperand_Success;
3941 }
3942
3943 Index = matchMSA128RegisterName(Identifier);
3944 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003945 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003946 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3947 return MatchOperand_Success;
3948 }
3949
3950 Index = matchMSA128CtrlRegisterName(Identifier);
3951 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003952 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003953 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3954 return MatchOperand_Success;
3955 }
3956
3957 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00003958}
3959
3960MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003961MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003962 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00003963 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003964
3965 if (Token.is(AsmToken::Identifier)) {
3966 DEBUG(dbgs() << ".. identifier\n");
3967 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00003968 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003969 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00003970 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003971 } else if (Token.is(AsmToken::Integer)) {
3972 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003973 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003974 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
3975 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003976 return MatchOperand_Success;
3977 }
3978
3979 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
3980
3981 return MatchOperand_NoMatch;
3982}
3983
David Blaikie960ea3f2014-06-08 16:18:35 +00003984MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003985MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003986 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003987 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003988
3989 auto Token = Parser.getTok();
3990
3991 SMLoc S = Token.getLoc();
3992
3993 if (Token.isNot(AsmToken::Dollar)) {
3994 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
3995 if (Token.is(AsmToken::Identifier)) {
3996 if (searchSymbolAlias(Operands))
3997 return MatchOperand_Success;
3998 }
3999 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4000 return MatchOperand_NoMatch;
4001 }
4002 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004003
Toma Tabacu13964452014-09-04 13:23:44 +00004004 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004005 if (ResTy == MatchOperand_Success) {
4006 Parser.Lex(); // $
4007 Parser.Lex(); // identifier
4008 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004009 return ResTy;
4010}
4011
4012MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004013MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004014 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004015 switch (getLexer().getKind()) {
4016 default:
4017 return MatchOperand_NoMatch;
4018 case AsmToken::LParen:
4019 case AsmToken::Minus:
4020 case AsmToken::Plus:
4021 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004022 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004023 case AsmToken::String:
4024 break;
4025 }
4026
4027 const MCExpr *IdVal;
4028 SMLoc S = Parser.getTok().getLoc();
4029 if (getParser().parseExpression(IdVal))
4030 return MatchOperand_ParseFail;
4031
4032 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4033 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4034 return MatchOperand_Success;
4035}
4036
David Blaikie960ea3f2014-06-08 16:18:35 +00004037MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004038MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004039 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004040 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004041
4042 SMLoc S = getLexer().getLoc();
4043
4044 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00004045 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004046 if (ResTy != MatchOperand_NoMatch)
4047 return ResTy;
4048
Daniel Sanders315386c2014-04-01 10:40:14 +00004049 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00004050 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00004051 if (ResTy != MatchOperand_NoMatch)
4052 return ResTy;
4053
Daniel Sandersffd84362014-04-01 10:41:48 +00004054 const MCExpr *Expr = nullptr;
4055 if (Parser.parseExpression(Expr)) {
4056 // We have no way of knowing if a symbol was consumed so we must ParseFail
4057 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004058 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004059 Operands.push_back(
4060 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004061 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004062}
4063
Vladimir Medic2b953d02013-10-01 09:48:56 +00004064MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004065MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004066 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004067 const MCExpr *IdVal;
4068 // If the first token is '$' we may have register operand.
4069 if (Parser.getTok().is(AsmToken::Dollar))
4070 return MatchOperand_NoMatch;
4071 SMLoc S = Parser.getTok().getLoc();
4072 if (getParser().parseExpression(IdVal))
4073 return MatchOperand_ParseFail;
4074 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004075 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004076 int64_t Val = MCE->getValue();
4077 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4078 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004079 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004080 return MatchOperand_Success;
4081}
4082
Matheus Almeida779c5932013-11-18 12:32:49 +00004083MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004084MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004085 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00004086 switch (getLexer().getKind()) {
4087 default:
4088 return MatchOperand_NoMatch;
4089 case AsmToken::LParen:
4090 case AsmToken::Plus:
4091 case AsmToken::Minus:
4092 case AsmToken::Integer:
4093 break;
4094 }
4095
4096 const MCExpr *Expr;
4097 SMLoc S = Parser.getTok().getLoc();
4098
4099 if (getParser().parseExpression(Expr))
4100 return MatchOperand_ParseFail;
4101
4102 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004103 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00004104 Error(S, "expected immediate value");
4105 return MatchOperand_ParseFail;
4106 }
4107
4108 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
4109 // and because the CPU always adds one to the immediate field, the allowed
4110 // range becomes 1..4. We'll only check the range here and will deal
4111 // with the addition/subtraction when actually decoding/encoding
4112 // the instruction.
4113 if (Val < 1 || Val > 4) {
4114 Error(S, "immediate not in range (1..4)");
4115 return MatchOperand_ParseFail;
4116 }
4117
Jack Carter3b2c96e2014-01-22 23:31:38 +00004118 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004119 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00004120 return MatchOperand_Success;
4121}
4122
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004123MipsAsmParser::OperandMatchResultTy
4124MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4125 MCAsmParser &Parser = getParser();
4126 SmallVector<unsigned, 10> Regs;
4127 unsigned RegNo;
4128 unsigned PrevReg = Mips::NoRegister;
4129 bool RegRange = false;
4130 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4131
4132 if (Parser.getTok().isNot(AsmToken::Dollar))
4133 return MatchOperand_ParseFail;
4134
4135 SMLoc S = Parser.getTok().getLoc();
4136 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4137 SMLoc E = getLexer().getLoc();
4138 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4139 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4140 if (RegRange) {
4141 // Remove last register operand because registers from register range
4142 // should be inserted first.
4143 if (RegNo == Mips::RA) {
4144 Regs.push_back(RegNo);
4145 } else {
4146 unsigned TmpReg = PrevReg + 1;
4147 while (TmpReg <= RegNo) {
4148 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
4149 Error(E, "invalid register operand");
4150 return MatchOperand_ParseFail;
4151 }
4152
4153 PrevReg = TmpReg;
4154 Regs.push_back(TmpReg++);
4155 }
4156 }
4157
4158 RegRange = false;
4159 } else {
4160 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
4161 (RegNo != Mips::RA)) {
4162 Error(E, "$16 or $31 expected");
4163 return MatchOperand_ParseFail;
4164 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
4165 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
4166 Error(E, "invalid register operand");
4167 return MatchOperand_ParseFail;
4168 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
4169 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
4170 Error(E, "consecutive register numbers expected");
4171 return MatchOperand_ParseFail;
4172 }
4173
4174 Regs.push_back(RegNo);
4175 }
4176
4177 if (Parser.getTok().is(AsmToken::Minus))
4178 RegRange = true;
4179
4180 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4181 !Parser.getTok().isNot(AsmToken::Comma)) {
4182 Error(E, "',' or '-' expected");
4183 return MatchOperand_ParseFail;
4184 }
4185
4186 Lex(); // Consume comma or minus
4187 if (Parser.getTok().isNot(AsmToken::Dollar))
4188 break;
4189
4190 PrevReg = RegNo;
4191 }
4192
4193 SMLoc E = Parser.getTok().getLoc();
4194 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4195 parseMemOperand(Operands);
4196 return MatchOperand_Success;
4197}
4198
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004199MipsAsmParser::OperandMatchResultTy
4200MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4201 MCAsmParser &Parser = getParser();
4202
4203 SMLoc S = Parser.getTok().getLoc();
4204 if (parseAnyRegister(Operands) != MatchOperand_Success)
4205 return MatchOperand_ParseFail;
4206
4207 SMLoc E = Parser.getTok().getLoc();
4208 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
4209 unsigned Reg = Op.getGPR32Reg();
4210 Operands.pop_back();
4211 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
4212 return MatchOperand_Success;
4213}
4214
Zoran Jovanovic41688672015-02-10 16:36:20 +00004215MipsAsmParser::OperandMatchResultTy
4216MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4217 MCAsmParser &Parser = getParser();
4218 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4219 SmallVector<unsigned, 10> Regs;
4220
4221 if (Parser.getTok().isNot(AsmToken::Dollar))
4222 return MatchOperand_ParseFail;
4223
4224 SMLoc S = Parser.getTok().getLoc();
4225
4226 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4227 return MatchOperand_ParseFail;
4228
4229 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4230 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4231 Regs.push_back(RegNo);
4232
4233 SMLoc E = Parser.getTok().getLoc();
4234 if (Parser.getTok().isNot(AsmToken::Comma)) {
4235 Error(E, "',' expected");
4236 return MatchOperand_ParseFail;
4237 }
4238
4239 // Remove comma.
4240 Parser.Lex();
4241
4242 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4243 return MatchOperand_ParseFail;
4244
4245 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4246 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4247 Regs.push_back(RegNo);
4248
4249 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4250
4251 return MatchOperand_Success;
4252}
4253
Jack Carterdc1e35d2012-09-06 20:00:02 +00004254MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
4255
Vladimir Medic4c299852013-11-06 11:27:05 +00004256 MCSymbolRefExpr::VariantKind VK =
4257 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
4258 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
4259 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
4260 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
4261 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
4262 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
4263 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
4264 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
4265 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
4266 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
4267 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
4268 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
4269 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
4270 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
4271 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
4272 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
4273 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
4274 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00004275 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
4276 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
4277 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
4278 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
4279 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
4280 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00004281 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
4282 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00004283 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004284
Matheus Almeida2852af82014-04-22 10:15:54 +00004285 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00004286
Jack Carterdc1e35d2012-09-06 20:00:02 +00004287 return VK;
4288}
Jack Cartera63b16a2012-09-07 00:23:42 +00004289
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004290/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4291/// either this.
4292/// ::= '(', register, ')'
4293/// handle it before we iterate so we don't get tripped up by the lack of
4294/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004295bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004296 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004297 if (getLexer().is(AsmToken::LParen)) {
4298 Operands.push_back(
4299 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4300 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004301 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004302 SMLoc Loc = getLexer().getLoc();
4303 Parser.eatToEndOfStatement();
4304 return Error(Loc, "unexpected token in argument list");
4305 }
4306 if (Parser.getTok().isNot(AsmToken::RParen)) {
4307 SMLoc Loc = getLexer().getLoc();
4308 Parser.eatToEndOfStatement();
4309 return Error(Loc, "unexpected token, expected ')'");
4310 }
4311 Operands.push_back(
4312 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4313 Parser.Lex();
4314 }
4315 return false;
4316}
4317
4318/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4319/// either one of these.
4320/// ::= '[', register, ']'
4321/// ::= '[', integer, ']'
4322/// handle it before we iterate so we don't get tripped up by the lack of
4323/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004324bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004325 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004326 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004327 if (getLexer().is(AsmToken::LBrac)) {
4328 Operands.push_back(
4329 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4330 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004331 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004332 SMLoc Loc = getLexer().getLoc();
4333 Parser.eatToEndOfStatement();
4334 return Error(Loc, "unexpected token in argument list");
4335 }
4336 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4337 SMLoc Loc = getLexer().getLoc();
4338 Parser.eatToEndOfStatement();
4339 return Error(Loc, "unexpected token, expected ']'");
4340 }
4341 Operands.push_back(
4342 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4343 Parser.Lex();
4344 }
4345 return false;
4346}
4347
David Blaikie960ea3f2014-06-08 16:18:35 +00004348bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4349 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004350 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004351 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004352
4353 // We have reached first instruction, module directive are now forbidden.
4354 getTargetStreamer().forbidModuleDirective();
4355
Vladimir Medic74593e62013-07-17 15:00:42 +00004356 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004357 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004358 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004359 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004360 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004361 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004362 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004363
4364 // Read the remaining operands.
4365 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4366 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004367 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004368 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004369 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004370 return Error(Loc, "unexpected token in argument list");
4371 }
Toma Tabacu13964452014-09-04 13:23:44 +00004372 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004373 return true;
4374 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004375
Jack Carterd0bd6422013-04-18 00:41:53 +00004376 while (getLexer().is(AsmToken::Comma)) {
4377 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004378 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004379 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004380 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004381 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004382 return Error(Loc, "unexpected token in argument list");
4383 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004384 // Parse bracket and parenthesis suffixes before we iterate
4385 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004386 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004387 return true;
4388 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004389 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004390 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004391 }
4392 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004393 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4394 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004395 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004396 return Error(Loc, "unexpected token in argument list");
4397 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004398 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004399 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004400}
4401
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004402bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004403 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004404 SMLoc Loc = getLexer().getLoc();
4405 Parser.eatToEndOfStatement();
4406 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004407}
4408
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004409bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004410 return Error(Loc, ErrorMsg);
4411}
4412
Jack Carter0b744b32012-10-04 02:29:46 +00004413bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004414 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004415 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004416
4417 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004418 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004419
4420 Parser.Lex(); // Eat "noat".
4421
Jack Carterd0bd6422013-04-18 00:41:53 +00004422 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004423 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004424 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004425 return false;
4426 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004427
4428 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004429 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004430 return false;
4431}
Jack Carterd0bd6422013-04-18 00:41:53 +00004432
Jack Carter0b744b32012-10-04 02:29:46 +00004433bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004434 // Line can be: ".set at", which sets $at to $1
4435 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004436 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004437 Parser.Lex(); // Eat "at".
4438
Jack Carter0b744b32012-10-04 02:29:46 +00004439 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004440 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004441 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004442
4443 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004444 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004445 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004446 }
4447
4448 if (getLexer().isNot(AsmToken::Equal)) {
4449 reportParseError("unexpected token, expected equals sign");
4450 return false;
4451 }
4452 Parser.Lex(); // Eat "=".
4453
4454 if (getLexer().isNot(AsmToken::Dollar)) {
4455 if (getLexer().is(AsmToken::EndOfStatement)) {
4456 reportParseError("no register specified");
4457 return false;
4458 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004459 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004460 return false;
4461 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004462 }
4463 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004464
Toma Tabacu16a74492015-02-13 10:30:57 +00004465 // Find out what "reg" is.
4466 unsigned AtRegNo;
4467 const AsmToken &Reg = Parser.getTok();
4468 if (Reg.is(AsmToken::Identifier)) {
4469 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4470 } else if (Reg.is(AsmToken::Integer)) {
4471 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004472 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004473 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004474 return false;
4475 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004476
4477 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004478 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004479 reportParseError("invalid register");
4480 return false;
4481 }
4482 Parser.Lex(); // Eat "reg".
4483
4484 // If this is not the end of the statement, report an error.
4485 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4486 reportParseError("unexpected token, expected end of statement");
4487 return false;
4488 }
4489
4490 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4491
4492 Parser.Lex(); // Consume the EndOfStatement.
4493 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004494}
4495
4496bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004497 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004498 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004499 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004500 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004501 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004502 return false;
4503 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004504 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004505 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004506 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004507 return false;
4508}
4509
4510bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004511 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004512 Parser.Lex();
4513 // If this is not the end of the statement, report an error.
4514 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004515 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004516 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00004517 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004518 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00004519 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004520 Parser.Lex(); // Consume the EndOfStatement.
4521 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004522}
4523
4524bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004525 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004526 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004527 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004528 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004529 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004530 return false;
4531 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004532 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004533 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004534 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004535 return false;
4536}
4537
4538bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004539 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004540 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004541 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004542 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004543 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004544 return false;
4545 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004546 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00004547 reportParseError("`noreorder' must be set before `nomacro'");
4548 return false;
4549 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004550 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004551 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004552 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004553 return false;
4554}
Jack Carterd76b2372013-03-21 21:44:16 +00004555
Daniel Sanders44934432014-08-07 12:03:36 +00004556bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004557 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004558 Parser.Lex();
4559
4560 // If this is not the end of the statement, report an error.
4561 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004562 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004563
4564 setFeatureBits(Mips::FeatureMSA, "msa");
4565 getTargetStreamer().emitDirectiveSetMsa();
4566 return false;
4567}
4568
4569bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004570 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004571 Parser.Lex();
4572
4573 // If this is not the end of the statement, report an error.
4574 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004575 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004576
4577 clearFeatureBits(Mips::FeatureMSA, "msa");
4578 getTargetStreamer().emitDirectiveSetNoMsa();
4579 return false;
4580}
4581
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004582bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004583 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004584 Parser.Lex(); // Eat "nodsp".
4585
4586 // If this is not the end of the statement, report an error.
4587 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4588 reportParseError("unexpected token, expected end of statement");
4589 return false;
4590 }
4591
4592 clearFeatureBits(Mips::FeatureDSP, "dsp");
4593 getTargetStreamer().emitDirectiveSetNoDsp();
4594 return false;
4595}
4596
Toma Tabacucc2502d2014-11-04 17:18:07 +00004597bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004598 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004599 Parser.Lex(); // Eat "mips16".
4600
Jack Carter39536722014-01-22 23:08:42 +00004601 // If this is not the end of the statement, report an error.
4602 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004603 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00004604 return false;
4605 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00004606
4607 setFeatureBits(Mips::FeatureMips16, "mips16");
4608 getTargetStreamer().emitDirectiveSetMips16();
4609 Parser.Lex(); // Consume the EndOfStatement.
4610 return false;
4611}
4612
4613bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004614 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004615 Parser.Lex(); // Eat "nomips16".
4616
4617 // If this is not the end of the statement, report an error.
4618 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4619 reportParseError("unexpected token, expected end of statement");
4620 return false;
4621 }
4622
4623 clearFeatureBits(Mips::FeatureMips16, "mips16");
4624 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00004625 Parser.Lex(); // Consume the EndOfStatement.
4626 return false;
4627}
4628
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004629bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004630 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004631 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004632 // Line can be: .set fp=32
4633 // .set fp=xx
4634 // .set fp=64
4635 Parser.Lex(); // Eat fp token
4636 AsmToken Tok = Parser.getTok();
4637 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004638 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004639 return false;
4640 }
4641 Parser.Lex(); // Eat '=' token.
4642 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004643
4644 if (!parseFpABIValue(FpAbiVal, ".set"))
4645 return false;
4646
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004647 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004648 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004649 return false;
4650 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004651 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004652 Parser.Lex(); // Consume the EndOfStatement.
4653 return false;
4654}
4655
Toma Tabacu32c72aa2015-06-30 09:36:50 +00004656bool MipsAsmParser::parseSetOddSPRegDirective() {
4657 MCAsmParser &Parser = getParser();
4658
4659 Parser.Lex(); // Eat "oddspreg".
4660 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4661 reportParseError("unexpected token, expected end of statement");
4662 return false;
4663 }
4664
4665 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4666 getTargetStreamer().emitDirectiveSetOddSPReg();
4667 return false;
4668}
4669
4670bool MipsAsmParser::parseSetNoOddSPRegDirective() {
4671 MCAsmParser &Parser = getParser();
4672
4673 Parser.Lex(); // Eat "nooddspreg".
4674 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4675 reportParseError("unexpected token, expected end of statement");
4676 return false;
4677 }
4678
4679 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4680 getTargetStreamer().emitDirectiveSetNoOddSPReg();
4681 return false;
4682}
4683
Toma Tabacu9db22db2014-09-09 10:15:38 +00004684bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004685 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004686 SMLoc Loc = getLexer().getLoc();
4687
4688 Parser.Lex();
4689 if (getLexer().isNot(AsmToken::EndOfStatement))
4690 return reportParseError("unexpected token, expected end of statement");
4691
4692 // Always keep an element on the options "stack" to prevent the user
4693 // from changing the initial options. This is how we remember them.
4694 if (AssemblerOptions.size() == 2)
4695 return reportParseError(Loc, ".set pop with no .set push");
4696
4697 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00004698 setAvailableFeatures(
4699 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
4700 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00004701
4702 getTargetStreamer().emitDirectiveSetPop();
4703 return false;
4704}
4705
4706bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004707 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004708 Parser.Lex();
4709 if (getLexer().isNot(AsmToken::EndOfStatement))
4710 return reportParseError("unexpected token, expected end of statement");
4711
4712 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00004713 AssemblerOptions.push_back(
4714 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00004715
4716 getTargetStreamer().emitDirectiveSetPush();
4717 return false;
4718}
4719
Toma Tabacu29696502015-06-02 09:48:04 +00004720bool MipsAsmParser::parseSetSoftFloatDirective() {
4721 MCAsmParser &Parser = getParser();
4722 Parser.Lex();
4723 if (getLexer().isNot(AsmToken::EndOfStatement))
4724 return reportParseError("unexpected token, expected end of statement");
4725
4726 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4727 getTargetStreamer().emitDirectiveSetSoftFloat();
4728 return false;
4729}
4730
4731bool MipsAsmParser::parseSetHardFloatDirective() {
4732 MCAsmParser &Parser = getParser();
4733 Parser.Lex();
4734 if (getLexer().isNot(AsmToken::EndOfStatement))
4735 return reportParseError("unexpected token, expected end of statement");
4736
4737 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4738 getTargetStreamer().emitDirectiveSetHardFloat();
4739 return false;
4740}
4741
Jack Carterd76b2372013-03-21 21:44:16 +00004742bool MipsAsmParser::parseSetAssignment() {
4743 StringRef Name;
4744 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00004745 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00004746
4747 if (Parser.parseIdentifier(Name))
4748 reportParseError("expected identifier after .set");
4749
4750 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004751 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00004752 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00004753
Jack Carter3b2c96e2014-01-22 23:31:38 +00004754 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00004755 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00004756
Jim Grosbach6f482002015-05-18 18:43:14 +00004757 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00004758 Sym->setVariableValue(Value);
4759
4760 return false;
4761}
Jack Carterd0bd6422013-04-18 00:41:53 +00004762
Toma Tabacu26647792014-09-09 12:52:14 +00004763bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004764 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00004765 Parser.Lex();
4766 if (getLexer().isNot(AsmToken::EndOfStatement))
4767 return reportParseError("unexpected token, expected end of statement");
4768
4769 // Reset assembler options to their initial values.
Toma Tabacu465acfd2015-06-09 13:33:26 +00004770 setAvailableFeatures(
4771 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
4772 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00004773 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
4774
4775 getTargetStreamer().emitDirectiveSetMips0();
4776 return false;
4777}
4778
Toma Tabacu85618b32014-08-19 14:22:52 +00004779bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004780 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00004781 Parser.Lex();
4782 if (getLexer().isNot(AsmToken::Equal))
4783 return reportParseError("unexpected token, expected equals sign");
4784
4785 Parser.Lex();
4786 StringRef Arch;
4787 if (Parser.parseIdentifier(Arch))
4788 return reportParseError("expected arch identifier");
4789
4790 StringRef ArchFeatureName =
4791 StringSwitch<StringRef>(Arch)
4792 .Case("mips1", "mips1")
4793 .Case("mips2", "mips2")
4794 .Case("mips3", "mips3")
4795 .Case("mips4", "mips4")
4796 .Case("mips5", "mips5")
4797 .Case("mips32", "mips32")
4798 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004799 .Case("mips32r3", "mips32r3")
4800 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004801 .Case("mips32r6", "mips32r6")
4802 .Case("mips64", "mips64")
4803 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004804 .Case("mips64r3", "mips64r3")
4805 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004806 .Case("mips64r6", "mips64r6")
4807 .Case("cnmips", "cnmips")
4808 .Case("r4000", "mips3") // This is an implementation of Mips3.
4809 .Default("");
4810
4811 if (ArchFeatureName.empty())
4812 return reportParseError("unsupported architecture");
4813
4814 selectArch(ArchFeatureName);
4815 getTargetStreamer().emitDirectiveSetArch(Arch);
4816 return false;
4817}
4818
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004819bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004820 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004821 Parser.Lex();
4822 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004823 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004824
Matheus Almeida2852af82014-04-22 10:15:54 +00004825 switch (Feature) {
4826 default:
4827 llvm_unreachable("Unimplemented feature");
4828 case Mips::FeatureDSP:
4829 setFeatureBits(Mips::FeatureDSP, "dsp");
4830 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004831 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004832 case Mips::FeatureMicroMips:
4833 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004834 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004835 case Mips::FeatureMips1:
4836 selectArch("mips1");
4837 getTargetStreamer().emitDirectiveSetMips1();
4838 break;
4839 case Mips::FeatureMips2:
4840 selectArch("mips2");
4841 getTargetStreamer().emitDirectiveSetMips2();
4842 break;
4843 case Mips::FeatureMips3:
4844 selectArch("mips3");
4845 getTargetStreamer().emitDirectiveSetMips3();
4846 break;
4847 case Mips::FeatureMips4:
4848 selectArch("mips4");
4849 getTargetStreamer().emitDirectiveSetMips4();
4850 break;
4851 case Mips::FeatureMips5:
4852 selectArch("mips5");
4853 getTargetStreamer().emitDirectiveSetMips5();
4854 break;
4855 case Mips::FeatureMips32:
4856 selectArch("mips32");
4857 getTargetStreamer().emitDirectiveSetMips32();
4858 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004859 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004860 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004861 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004862 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004863 case Mips::FeatureMips32r3:
4864 selectArch("mips32r3");
4865 getTargetStreamer().emitDirectiveSetMips32R3();
4866 break;
4867 case Mips::FeatureMips32r5:
4868 selectArch("mips32r5");
4869 getTargetStreamer().emitDirectiveSetMips32R5();
4870 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004871 case Mips::FeatureMips32r6:
4872 selectArch("mips32r6");
4873 getTargetStreamer().emitDirectiveSetMips32R6();
4874 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004875 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004876 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00004877 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00004878 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004879 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004880 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004881 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00004882 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004883 case Mips::FeatureMips64r3:
4884 selectArch("mips64r3");
4885 getTargetStreamer().emitDirectiveSetMips64R3();
4886 break;
4887 case Mips::FeatureMips64r5:
4888 selectArch("mips64r5");
4889 getTargetStreamer().emitDirectiveSetMips64R5();
4890 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004891 case Mips::FeatureMips64r6:
4892 selectArch("mips64r6");
4893 getTargetStreamer().emitDirectiveSetMips64R6();
4894 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004895 }
4896 return false;
4897}
4898
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004899bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004900 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004901 if (getLexer().isNot(AsmToken::Comma)) {
4902 SMLoc Loc = getLexer().getLoc();
4903 Parser.eatToEndOfStatement();
4904 return Error(Loc, ErrorStr);
4905 }
4906
Matheus Almeida2852af82014-04-22 10:15:54 +00004907 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004908 return true;
4909}
4910
Daniel Sanderse2982ad2015-09-17 16:08:39 +00004911// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
4912// In this class, it is only used for .cprestore.
4913// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
4914// MipsTargetELFStreamer and MipsAsmParser.
4915bool MipsAsmParser::isPicAndNotNxxAbi() {
4916 return inPicMode() && !(isABI_N32() || isABI_N64());
4917}
4918
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004919bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00004920 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00004921 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004922
Toma Tabacudde4c462014-11-06 10:02:45 +00004923 if (inMips16Mode()) {
4924 reportParseError(".cpload is not supported in Mips16 mode");
4925 return false;
4926 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004927
David Blaikie960ea3f2014-06-08 16:18:35 +00004928 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00004929 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004930 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4931 reportParseError("expected register containing function address");
4932 return false;
4933 }
4934
David Blaikie960ea3f2014-06-08 16:18:35 +00004935 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
4936 if (!RegOpnd.isGPRAsmReg()) {
4937 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004938 return false;
4939 }
4940
Toma Tabacudde4c462014-11-06 10:02:45 +00004941 // If this is not the end of the statement, report an error.
4942 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4943 reportParseError("unexpected token, expected end of statement");
4944 return false;
4945 }
4946
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004947 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004948 return false;
4949}
4950
Daniel Sanderse2982ad2015-09-17 16:08:39 +00004951bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
4952 MCAsmParser &Parser = getParser();
4953
4954 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
4955 // is used in non-PIC mode.
4956
4957 if (inMips16Mode()) {
4958 reportParseError(".cprestore is not supported in Mips16 mode");
4959 return false;
4960 }
4961
4962 // Get the stack offset value.
4963 const MCExpr *StackOffset;
4964 int64_t StackOffsetVal;
4965 if (Parser.parseExpression(StackOffset)) {
4966 reportParseError("expected stack offset value");
4967 return false;
4968 }
4969
4970 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
4971 reportParseError("stack offset is not an absolute expression");
4972 return false;
4973 }
4974
4975 if (StackOffsetVal < 0) {
4976 Warning(Loc, ".cprestore with negative stack offset has no effect");
4977 IsCpRestoreSet = false;
4978 } else {
4979 IsCpRestoreSet = true;
4980 CpRestoreOffset = StackOffsetVal;
4981 }
4982
4983 // If this is not the end of the statement, report an error.
4984 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4985 reportParseError("unexpected token, expected end of statement");
4986 return false;
4987 }
4988
4989 // Store the $gp on the stack.
4990 SmallVector<MCInst, 3> StoreInsts;
4991 createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc,
4992 StoreInsts);
4993
4994 getTargetStreamer().emitDirectiveCpRestore(StoreInsts, CpRestoreOffset);
4995 Parser.Lex(); // Consume the EndOfStatement.
4996 return false;
4997}
4998
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004999bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005000 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005001 unsigned FuncReg;
5002 unsigned Save;
5003 bool SaveIsReg = true;
5004
Matheus Almeida7e815762014-06-18 13:08:59 +00005005 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005006 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005007 if (ResTy == MatchOperand_NoMatch) {
5008 reportParseError("expected register containing function address");
5009 Parser.eatToEndOfStatement();
5010 return false;
5011 }
5012
5013 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5014 if (!FuncRegOpnd.isGPRAsmReg()) {
5015 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
5016 Parser.eatToEndOfStatement();
5017 return false;
5018 }
5019
5020 FuncReg = FuncRegOpnd.getGPR32Reg();
5021 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005022
Toma Tabacu65f10572014-09-16 15:00:52 +00005023 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005024 return true;
5025
Toma Tabacu13964452014-09-04 13:23:44 +00005026 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005027 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005028 const MCExpr *OffsetExpr;
5029 int64_t OffsetVal;
5030 SMLoc ExprLoc = getLexer().getLoc();
5031
5032 if (Parser.parseExpression(OffsetExpr) ||
5033 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5034 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005035 Parser.eatToEndOfStatement();
5036 return false;
5037 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005038
5039 Save = OffsetVal;
5040 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005041 } else {
5042 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5043 if (!SaveOpnd.isGPRAsmReg()) {
5044 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5045 Parser.eatToEndOfStatement();
5046 return false;
5047 }
5048 Save = SaveOpnd.getGPR32Reg();
5049 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005050
Toma Tabacu65f10572014-09-16 15:00:52 +00005051 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005052 return true;
5053
Toma Tabacu8874eac2015-02-18 13:46:53 +00005054 const MCExpr *Expr;
5055 if (Parser.parseExpression(Expr)) {
5056 reportParseError("expected expression");
5057 return false;
5058 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005059
Toma Tabacu8874eac2015-02-18 13:46:53 +00005060 if (Expr->getKind() != MCExpr::SymbolRef) {
5061 reportParseError("expected symbol");
5062 return false;
5063 }
5064 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5065
Daniel Sandersf173dda2015-09-22 10:50:09 +00005066 CpSaveLocation = Save;
5067 CpSaveLocationIsRegister = SaveIsReg;
5068
Toma Tabacu8874eac2015-02-18 13:46:53 +00005069 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5070 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005071 return false;
5072}
5073
Daniel Sandersf173dda2015-09-22 10:50:09 +00005074bool MipsAsmParser::parseDirectiveCPReturn() {
5075 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5076 CpSaveLocationIsRegister);
5077 return false;
5078}
5079
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005080bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005081 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005082 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5083 const AsmToken &Tok = Parser.getTok();
5084
5085 if (Tok.getString() == "2008") {
5086 Parser.Lex();
5087 getTargetStreamer().emitDirectiveNaN2008();
5088 return false;
5089 } else if (Tok.getString() == "legacy") {
5090 Parser.Lex();
5091 getTargetStreamer().emitDirectiveNaNLegacy();
5092 return false;
5093 }
5094 }
5095 // If we don't recognize the option passed to the .nan
5096 // directive (e.g. no option or unknown option), emit an error.
5097 reportParseError("invalid option in .nan directive");
5098 return false;
5099}
5100
Jack Carter0b744b32012-10-04 02:29:46 +00005101bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005102 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005103 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005104 const AsmToken &Tok = Parser.getTok();
5105
5106 if (Tok.getString() == "noat") {
5107 return parseSetNoAtDirective();
5108 } else if (Tok.getString() == "at") {
5109 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005110 } else if (Tok.getString() == "arch") {
5111 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005112 } else if (Tok.getString() == "fp") {
5113 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005114 } else if (Tok.getString() == "oddspreg") {
5115 return parseSetOddSPRegDirective();
5116 } else if (Tok.getString() == "nooddspreg") {
5117 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005118 } else if (Tok.getString() == "pop") {
5119 return parseSetPopDirective();
5120 } else if (Tok.getString() == "push") {
5121 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005122 } else if (Tok.getString() == "reorder") {
5123 return parseSetReorderDirective();
5124 } else if (Tok.getString() == "noreorder") {
5125 return parseSetNoReorderDirective();
5126 } else if (Tok.getString() == "macro") {
5127 return parseSetMacroDirective();
5128 } else if (Tok.getString() == "nomacro") {
5129 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005130 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005131 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005132 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005133 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005134 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005135 getTargetStreamer().emitDirectiveSetNoMicroMips();
5136 Parser.eatToEndOfStatement();
5137 return false;
5138 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005139 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005140 } else if (Tok.getString() == "mips0") {
5141 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005142 } else if (Tok.getString() == "mips1") {
5143 return parseSetFeature(Mips::FeatureMips1);
5144 } else if (Tok.getString() == "mips2") {
5145 return parseSetFeature(Mips::FeatureMips2);
5146 } else if (Tok.getString() == "mips3") {
5147 return parseSetFeature(Mips::FeatureMips3);
5148 } else if (Tok.getString() == "mips4") {
5149 return parseSetFeature(Mips::FeatureMips4);
5150 } else if (Tok.getString() == "mips5") {
5151 return parseSetFeature(Mips::FeatureMips5);
5152 } else if (Tok.getString() == "mips32") {
5153 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005154 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005155 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005156 } else if (Tok.getString() == "mips32r3") {
5157 return parseSetFeature(Mips::FeatureMips32r3);
5158 } else if (Tok.getString() == "mips32r5") {
5159 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005160 } else if (Tok.getString() == "mips32r6") {
5161 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005162 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005163 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005164 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005165 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005166 } else if (Tok.getString() == "mips64r3") {
5167 return parseSetFeature(Mips::FeatureMips64r3);
5168 } else if (Tok.getString() == "mips64r5") {
5169 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005170 } else if (Tok.getString() == "mips64r6") {
5171 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005172 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005173 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005174 } else if (Tok.getString() == "nodsp") {
5175 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005176 } else if (Tok.getString() == "msa") {
5177 return parseSetMsaDirective();
5178 } else if (Tok.getString() == "nomsa") {
5179 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005180 } else if (Tok.getString() == "softfloat") {
5181 return parseSetSoftFloatDirective();
5182 } else if (Tok.getString() == "hardfloat") {
5183 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005184 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005185 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005186 parseSetAssignment();
5187 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005188 }
Jack Carter07c818d2013-01-25 01:31:34 +00005189
Jack Carter0b744b32012-10-04 02:29:46 +00005190 return true;
5191}
5192
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005193/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005194/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005195bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005196 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005197 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5198 for (;;) {
5199 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005200 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005201 return true;
5202
5203 getParser().getStreamer().EmitValue(Value, Size);
5204
5205 if (getLexer().is(AsmToken::EndOfStatement))
5206 break;
5207
Jack Carter07c818d2013-01-25 01:31:34 +00005208 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005209 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005210 Parser.Lex();
5211 }
5212 }
5213
5214 Parser.Lex();
5215 return false;
5216}
5217
Vladimir Medic4c299852013-11-06 11:27:05 +00005218/// parseDirectiveGpWord
5219/// ::= .gpword local_sym
5220bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005221 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005222 const MCExpr *Value;
5223 // EmitGPRel32Value requires an expression, so we are using base class
5224 // method to evaluate the expression.
5225 if (getParser().parseExpression(Value))
5226 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005227 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005228
Vladimir Medice10c1122013-11-13 13:18:04 +00005229 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005230 return Error(getLexer().getLoc(),
5231 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005232 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005233 return false;
5234}
5235
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005236/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005237/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005238bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005239 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005240 const MCExpr *Value;
5241 // EmitGPRel64Value requires an expression, so we are using base class
5242 // method to evaluate the expression.
5243 if (getParser().parseExpression(Value))
5244 return true;
5245 getParser().getStreamer().EmitGPRel64Value(Value);
5246
5247 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005248 return Error(getLexer().getLoc(),
5249 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005250 Parser.Lex(); // Eat EndOfStatement token.
5251 return false;
5252}
5253
Jack Carter0cd3c192014-01-06 23:27:31 +00005254bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005255 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005256 // Get the option token.
5257 AsmToken Tok = Parser.getTok();
5258 // At the moment only identifiers are supported.
5259 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005260 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005261 Parser.eatToEndOfStatement();
5262 return false;
5263 }
5264
5265 StringRef Option = Tok.getIdentifier();
5266
5267 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005268 // MipsAsmParser needs to know if the current PIC mode changes.
5269 IsPicEnabled = false;
5270
Jack Carter0cd3c192014-01-06 23:27:31 +00005271 getTargetStreamer().emitDirectiveOptionPic0();
5272 Parser.Lex();
5273 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5274 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005275 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005276 Parser.eatToEndOfStatement();
5277 }
5278 return false;
5279 }
5280
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005281 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005282 // MipsAsmParser needs to know if the current PIC mode changes.
5283 IsPicEnabled = true;
5284
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005285 getTargetStreamer().emitDirectiveOptionPic2();
5286 Parser.Lex();
5287 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5288 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005289 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005290 Parser.eatToEndOfStatement();
5291 }
5292 return false;
5293 }
5294
Jack Carter0cd3c192014-01-06 23:27:31 +00005295 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005296 Warning(Parser.getTok().getLoc(),
5297 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005298 Parser.eatToEndOfStatement();
5299 return false;
5300}
5301
Toma Tabacu9ca50962015-04-16 09:53:47 +00005302/// parseInsnDirective
5303/// ::= .insn
5304bool MipsAsmParser::parseInsnDirective() {
5305 // If this is not the end of the statement, report an error.
5306 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5307 reportParseError("unexpected token, expected end of statement");
5308 return false;
5309 }
5310
5311 // The actual label marking happens in
5312 // MipsELFStreamer::createPendingLabelRelocs().
5313 getTargetStreamer().emitDirectiveInsn();
5314
5315 getParser().Lex(); // Eat EndOfStatement token.
5316 return false;
5317}
5318
Daniel Sanders7e527422014-07-10 13:38:23 +00005319/// parseDirectiveModule
5320/// ::= .module oddspreg
5321/// ::= .module nooddspreg
5322/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005323/// ::= .module softfloat
5324/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005325bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005326 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005327 MCAsmLexer &Lexer = getLexer();
5328 SMLoc L = Lexer.getLoc();
5329
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005330 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005331 // TODO : get a better message.
5332 reportParseError(".module directive must appear before any code");
5333 return false;
5334 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005335
Toma Tabacuc405c822015-01-23 10:40:19 +00005336 StringRef Option;
5337 if (Parser.parseIdentifier(Option)) {
5338 reportParseError("expected .module option identifier");
5339 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005340 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005341
Toma Tabacuc405c822015-01-23 10:40:19 +00005342 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005343 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005344
Toma Tabacu3c499582015-06-25 10:56:57 +00005345 // Synchronize the abiflags information with the FeatureBits information we
5346 // changed above.
5347 getTargetStreamer().updateABIInfo(*this);
5348
5349 // If printing assembly, use the recently updated abiflags information.
5350 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5351 // emitted at the end).
5352 getTargetStreamer().emitDirectiveModuleOddSPReg();
5353
Toma Tabacuc405c822015-01-23 10:40:19 +00005354 // If this is not the end of the statement, report an error.
5355 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5356 reportParseError("unexpected token, expected end of statement");
5357 return false;
5358 }
5359
5360 return false; // parseDirectiveModule has finished successfully.
5361 } else if (Option == "nooddspreg") {
5362 if (!isABI_O32()) {
5363 Error(L, "'.module nooddspreg' requires the O32 ABI");
5364 return false;
5365 }
5366
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005367 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005368
Toma Tabacu3c499582015-06-25 10:56:57 +00005369 // Synchronize the abiflags information with the FeatureBits information we
5370 // changed above.
5371 getTargetStreamer().updateABIInfo(*this);
5372
5373 // If printing assembly, use the recently updated abiflags information.
5374 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5375 // emitted at the end).
5376 getTargetStreamer().emitDirectiveModuleOddSPReg();
5377
Toma Tabacuc405c822015-01-23 10:40:19 +00005378 // If this is not the end of the statement, report an error.
5379 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5380 reportParseError("unexpected token, expected end of statement");
5381 return false;
5382 }
5383
5384 return false; // parseDirectiveModule has finished successfully.
5385 } else if (Option == "fp") {
5386 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005387 } else if (Option == "softfloat") {
5388 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5389
5390 // Synchronize the ABI Flags information with the FeatureBits information we
5391 // updated above.
5392 getTargetStreamer().updateABIInfo(*this);
5393
5394 // If printing assembly, use the recently updated ABI Flags information.
5395 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5396 // emitted later).
5397 getTargetStreamer().emitDirectiveModuleSoftFloat();
5398
5399 // If this is not the end of the statement, report an error.
5400 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5401 reportParseError("unexpected token, expected end of statement");
5402 return false;
5403 }
5404
5405 return false; // parseDirectiveModule has finished successfully.
5406 } else if (Option == "hardfloat") {
5407 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5408
5409 // Synchronize the ABI Flags information with the FeatureBits information we
5410 // updated above.
5411 getTargetStreamer().updateABIInfo(*this);
5412
5413 // If printing assembly, use the recently updated ABI Flags information.
5414 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5415 // emitted later).
5416 getTargetStreamer().emitDirectiveModuleHardFloat();
5417
5418 // If this is not the end of the statement, report an error.
5419 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5420 reportParseError("unexpected token, expected end of statement");
5421 return false;
5422 }
5423
5424 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005425 } else {
5426 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5427 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005428}
5429
5430/// parseDirectiveModuleFP
5431/// ::= =32
5432/// ::= =xx
5433/// ::= =64
5434bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005435 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005436 MCAsmLexer &Lexer = getLexer();
5437
5438 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005439 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005440 return false;
5441 }
5442 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005443
Daniel Sanders7e527422014-07-10 13:38:23 +00005444 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005445 if (!parseFpABIValue(FpABI, ".module"))
5446 return false;
5447
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005448 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005449 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005450 return false;
5451 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005452
Toma Tabacua64e5402015-06-25 12:44:38 +00005453 // Synchronize the abiflags information with the FeatureBits information we
5454 // changed above.
5455 getTargetStreamer().updateABIInfo(*this);
5456
5457 // If printing assembly, use the recently updated abiflags information.
5458 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5459 // emitted at the end).
5460 getTargetStreamer().emitDirectiveModuleFP();
5461
Daniel Sanders7e527422014-07-10 13:38:23 +00005462 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005463 return false;
5464}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005465
Daniel Sanders7e527422014-07-10 13:38:23 +00005466bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005467 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005468 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005469 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005470 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005471
5472 if (Lexer.is(AsmToken::Identifier)) {
5473 StringRef Value = Parser.getTok().getString();
5474 Parser.Lex();
5475
5476 if (Value != "xx") {
5477 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5478 return false;
5479 }
5480
5481 if (!isABI_O32()) {
5482 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5483 return false;
5484 }
5485
Daniel Sanders7e527422014-07-10 13:38:23 +00005486 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005487 if (ModuleLevelOptions) {
5488 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5489 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5490 } else {
5491 setFeatureBits(Mips::FeatureFPXX, "fpxx");
5492 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5493 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005494 return true;
5495 }
5496
5497 if (Lexer.is(AsmToken::Integer)) {
5498 unsigned Value = Parser.getTok().getIntVal();
5499 Parser.Lex();
5500
5501 if (Value != 32 && Value != 64) {
5502 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5503 return false;
5504 }
5505
5506 if (Value == 32) {
5507 if (!isABI_O32()) {
5508 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
5509 return false;
5510 }
5511
Daniel Sanders7e527422014-07-10 13:38:23 +00005512 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005513 if (ModuleLevelOptions) {
5514 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5515 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5516 } else {
5517 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5518 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5519 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005520 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00005521 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005522 if (ModuleLevelOptions) {
5523 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5524 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5525 } else {
5526 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5527 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
5528 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005529 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005530
Daniel Sanders7e527422014-07-10 13:38:23 +00005531 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005532 }
5533
5534 return false;
5535}
5536
Jack Carter0b744b32012-10-04 02:29:46 +00005537bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005538 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005539 StringRef IDVal = DirectiveID.getString();
5540
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005541 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005542 return parseDirectiveCpLoad(DirectiveID.getLoc());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005543 if (IDVal == ".cprestore")
5544 return parseDirectiveCpRestore(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00005545 if (IDVal == ".dword") {
5546 parseDataDirective(8, DirectiveID.getLoc());
5547 return false;
5548 }
Jack Carterd0bd6422013-04-18 00:41:53 +00005549 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005550 StringRef SymbolName;
5551
5552 if (Parser.parseIdentifier(SymbolName)) {
5553 reportParseError("expected identifier after .ent");
5554 return false;
5555 }
5556
5557 // There's an undocumented extension that allows an integer to
5558 // follow the name of the procedure which AFAICS is ignored by GAS.
5559 // Example: .ent foo,2
5560 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5561 if (getLexer().isNot(AsmToken::Comma)) {
5562 // Even though we accept this undocumented extension for compatibility
5563 // reasons, the additional integer argument does not actually change
5564 // the behaviour of the '.ent' directive, so we would like to discourage
5565 // its use. We do this by not referring to the extended version in
5566 // error messages which are not directly related to its use.
5567 reportParseError("unexpected token, expected end of statement");
5568 return false;
5569 }
5570 Parser.Lex(); // Eat the comma.
5571 const MCExpr *DummyNumber;
5572 int64_t DummyNumberVal;
5573 // If the user was explicitly trying to use the extended version,
5574 // we still give helpful extension-related error messages.
5575 if (Parser.parseExpression(DummyNumber)) {
5576 reportParseError("expected number after comma");
5577 return false;
5578 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00005579 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005580 reportParseError("expected an absolute expression after comma");
5581 return false;
5582 }
5583 }
5584
5585 // If this is not the end of the statement, report an error.
5586 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5587 reportParseError("unexpected token, expected end of statement");
5588 return false;
5589 }
5590
Jim Grosbach6f482002015-05-18 18:43:14 +00005591 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005592
5593 getTargetStreamer().emitDirectiveEnt(*Sym);
5594 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005595 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005596 return false;
5597 }
5598
Jack Carter07c818d2013-01-25 01:31:34 +00005599 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005600 StringRef SymbolName;
5601
5602 if (Parser.parseIdentifier(SymbolName)) {
5603 reportParseError("expected identifier after .end");
5604 return false;
5605 }
5606
5607 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5608 reportParseError("unexpected token, expected end of statement");
5609 return false;
5610 }
5611
5612 if (CurrentFn == nullptr) {
5613 reportParseError(".end used without .ent");
5614 return false;
5615 }
5616
5617 if ((SymbolName != CurrentFn->getName())) {
5618 reportParseError(".end symbol does not match .ent symbol");
5619 return false;
5620 }
5621
5622 getTargetStreamer().emitDirectiveEnd(SymbolName);
5623 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005624 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005625 return false;
5626 }
5627
Jack Carter07c818d2013-01-25 01:31:34 +00005628 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005629 // .frame $stack_reg, frame_size_in_bytes, $return_reg
5630 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005631 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005632 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5633 reportParseError("expected stack register");
5634 return false;
5635 }
5636
5637 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5638 if (!StackRegOpnd.isGPRAsmReg()) {
5639 reportParseError(StackRegOpnd.getStartLoc(),
5640 "expected general purpose register");
5641 return false;
5642 }
5643 unsigned StackReg = StackRegOpnd.getGPR32Reg();
5644
5645 if (Parser.getTok().is(AsmToken::Comma))
5646 Parser.Lex();
5647 else {
5648 reportParseError("unexpected token, expected comma");
5649 return false;
5650 }
5651
5652 // Parse the frame size.
5653 const MCExpr *FrameSize;
5654 int64_t FrameSizeVal;
5655
5656 if (Parser.parseExpression(FrameSize)) {
5657 reportParseError("expected frame size value");
5658 return false;
5659 }
5660
Jim Grosbach13760bd2015-05-30 01:25:56 +00005661 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005662 reportParseError("frame size not an absolute expression");
5663 return false;
5664 }
5665
5666 if (Parser.getTok().is(AsmToken::Comma))
5667 Parser.Lex();
5668 else {
5669 reportParseError("unexpected token, expected comma");
5670 return false;
5671 }
5672
5673 // Parse the return register.
5674 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00005675 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005676 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5677 reportParseError("expected return register");
5678 return false;
5679 }
5680
5681 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5682 if (!ReturnRegOpnd.isGPRAsmReg()) {
5683 reportParseError(ReturnRegOpnd.getStartLoc(),
5684 "expected general purpose register");
5685 return false;
5686 }
5687
5688 // If this is not the end of the statement, report an error.
5689 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5690 reportParseError("unexpected token, expected end of statement");
5691 return false;
5692 }
5693
5694 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
5695 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005696 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005697 return false;
5698 }
5699
Jack Carter07c818d2013-01-25 01:31:34 +00005700 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00005701 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00005702 }
5703
Daniel Sandersd97a6342014-08-13 10:07:34 +00005704 if (IDVal == ".mask" || IDVal == ".fmask") {
5705 // .mask bitmask, frame_offset
5706 // bitmask: One bit for each register used.
5707 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
5708 // first register is expected to be saved.
5709 // Examples:
5710 // .mask 0x80000000, -4
5711 // .fmask 0x80000000, -4
5712 //
Jack Carterbe332172012-09-07 00:48:02 +00005713
Daniel Sandersd97a6342014-08-13 10:07:34 +00005714 // Parse the bitmask
5715 const MCExpr *BitMask;
5716 int64_t BitMaskVal;
5717
5718 if (Parser.parseExpression(BitMask)) {
5719 reportParseError("expected bitmask value");
5720 return false;
5721 }
5722
Jim Grosbach13760bd2015-05-30 01:25:56 +00005723 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005724 reportParseError("bitmask not an absolute expression");
5725 return false;
5726 }
5727
5728 if (Parser.getTok().is(AsmToken::Comma))
5729 Parser.Lex();
5730 else {
5731 reportParseError("unexpected token, expected comma");
5732 return false;
5733 }
5734
5735 // Parse the frame_offset
5736 const MCExpr *FrameOffset;
5737 int64_t FrameOffsetVal;
5738
5739 if (Parser.parseExpression(FrameOffset)) {
5740 reportParseError("expected frame offset value");
5741 return false;
5742 }
5743
Jim Grosbach13760bd2015-05-30 01:25:56 +00005744 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005745 reportParseError("frame offset not an absolute expression");
5746 return false;
5747 }
5748
5749 // If this is not the end of the statement, report an error.
5750 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5751 reportParseError("unexpected token, expected end of statement");
5752 return false;
5753 }
5754
5755 if (IDVal == ".mask")
5756 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
5757 else
5758 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00005759 return false;
5760 }
5761
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005762 if (IDVal == ".nan")
5763 return parseDirectiveNaN();
5764
Jack Carter07c818d2013-01-25 01:31:34 +00005765 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005766 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00005767 return false;
5768 }
5769
Rafael Espindolab59fb732014-03-28 18:50:26 +00005770 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005771 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005772 return false;
5773 }
5774
Jack Carter07c818d2013-01-25 01:31:34 +00005775 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005776 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00005777 return false;
5778 }
5779
Jack Carter0cd3c192014-01-06 23:27:31 +00005780 if (IDVal == ".option")
5781 return parseDirectiveOption();
5782
5783 if (IDVal == ".abicalls") {
5784 getTargetStreamer().emitDirectiveAbiCalls();
5785 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005786 Error(Parser.getTok().getLoc(),
5787 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005788 // Clear line
5789 Parser.eatToEndOfStatement();
5790 }
5791 return false;
5792 }
5793
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005794 if (IDVal == ".cpsetup")
5795 return parseDirectiveCPSetup();
5796
Daniel Sandersf173dda2015-09-22 10:50:09 +00005797 if (IDVal == ".cpreturn")
5798 return parseDirectiveCPReturn();
5799
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005800 if (IDVal == ".module")
5801 return parseDirectiveModule();
5802
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005803 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
5804 return parseInternalDirectiveReallowModule();
5805
Toma Tabacu9ca50962015-04-16 09:53:47 +00005806 if (IDVal == ".insn")
5807 return parseInsnDirective();
5808
Rafael Espindola870c4e92012-01-11 03:56:41 +00005809 return true;
5810}
5811
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005812bool MipsAsmParser::parseInternalDirectiveReallowModule() {
5813 // If this is not the end of the statement, report an error.
5814 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5815 reportParseError("unexpected token, expected end of statement");
5816 return false;
5817 }
5818
5819 getTargetStreamer().reallowModuleDirective();
5820
5821 getParser().Lex(); // Eat EndOfStatement token.
5822 return false;
5823}
5824
Rafael Espindola870c4e92012-01-11 03:56:41 +00005825extern "C" void LLVMInitializeMipsAsmParser() {
5826 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
5827 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
5828 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
5829 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
5830}
Jack Carterb4dbc172012-09-05 23:34:03 +00005831
5832#define GET_REGISTER_MATCHER
5833#define GET_MATCHER_IMPLEMENTATION
5834#include "MipsGenAsmMatcher.inc"