blob: 551d7643e14d3c8e930474dd76beb9bca830c18e [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Eric Christophera5762812015-01-26 17:33:46 +000010#include "MCTargetDesc/MipsABIInfo.h"
Petar Jovanovica5da5882014-02-04 18:41:57 +000011#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000012#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000013#include "MipsRegisterInfo.h"
Daniel Sandersa6994442015-08-18 12:33:54 +000014#include "MipsTargetObjectFile.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000015#include "MipsTargetStreamer.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000016#include "llvm/ADT/APInt.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000017#include "llvm/ADT/SmallVector.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000018#include "llvm/ADT/StringSwitch.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000019#include "llvm/MC/MCContext.h"
20#include "llvm/MC/MCExpr.h"
21#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000022#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000023#include "llvm/MC/MCParser/MCAsmLexer.h"
24#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000025#include "llvm/MC/MCStreamer.h"
26#include "llvm/MC/MCSubtargetInfo.h"
27#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000028#include "llvm/MC/MCTargetAsmParser.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000029#include "llvm/Support/Debug.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000030#include "llvm/Support/MathExtras.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000031#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000032#include "llvm/Support/TargetRegistry.h"
Benjamin Kramer799003b2015-03-23 19:32:43 +000033#include "llvm/Support/raw_ostream.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000034#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000035
36using namespace llvm;
37
Chandler Carruthe96dd892014-04-21 22:55:11 +000038#define DEBUG_TYPE "mips-asm-parser"
39
Joey Gouly0e76fa72013-09-12 10:28:05 +000040namespace llvm {
41class MCInstrInfo;
42}
43
Rafael Espindola870c4e92012-01-11 03:56:41 +000044namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000045class MipsAssemblerOptions {
46public:
Toma Tabacu465acfd2015-06-09 13:33:26 +000047 MipsAssemblerOptions(const FeatureBitset &Features_) :
Toma Tabacu9db22db2014-09-09 10:15:38 +000048 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000049
Toma Tabacu9db22db2014-09-09 10:15:38 +000050 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000051 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000052 Reorder = Opts->isReorder();
53 Macro = Opts->isMacro();
54 Features = Opts->getFeatures();
55 }
56
Toma Tabacub19cf202015-04-27 13:12:59 +000057 unsigned getATRegIndex() const { return ATReg; }
58 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000059 if (Reg > 31)
60 return false;
61
62 ATReg = Reg;
63 return true;
64 }
Jack Carter0b744b32012-10-04 02:29:46 +000065
Toma Tabacu9db22db2014-09-09 10:15:38 +000066 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000067 void setReorder() { Reorder = true; }
68 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000069
Toma Tabacu9db22db2014-09-09 10:15:38 +000070 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000071 void setMacro() { Macro = true; }
72 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000073
Toma Tabacu465acfd2015-06-09 13:33:26 +000074 const FeatureBitset &getFeatures() const { return Features; }
75 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000076
Daniel Sandersf0df2212014-08-04 12:20:00 +000077 // Set of features that are either architecture features or referenced
78 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
79 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
80 // The reason we need this mask is explained in the selectArch function.
81 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +000082 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +000083
Jack Carter0b744b32012-10-04 02:29:46 +000084private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000085 unsigned ATReg;
86 bool Reorder;
87 bool Macro;
Toma Tabacu465acfd2015-06-09 13:33:26 +000088 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +000089};
90}
91
Michael Kupersteindb0712f2015-05-26 10:47:10 +000092const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
93 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
94 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
95 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
96 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
97 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
98 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
99 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
100 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
101};
102
Jack Carter0b744b32012-10-04 02:29:46 +0000103namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +0000104class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000105 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000106 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000107 return static_cast<MipsTargetStreamer &>(TS);
108 }
109
Jack Carterb4dbc172012-09-05 23:34:03 +0000110 MCSubtargetInfo &STI;
Eric Christophera5762812015-01-26 17:33:46 +0000111 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000112 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000113 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
114 // nullptr, which indicates that no function is currently
115 // selected. This usually happens after an '.end func'
116 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000117 bool IsLittleEndian;
Daniel Sandersa6994442015-08-18 12:33:54 +0000118 bool IsPicEnabled;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000119 bool IsCpRestoreSet;
120 int CpRestoreOffset;
Daniel Sandersf173dda2015-09-22 10:50:09 +0000121 unsigned CpSaveLocation;
122 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
123 bool CpSaveLocationIsRegister;
Jack Carter0b744b32012-10-04 02:29:46 +0000124
Daniel Sandersef638fe2014-10-03 15:37:37 +0000125 // Print a warning along with its fix-it message at the given range.
126 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
127 SMRange Range, bool ShowColors = true);
128
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000129#define GET_ASSEMBLER_HEADER
130#include "MipsGenAsmMatcher.inc"
131
Matheus Almeida595fcab2014-06-11 15:05:56 +0000132 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
133
Chad Rosier49963552012-10-13 00:26:04 +0000134 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000135 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000136 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000137 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000138
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000139 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000140 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000141
Toma Tabacu13964452014-09-04 13:23:44 +0000142 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000143
Toma Tabacu13964452014-09-04 13:23:44 +0000144 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000145
David Blaikie960ea3f2014-06-08 16:18:35 +0000146 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
147 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000148
Craig Topper56c590a2014-04-29 07:58:02 +0000149 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000150
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000151 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
152 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000153 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000154 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000155 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
156 SMLoc S);
157 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
158 OperandMatchResultTy parseImm(OperandVector &Operands);
159 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
160 OperandMatchResultTy parseInvNum(OperandVector &Operands);
161 OperandMatchResultTy parseLSAImm(OperandVector &Operands);
162 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
163 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
164 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000165
David Blaikie960ea3f2014-06-08 16:18:35 +0000166 bool searchSymbolAlias(OperandVector &Operands);
167
Toma Tabacu13964452014-09-04 13:23:44 +0000168 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000169
Jack Carter30a59822012-10-04 04:03:53 +0000170 bool needsExpansion(MCInst &Inst);
171
Matheus Almeida3813d572014-06-19 14:39:14 +0000172 // Expands assembly pseudo instructions.
173 // Returns false on success, true otherwise.
174 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000175 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000176
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000177 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
178 SmallVectorImpl<MCInst> &Instructions);
179
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000180 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000181 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000182 SmallVectorImpl<MCInst> &Instructions);
183
Toma Tabacuf712ede2015-06-17 14:31:51 +0000184 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
185 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
186 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacu674825c2015-06-16 12:16:24 +0000187
Toma Tabacu00e98672015-05-01 12:19:27 +0000188 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000189 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000190
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000191 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
192 const MCOperand &Offset, bool Is32BitAddress,
193 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000194
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000195 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
196 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000197
Jack Carter9e65aa32013-03-22 00:05:30 +0000198 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000199 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
200 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000201
202 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
203 SmallVectorImpl<MCInst> &Instructions);
204
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000205 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
206 SmallVectorImpl<MCInst> &Instructions);
207
Toma Tabacue1e460d2015-06-11 10:36:10 +0000208 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc,
209 SmallVectorImpl<MCInst> &Instructions);
210
Toma Tabacu1a108322015-06-17 13:20:24 +0000211 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc,
212 SmallVectorImpl<MCInst> &Instructions);
213
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000214 bool expandDiv(MCInst &Inst, SMLoc IDLoc,
215 SmallVectorImpl<MCInst> &Instructions, const bool IsMips64,
216 const bool Signed);
217
Toma Tabacud88d79c2015-06-23 14:39:42 +0000218 bool expandUlhu(MCInst &Inst, SMLoc IDLoc,
219 SmallVectorImpl<MCInst> &Instructions);
220
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000221 bool expandUlw(MCInst &Inst, SMLoc IDLoc,
222 SmallVectorImpl<MCInst> &Instructions);
223
Toma Tabacu234482a2015-03-16 12:03:39 +0000224 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
225 SmallVectorImpl<MCInst> &Instructions);
226
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000227 void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +0000228 bool Is64Bit, SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000229
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000230 void createCpRestoreMemOp(bool IsLoad, int StackOffset, SMLoc IDLoc,
231 SmallVectorImpl<MCInst> &Instructions);
232
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000233 bool reportParseError(Twine ErrorMsg);
234 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000235
Jack Carterb5cf5902013-04-17 00:18:04 +0000236 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000237 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000238
Vladimir Medic4c299852013-11-06 11:27:05 +0000239 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000240
241 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000242 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000243 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000244 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000245 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000246 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000247 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000248 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000249 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000250 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000251 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000252 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000253 bool parseInsnDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000254
255 bool parseSetAtDirective();
256 bool parseSetNoAtDirective();
257 bool parseSetMacroDirective();
258 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000259 bool parseSetMsaDirective();
260 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000261 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000262 bool parseSetReorderDirective();
263 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000264 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000265 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000266 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000267 bool parseSetOddSPRegDirective();
268 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000269 bool parseSetPopDirective();
270 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000271 bool parseSetSoftFloatDirective();
272 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000273
Jack Carterd76b2372013-03-21 21:44:16 +0000274 bool parseSetAssignment();
275
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000276 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000277 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000278 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000279 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000280 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000281 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
282 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000283
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000284 bool parseInternalDirectiveReallowModule();
285
Jack Carterdc1e35d2012-09-06 20:00:02 +0000286 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000287
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000288 bool eatComma(StringRef ErrorStr);
289
Jack Carter1ac53222013-02-20 23:11:17 +0000290 int matchCPURegisterName(StringRef Symbol);
291
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000292 int matchHWRegsRegisterName(StringRef Symbol);
293
Jack Carter873c7242013-01-12 01:03:14 +0000294 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000295
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000296 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000297
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000298 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000299
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000300 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000301
Jack Carter5dc8ac92013-09-25 23:50:44 +0000302 int matchMSA128RegisterName(StringRef Name);
303
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000304 int matchMSA128CtrlRegisterName(StringRef Name);
305
Jack Carterd0bd6422013-04-18 00:41:53 +0000306 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000307
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000308 unsigned getGPR(int RegNo);
309
Toma Tabacu89a712b2015-04-15 10:48:56 +0000310 /// Returns the internal register number for the current AT. Also checks if
311 /// the current AT is unavailable (set to $0) and gives an error if it is.
312 /// This should be used in pseudo-instruction expansions which need AT.
313 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000314
315 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000316 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000317
318 // Helper function that checks if the value of a vector index is within the
319 // boundaries of accepted values for each RegisterKind
320 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
321 bool validateMSAIndex(int Val, int RegKind);
322
Daniel Sandersf0df2212014-08-04 12:20:00 +0000323 // Selects a new architecture by updating the FeatureBits with the necessary
324 // info including implied dependencies.
325 // Internally, it clears all the feature bits related to *any* architecture
326 // and selects the new one using the ToggleFeature functionality of the
327 // MCSubtargetInfo object that handles implied dependencies. The reason we
328 // clear all the arch related bits manually is because ToggleFeature only
329 // clears the features that imply the feature being cleared and not the
330 // features implied by the feature being cleared. This is easier to see
331 // with an example:
332 // --------------------------------------------------
333 // | Feature | Implies |
334 // | -------------------------------------------------|
335 // | FeatureMips1 | None |
336 // | FeatureMips2 | FeatureMips1 |
337 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
338 // | FeatureMips4 | FeatureMips3 |
339 // | ... | |
340 // --------------------------------------------------
341 //
342 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
343 // FeatureMipsGP64 | FeatureMips1)
344 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
345 void selectArch(StringRef ArchFeature) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000346 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000347 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
348 STI.setFeatureBits(FeatureBits);
349 setAvailableFeatures(
350 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000351 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000352 }
353
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000354 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000355 if (!(STI.getFeatureBits()[Feature])) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000356 setAvailableFeatures(
357 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000358 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000359 }
360 }
361
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000362 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000363 if (STI.getFeatureBits()[Feature]) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000364 setAvailableFeatures(
365 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000366 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000367 }
368 }
369
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000370 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
371 setFeatureBits(Feature, FeatureString);
372 AssemblerOptions.front()->setFeatures(STI.getFeatureBits());
373 }
374
375 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
376 clearFeatureBits(Feature, FeatureString);
377 AssemblerOptions.front()->setFeatures(STI.getFeatureBits());
378 }
379
Rafael Espindola870c4e92012-01-11 03:56:41 +0000380public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000381 enum MipsMatchResultTy {
382 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
383#define GET_OPERAND_DIAGNOSTIC_TYPES
384#include "MipsGenAsmMatcher.inc"
385#undef GET_OPERAND_DIAGNOSTIC_TYPES
386
387 };
388
Joey Gouly0e76fa72013-09-12 10:28:05 +0000389 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000390 const MCInstrInfo &MII, const MCTargetOptions &Options)
Colin LeMahieufe2c8b82015-07-27 21:56:53 +0000391 : MCTargetAsmParser(Options), STI(sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000392 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
393 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000394 MCAsmParserExtension::Initialize(parser);
395
Toma Tabacu11e14a92015-04-21 11:50:52 +0000396 parser.addAliasForDirective(".asciiz", ".asciz");
397
Jack Carterb4dbc172012-09-05 23:34:03 +0000398 // Initialize the set of available features.
399 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000400
Toma Tabacu9db22db2014-09-09 10:15:38 +0000401 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000402 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000403 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000404
Toma Tabacu9db22db2014-09-09 10:15:38 +0000405 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000406 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000407 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000408
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000409 getTargetStreamer().updateABIInfo(*this);
410
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000411 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000412 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000413
414 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000415
Daniel Sandersa6994442015-08-18 12:33:54 +0000416 IsPicEnabled =
417 (getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_);
418
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000419 IsCpRestoreSet = false;
420 CpRestoreOffset = -1;
421
Daniel Sanders50f17232015-09-15 16:17:27 +0000422 Triple TheTriple(sti.getTargetTriple());
423 if ((TheTriple.getArch() == Triple::mips) ||
424 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000425 IsLittleEndian = false;
426 else
427 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000428 }
429
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000430 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
431 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
432
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000433 bool isGP64bit() const { return STI.getFeatureBits()[Mips::FeatureGP64Bit]; }
434 bool isFP64bit() const { return STI.getFeatureBits()[Mips::FeatureFP64Bit]; }
Eric Christophera5762812015-01-26 17:33:46 +0000435 const MipsABIInfo &getABI() const { return ABI; }
436 bool isABI_N32() const { return ABI.IsN32(); }
437 bool isABI_N64() const { return ABI.IsN64(); }
438 bool isABI_O32() const { return ABI.IsO32(); }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000439 bool isABI_FPXX() const { return STI.getFeatureBits()[Mips::FeatureFPXX]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000440
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000441 bool useOddSPReg() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000442 return !(STI.getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000443 }
444
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000445 bool inMicroMipsMode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000446 return STI.getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000447 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000448 bool hasMips1() const { return STI.getFeatureBits()[Mips::FeatureMips1]; }
449 bool hasMips2() const { return STI.getFeatureBits()[Mips::FeatureMips2]; }
450 bool hasMips3() const { return STI.getFeatureBits()[Mips::FeatureMips3]; }
451 bool hasMips4() const { return STI.getFeatureBits()[Mips::FeatureMips4]; }
452 bool hasMips5() const { return STI.getFeatureBits()[Mips::FeatureMips5]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000453 bool hasMips32() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000454 return STI.getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000455 }
456 bool hasMips64() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000457 return STI.getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000458 }
459 bool hasMips32r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000460 return STI.getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000461 }
462 bool hasMips64r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000463 return STI.getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000464 }
Daniel Sanders17793142015-02-18 16:24:50 +0000465 bool hasMips32r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000466 return (STI.getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000467 }
468 bool hasMips64r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000469 return (STI.getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000470 }
471 bool hasMips32r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000472 return (STI.getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000473 }
474 bool hasMips64r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000475 return (STI.getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000476 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000477 bool hasMips32r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000478 return STI.getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000479 }
480 bool hasMips64r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000481 return STI.getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000482 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000483
484 bool hasDSP() const { return STI.getFeatureBits()[Mips::FeatureDSP]; }
485 bool hasDSPR2() const { return STI.getFeatureBits()[Mips::FeatureDSPR2]; }
486 bool hasMSA() const { return STI.getFeatureBits()[Mips::FeatureMSA]; }
Kai Nackee0245392015-01-27 19:11:28 +0000487 bool hasCnMips() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000488 return (STI.getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000489 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000490
Daniel Sandersa6994442015-08-18 12:33:54 +0000491 bool inPicMode() {
492 return IsPicEnabled;
493 }
494
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000495 bool inMips16Mode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000496 return STI.getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000497 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000498
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000499 bool useTraps() const {
500 return STI.getFeatureBits()[Mips::FeatureUseTCCInDIV];
501 }
502
Eric Christophere8ae3e32015-05-07 23:10:21 +0000503 bool useSoftFloat() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000504 return STI.getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000505 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000506
Toma Tabacud9d344b2015-04-27 14:05:04 +0000507 /// Warn if RegIndex is the same as the current AT.
508 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000509
510 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000511
512 bool isLittle() const { return IsLittleEndian; }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000513};
514}
515
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000516namespace {
517
518/// MipsOperand - Instances of this class represent a parsed Mips machine
519/// instruction.
520class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000521public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000522 /// Broad categories of register classes
523 /// The exact class is finalized by the render method.
524 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000525 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000526 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000527 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000528 RegKind_FCC = 4, /// FCC
529 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
530 RegKind_MSACtrl = 16, /// MSA control registers
531 RegKind_COP2 = 32, /// COP2
532 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
533 /// context).
534 RegKind_CCR = 128, /// CCR
535 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000536 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000537 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000538 /// Potentially any (e.g. $1)
539 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
540 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000541 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000542 };
543
544private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000545 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000546 k_Immediate, /// An immediate (possibly involving symbol references)
547 k_Memory, /// Base + Offset Memory Address
548 k_PhysRegister, /// A physical register from the Mips namespace
549 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000550 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000551 k_RegList, /// A physical register list
552 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000553 } Kind;
554
David Blaikie960ea3f2014-06-08 16:18:35 +0000555public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000556 MipsOperand(KindTy K, MipsAsmParser &Parser)
557 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
558
David Blaikie960ea3f2014-06-08 16:18:35 +0000559private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000560 /// For diagnostics, and checking the assembler temporary
561 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000562
Eric Christopher8996c5d2013-03-15 00:42:55 +0000563 struct Token {
564 const char *Data;
565 unsigned Length;
566 };
567
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000568 struct PhysRegOp {
569 unsigned Num; /// Register Number
570 };
571
572 struct RegIdxOp {
573 unsigned Index; /// Index into the register class
574 RegKind Kind; /// Bitfield of the kinds it could possibly be
575 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000576 };
577
578 struct ImmOp {
579 const MCExpr *Val;
580 };
581
582 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000583 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000584 const MCExpr *Off;
585 };
586
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000587 struct RegListOp {
588 SmallVector<unsigned, 10> *List;
589 };
590
Jack Carterb4dbc172012-09-05 23:34:03 +0000591 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000592 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000593 struct PhysRegOp PhysReg;
594 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000595 struct ImmOp Imm;
596 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000597 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000598 };
599
600 SMLoc StartLoc, EndLoc;
601
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000602 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000603 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
604 const MCRegisterInfo *RegInfo,
605 SMLoc S, SMLoc E,
606 MipsAsmParser &Parser) {
607 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000608 Op->RegIdx.Index = Index;
609 Op->RegIdx.RegInfo = RegInfo;
610 Op->RegIdx.Kind = RegKind;
611 Op->StartLoc = S;
612 Op->EndLoc = E;
613 return Op;
614 }
615
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000616public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000617 /// Coerce the register to GPR32 and return the real register for the current
618 /// target.
619 unsigned getGPR32Reg() const {
620 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000621 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000622 unsigned ClassID = Mips::GPR32RegClassID;
623 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000624 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000625
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000626 /// Coerce the register to GPR32 and return the real register for the current
627 /// target.
628 unsigned getGPRMM16Reg() const {
629 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
630 unsigned ClassID = Mips::GPR32RegClassID;
631 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
632 }
633
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000634 /// Coerce the register to GPR64 and return the real register for the current
635 /// target.
636 unsigned getGPR64Reg() const {
637 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
638 unsigned ClassID = Mips::GPR64RegClassID;
639 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000640 }
641
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000642private:
643 /// Coerce the register to AFGR64 and return the real register for the current
644 /// target.
645 unsigned getAFGR64Reg() const {
646 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
647 if (RegIdx.Index % 2 != 0)
648 AsmParser.Warning(StartLoc, "Float register should be even.");
649 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
650 .getRegister(RegIdx.Index / 2);
651 }
652
653 /// Coerce the register to FGR64 and return the real register for the current
654 /// target.
655 unsigned getFGR64Reg() const {
656 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
657 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
658 .getRegister(RegIdx.Index);
659 }
660
661 /// Coerce the register to FGR32 and return the real register for the current
662 /// target.
663 unsigned getFGR32Reg() const {
664 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
665 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
666 .getRegister(RegIdx.Index);
667 }
668
669 /// Coerce the register to FGRH32 and return the real register for the current
670 /// target.
671 unsigned getFGRH32Reg() const {
672 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
673 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
674 .getRegister(RegIdx.Index);
675 }
676
677 /// Coerce the register to FCC and return the real register for the current
678 /// target.
679 unsigned getFCCReg() const {
680 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
681 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
682 .getRegister(RegIdx.Index);
683 }
684
685 /// Coerce the register to MSA128 and return the real register for the current
686 /// target.
687 unsigned getMSA128Reg() const {
688 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
689 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
690 // identical
691 unsigned ClassID = Mips::MSA128BRegClassID;
692 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
693 }
694
695 /// Coerce the register to MSACtrl and return the real register for the
696 /// current target.
697 unsigned getMSACtrlReg() const {
698 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
699 unsigned ClassID = Mips::MSACtrlRegClassID;
700 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
701 }
702
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000703 /// Coerce the register to COP0 and return the real register for the
704 /// current target.
705 unsigned getCOP0Reg() const {
706 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
707 unsigned ClassID = Mips::COP0RegClassID;
708 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
709 }
710
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000711 /// Coerce the register to COP2 and return the real register for the
712 /// current target.
713 unsigned getCOP2Reg() const {
714 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
715 unsigned ClassID = Mips::COP2RegClassID;
716 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
717 }
718
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000719 /// Coerce the register to COP3 and return the real register for the
720 /// current target.
721 unsigned getCOP3Reg() const {
722 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
723 unsigned ClassID = Mips::COP3RegClassID;
724 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
725 }
726
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000727 /// Coerce the register to ACC64DSP and return the real register for the
728 /// current target.
729 unsigned getACC64DSPReg() const {
730 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
731 unsigned ClassID = Mips::ACC64DSPRegClassID;
732 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
733 }
734
735 /// Coerce the register to HI32DSP and return the real register for the
736 /// current target.
737 unsigned getHI32DSPReg() const {
738 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
739 unsigned ClassID = Mips::HI32DSPRegClassID;
740 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
741 }
742
743 /// Coerce the register to LO32DSP and return the real register for the
744 /// current target.
745 unsigned getLO32DSPReg() const {
746 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
747 unsigned ClassID = Mips::LO32DSPRegClassID;
748 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
749 }
750
751 /// Coerce the register to CCR and return the real register for the
752 /// current target.
753 unsigned getCCRReg() const {
754 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
755 unsigned ClassID = Mips::CCRRegClassID;
756 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
757 }
758
759 /// Coerce the register to HWRegs and return the real register for the
760 /// current target.
761 unsigned getHWRegsReg() const {
762 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
763 unsigned ClassID = Mips::HWRegsRegClassID;
764 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
765 }
766
767public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000768 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000769 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000770 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000771 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000772 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000773 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000774 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000775 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000776 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000777
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000778 void addRegOperands(MCInst &Inst, unsigned N) const {
779 llvm_unreachable("Use a custom parser instead");
780 }
781
Daniel Sanders21bce302014-04-01 12:35:23 +0000782 /// Render the operand to an MCInst as a GPR32
783 /// Asserts if the wrong number of operands are requested, or the operand
784 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000785 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
786 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000787 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000788 }
789
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000790 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
791 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000792 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000793 }
794
Jozef Kolek1904fa22014-11-24 14:25:53 +0000795 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
796 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000797 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000798 }
799
Zoran Jovanovic41688672015-02-10 16:36:20 +0000800 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
801 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000802 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000803 }
804
Daniel Sanders21bce302014-04-01 12:35:23 +0000805 /// Render the operand to an MCInst as a GPR64
806 /// Asserts if the wrong number of operands are requested, or the operand
807 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000808 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
809 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000810 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000811 }
812
813 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
814 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000815 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000816 }
817
818 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
819 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000820 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000821 }
822
823 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
824 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000825 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000826 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000827 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000828 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
829 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000830 }
831
832 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
833 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000834 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000835 }
836
837 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
838 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000839 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000840 }
841
842 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
843 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000844 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000845 }
846
847 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
848 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000849 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000850 }
851
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000852 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
853 assert(N == 1 && "Invalid number of operands!");
854 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
855 }
856
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000857 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
858 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000859 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000860 }
861
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000862 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
863 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000864 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000865 }
866
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000867 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
868 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000869 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000870 }
871
872 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
873 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000874 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000875 }
876
877 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
878 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000879 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000880 }
881
882 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
883 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000884 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000885 }
886
887 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
888 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000889 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000890 }
891
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000892 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000893 assert(N == 1 && "Invalid number of operands!");
894 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000895 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000896 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000897
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000898 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000899 assert(N == 2 && "Invalid number of operands!");
900
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000901 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
902 ? getMemBase()->getGPR64Reg()
903 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000904
905 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000906 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000907 }
908
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000909 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
910 assert(N == 2 && "Invalid number of operands!");
911
Jim Grosbache9119e42015-05-13 18:37:00 +0000912 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000913
914 const MCExpr *Expr = getMemOff();
915 addExpr(Inst, Expr);
916 }
917
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000918 void addRegListOperands(MCInst &Inst, unsigned N) const {
919 assert(N == 1 && "Invalid number of operands!");
920
921 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000922 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000923 }
924
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000925 void addRegPairOperands(MCInst &Inst, unsigned N) const {
926 assert(N == 2 && "Invalid number of operands!");
927 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +0000928 Inst.addOperand(MCOperand::createReg(RegNo++));
929 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000930 }
931
Zoran Jovanovic41688672015-02-10 16:36:20 +0000932 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
933 assert(N == 2 && "Invalid number of operands!");
934 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000935 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000936 }
937
Craig Topper56c590a2014-04-29 07:58:02 +0000938 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000939 // As a special case until we sort out the definition of div/divu, pretend
940 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
941 if (isGPRAsmReg() && RegIdx.Index == 0)
942 return true;
943
944 return Kind == k_PhysRegister;
945 }
946 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000947 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000948 bool isConstantImm() const {
949 return isImm() && dyn_cast<MCConstantExpr>(getImm());
950 }
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +0000951 template <unsigned Bits> bool isUImm() const {
952 return isImm() && isConstantImm() && isUInt<Bits>(getConstantImm());
953 }
Craig Topper56c590a2014-04-29 07:58:02 +0000954 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000955 // Note: It's not possible to pretend that other operand kinds are tokens.
956 // The matcher emitter checks tokens first.
957 return Kind == k_Token;
958 }
Craig Topper56c590a2014-04-29 07:58:02 +0000959 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000960 bool isConstantMemOff() const {
961 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
962 }
963 template <unsigned Bits> bool isMemWithSimmOffset() const {
Zoran Jovanovica6593ff2015-08-18 12:53:08 +0000964 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
965 && getMemBase()->isGPRAsmReg();
966 }
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +0000967 template <unsigned Bits> bool isMemWithSimmOffsetGPR() const {
968 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) &&
969 getMemBase()->isGPRAsmReg();
970 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000971 bool isMemWithGRPMM16Base() const {
972 return isMem() && getMemBase()->isMM16AsmReg();
973 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000974 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
975 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
976 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
977 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000978 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
979 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
980 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
981 && (getMemBase()->getGPR32Reg() == Mips::SP);
982 }
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +0000983 bool isUImm5Lsl2() const {
984 return (isImm() && isConstantImm() && isShiftedUInt<5, 2>(getConstantImm()));
985 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000986 bool isRegList16() const {
987 if (!isRegList())
988 return false;
989
990 int Size = RegList.List->size();
991 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
992 RegList.List->back() != Mips::RA)
993 return false;
994
995 int PrevReg = *RegList.List->begin();
996 for (int i = 1; i < Size - 1; i++) {
997 int Reg = (*(RegList.List))[i];
998 if ( Reg != PrevReg + 1)
999 return false;
1000 PrevReg = Reg;
1001 }
1002
1003 return true;
1004 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001005 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001006 bool isLSAImm() const {
1007 if (!isConstantImm())
1008 return false;
1009 int64_t Val = getConstantImm();
1010 return 1 <= Val && Val <= 4;
1011 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001012 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001013 bool isMovePRegPair() const {
1014 if (Kind != k_RegList || RegList.List->size() != 2)
1015 return false;
1016
1017 unsigned R0 = RegList.List->front();
1018 unsigned R1 = RegList.List->back();
1019
1020 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1021 (R0 == Mips::A1 && R1 == Mips::A3) ||
1022 (R0 == Mips::A2 && R1 == Mips::A3) ||
1023 (R0 == Mips::A0 && R1 == Mips::S5) ||
1024 (R0 == Mips::A0 && R1 == Mips::S6) ||
1025 (R0 == Mips::A0 && R1 == Mips::A1) ||
1026 (R0 == Mips::A0 && R1 == Mips::A2) ||
1027 (R0 == Mips::A0 && R1 == Mips::A3))
1028 return true;
1029
1030 return false;
1031 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001032
1033 StringRef getToken() const {
1034 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001035 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001036 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001037 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001038
Craig Topper56c590a2014-04-29 07:58:02 +00001039 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001040 // As a special case until we sort out the definition of div/divu, pretend
1041 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1042 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1043 RegIdx.Kind & RegKind_GPR)
1044 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001045
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001046 assert(Kind == k_PhysRegister && "Invalid access!");
1047 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001048 }
1049
Jack Carterb4dbc172012-09-05 23:34:03 +00001050 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001051 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001052 return Imm.Val;
1053 }
1054
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001055 int64_t getConstantImm() const {
1056 const MCExpr *Val = getImm();
1057 return static_cast<const MCConstantExpr *>(Val)->getValue();
1058 }
1059
1060 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001061 assert((Kind == k_Memory) && "Invalid access!");
1062 return Mem.Base;
1063 }
1064
1065 const MCExpr *getMemOff() const {
1066 assert((Kind == k_Memory) && "Invalid access!");
1067 return Mem.Off;
1068 }
1069
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001070 int64_t getConstantMemOff() const {
1071 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1072 }
1073
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001074 const SmallVectorImpl<unsigned> &getRegList() const {
1075 assert((Kind == k_RegList) && "Invalid access!");
1076 return *(RegList.List);
1077 }
1078
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001079 unsigned getRegPair() const {
1080 assert((Kind == k_RegPair) && "Invalid access!");
1081 return RegIdx.Index;
1082 }
1083
David Blaikie960ea3f2014-06-08 16:18:35 +00001084 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1085 MipsAsmParser &Parser) {
1086 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001087 Op->Tok.Data = Str.data();
1088 Op->Tok.Length = Str.size();
1089 Op->StartLoc = S;
1090 Op->EndLoc = S;
1091 return Op;
1092 }
1093
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001094 /// Create a numeric register (e.g. $1). The exact register remains
1095 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001096 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001097 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001098 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001099 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001100 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001101 }
1102
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001103 /// Create a register that is definitely a GPR.
1104 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001105 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001106 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001107 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001108 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001109 }
1110
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001111 /// Create a register that is definitely a FGR.
1112 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001113 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001114 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001115 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001116 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1117 }
1118
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001119 /// Create a register that is definitely a HWReg.
1120 /// This is typically only used for named registers such as $hwr_cpunum.
1121 static std::unique_ptr<MipsOperand>
1122 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1123 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1124 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1125 }
1126
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001127 /// Create a register that is definitely an FCC.
1128 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001129 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001130 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001131 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001132 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1133 }
1134
1135 /// Create a register that is definitely an ACC.
1136 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001137 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001138 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001139 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001140 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1141 }
1142
1143 /// Create a register that is definitely an MSA128.
1144 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001145 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001146 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001147 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001148 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1149 }
1150
1151 /// Create a register that is definitely an MSACtrl.
1152 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001153 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001154 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001155 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001156 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1157 }
1158
David Blaikie960ea3f2014-06-08 16:18:35 +00001159 static std::unique_ptr<MipsOperand>
1160 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1161 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001162 Op->Imm.Val = Val;
1163 Op->StartLoc = S;
1164 Op->EndLoc = E;
1165 return Op;
1166 }
1167
David Blaikie960ea3f2014-06-08 16:18:35 +00001168 static std::unique_ptr<MipsOperand>
1169 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1170 SMLoc E, MipsAsmParser &Parser) {
1171 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1172 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001173 Op->Mem.Off = Off;
1174 Op->StartLoc = S;
1175 Op->EndLoc = E;
1176 return Op;
1177 }
1178
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001179 static std::unique_ptr<MipsOperand>
1180 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1181 MipsAsmParser &Parser) {
1182 assert (Regs.size() > 0 && "Empty list not allowed");
1183
1184 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001185 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001186 Op->StartLoc = StartLoc;
1187 Op->EndLoc = EndLoc;
1188 return Op;
1189 }
1190
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001191 static std::unique_ptr<MipsOperand>
1192 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1193 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1194 Op->RegIdx.Index = RegNo;
1195 Op->StartLoc = S;
1196 Op->EndLoc = E;
1197 return Op;
1198 }
1199
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001200 bool isGPRAsmReg() const {
1201 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001202 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001203 bool isMM16AsmReg() const {
1204 if (!(isRegIdx() && RegIdx.Kind))
1205 return false;
1206 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1207 || RegIdx.Index == 16 || RegIdx.Index == 17);
1208 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001209 bool isMM16AsmRegZero() const {
1210 if (!(isRegIdx() && RegIdx.Kind))
1211 return false;
1212 return (RegIdx.Index == 0 ||
1213 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1214 RegIdx.Index == 17);
1215 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001216 bool isMM16AsmRegMoveP() const {
1217 if (!(isRegIdx() && RegIdx.Kind))
1218 return false;
1219 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1220 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1221 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001222 bool isFGRAsmReg() const {
1223 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1224 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001225 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001226 bool isHWRegsAsmReg() const {
1227 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001228 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001229 bool isCCRAsmReg() const {
1230 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001231 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001232 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001233 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1234 return false;
1235 if (!AsmParser.hasEightFccRegisters())
1236 return RegIdx.Index == 0;
1237 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001238 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001239 bool isACCAsmReg() const {
1240 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001241 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001242 bool isCOP0AsmReg() const {
1243 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1244 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001245 bool isCOP2AsmReg() const {
1246 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001247 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001248 bool isCOP3AsmReg() const {
1249 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1250 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001251 bool isMSA128AsmReg() const {
1252 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001253 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001254 bool isMSACtrlAsmReg() const {
1255 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001256 }
1257
Jack Carterb4dbc172012-09-05 23:34:03 +00001258 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001259 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001260 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001261 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001262
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001263 virtual ~MipsOperand() {
1264 switch (Kind) {
1265 case k_Immediate:
1266 break;
1267 case k_Memory:
1268 delete Mem.Base;
1269 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001270 case k_RegList:
1271 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001272 case k_PhysRegister:
1273 case k_RegisterIndex:
1274 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001275 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001276 break;
1277 }
1278 }
1279
Craig Topper56c590a2014-04-29 07:58:02 +00001280 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001281 switch (Kind) {
1282 case k_Immediate:
1283 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001284 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001285 OS << ">";
1286 break;
1287 case k_Memory:
1288 OS << "Mem<";
1289 Mem.Base->print(OS);
1290 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001291 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001292 OS << ">";
1293 break;
1294 case k_PhysRegister:
1295 OS << "PhysReg<" << PhysReg.Num << ">";
1296 break;
1297 case k_RegisterIndex:
1298 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1299 break;
1300 case k_Token:
1301 OS << Tok.Data;
1302 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001303 case k_RegList:
1304 OS << "RegList< ";
1305 for (auto Reg : (*RegList.List))
1306 OS << Reg << " ";
1307 OS << ">";
1308 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001309 case k_RegPair:
1310 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1311 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001312 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001313 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001314}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001315} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001316
Jack Carter9e65aa32013-03-22 00:05:30 +00001317namespace llvm {
1318extern const MCInstrDesc MipsInsts[];
1319}
1320static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1321 return MipsInsts[Opcode];
1322}
1323
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001324static bool hasShortDelaySlot(unsigned Opcode) {
1325 switch (Opcode) {
1326 case Mips::JALS_MM:
1327 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001328 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001329 case Mips::BGEZALS_MM:
1330 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001331 return true;
1332 default:
1333 return false;
1334 }
1335}
1336
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001337static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1338 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1339 return &SRExpr->getSymbol();
1340 }
1341
1342 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1343 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1344 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1345
1346 if (LHSSym)
1347 return LHSSym;
1348
1349 if (RHSSym)
1350 return RHSSym;
1351
1352 return nullptr;
1353 }
1354
1355 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1356 return getSingleMCSymbol(UExpr->getSubExpr());
1357
1358 return nullptr;
1359}
1360
1361static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1362 if (isa<MCSymbolRefExpr>(Expr))
1363 return 1;
1364
1365 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1366 return countMCSymbolRefExpr(BExpr->getLHS()) +
1367 countMCSymbolRefExpr(BExpr->getRHS());
1368
1369 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1370 return countMCSymbolRefExpr(UExpr->getSubExpr());
1371
1372 return 0;
1373}
1374
Jack Carter9e65aa32013-03-22 00:05:30 +00001375bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001376 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001377 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001378 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001379
Jack Carter9e65aa32013-03-22 00:05:30 +00001380 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001381
1382 if (MCID.isBranch() || MCID.isCall()) {
1383 const unsigned Opcode = Inst.getOpcode();
1384 MCOperand Offset;
1385
1386 switch (Opcode) {
1387 default:
1388 break;
Kai Nackee0245392015-01-27 19:11:28 +00001389 case Mips::BBIT0:
1390 case Mips::BBIT032:
1391 case Mips::BBIT1:
1392 case Mips::BBIT132:
1393 assert(hasCnMips() && "instruction only valid for octeon cpus");
1394 // Fall through
1395
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001396 case Mips::BEQ:
1397 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001398 case Mips::BEQ_MM:
1399 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001400 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001401 Offset = Inst.getOperand(2);
1402 if (!Offset.isImm())
1403 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001404 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001405 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001406 if (OffsetToAlignment(Offset.getImm(),
1407 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001408 return Error(IDLoc, "branch to misaligned address");
1409 break;
1410 case Mips::BGEZ:
1411 case Mips::BGTZ:
1412 case Mips::BLEZ:
1413 case Mips::BLTZ:
1414 case Mips::BGEZAL:
1415 case Mips::BLTZAL:
1416 case Mips::BC1F:
1417 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001418 case Mips::BGEZ_MM:
1419 case Mips::BGTZ_MM:
1420 case Mips::BLEZ_MM:
1421 case Mips::BLTZ_MM:
1422 case Mips::BGEZAL_MM:
1423 case Mips::BLTZAL_MM:
1424 case Mips::BC1F_MM:
1425 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001426 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001427 Offset = Inst.getOperand(1);
1428 if (!Offset.isImm())
1429 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001430 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001431 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001432 if (OffsetToAlignment(Offset.getImm(),
1433 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001434 return Error(IDLoc, "branch to misaligned address");
1435 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001436 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001437 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001438 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001439 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001440 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1441 Offset = Inst.getOperand(1);
1442 if (!Offset.isImm())
1443 break; // We'll deal with this situation later on when applying fixups.
1444 if (!isIntN(8, Offset.getImm()))
1445 return Error(IDLoc, "branch target out of range");
1446 if (OffsetToAlignment(Offset.getImm(), 2LL))
1447 return Error(IDLoc, "branch to misaligned address");
1448 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001449 }
1450 }
1451
Daniel Sandersa84989a2014-06-16 13:25:35 +00001452 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1453 // We still accept it but it is a normal nop.
1454 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1455 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1456 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1457 "nop instruction");
1458 }
1459
Kai Nackee0245392015-01-27 19:11:28 +00001460 if (hasCnMips()) {
1461 const unsigned Opcode = Inst.getOpcode();
1462 MCOperand Opnd;
1463 int Imm;
1464
1465 switch (Opcode) {
1466 default:
1467 break;
1468
1469 case Mips::BBIT0:
1470 case Mips::BBIT032:
1471 case Mips::BBIT1:
1472 case Mips::BBIT132:
1473 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1474 // The offset is handled above
1475 Opnd = Inst.getOperand(1);
1476 if (!Opnd.isImm())
1477 return Error(IDLoc, "expected immediate operand kind");
1478 Imm = Opnd.getImm();
1479 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1480 Opcode == Mips::BBIT1 ? 63 : 31))
1481 return Error(IDLoc, "immediate operand value out of range");
1482 if (Imm > 31) {
1483 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1484 : Mips::BBIT132);
1485 Inst.getOperand(1).setImm(Imm - 32);
1486 }
1487 break;
1488
1489 case Mips::CINS:
1490 case Mips::CINS32:
1491 case Mips::EXTS:
1492 case Mips::EXTS32:
1493 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1494 // Check length
1495 Opnd = Inst.getOperand(3);
1496 if (!Opnd.isImm())
1497 return Error(IDLoc, "expected immediate operand kind");
1498 Imm = Opnd.getImm();
1499 if (Imm < 0 || Imm > 31)
1500 return Error(IDLoc, "immediate operand value out of range");
1501 // Check position
1502 Opnd = Inst.getOperand(2);
1503 if (!Opnd.isImm())
1504 return Error(IDLoc, "expected immediate operand kind");
1505 Imm = Opnd.getImm();
1506 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1507 Opcode == Mips::EXTS ? 63 : 31))
1508 return Error(IDLoc, "immediate operand value out of range");
1509 if (Imm > 31) {
1510 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1511 Inst.getOperand(2).setImm(Imm - 32);
1512 }
1513 break;
1514
1515 case Mips::SEQi:
1516 case Mips::SNEi:
1517 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1518 Opnd = Inst.getOperand(2);
1519 if (!Opnd.isImm())
1520 return Error(IDLoc, "expected immediate operand kind");
1521 Imm = Opnd.getImm();
1522 if (!isInt<10>(Imm))
1523 return Error(IDLoc, "immediate operand value out of range");
1524 break;
1525 }
1526 }
1527
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001528 // This expansion is not in a function called by expandInstruction() because
1529 // the pseudo-instruction doesn't have a distinct opcode.
1530 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1531 inPicMode()) {
1532 warnIfNoMacro(IDLoc);
1533
1534 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1535
1536 // We can do this expansion if there's only 1 symbol in the argument
1537 // expression.
1538 if (countMCSymbolRefExpr(JalExpr) > 1)
1539 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1540
1541 // FIXME: This is checking the expression can be handled by the later stages
1542 // of the assembler. We ought to leave it to those later stages but
1543 // we can't do that until we stop evaluateRelocExpr() rewriting the
1544 // expressions into non-equivalent forms.
1545 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1546
1547 // FIXME: Add support for label+offset operands (currently causes an error).
1548 // FIXME: Add support for forward-declared local symbols.
1549 // FIXME: Add expansion for when the LargeGOT option is enabled.
1550 if (JalSym->isInSection() || JalSym->isTemporary()) {
1551 if (isABI_O32()) {
1552 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001553 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001554 // R_(MICRO)MIPS_GOT16 label
1555 // addiu $25, $25, 0
1556 // R_(MICRO)MIPS_LO16 label
1557 // jalr $25
1558 const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
1559 const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
1560
1561 MCInst LwInst;
1562 LwInst.setOpcode(Mips::LW);
1563 LwInst.addOperand(MCOperand::createReg(Mips::T9));
1564 LwInst.addOperand(MCOperand::createReg(Mips::GP));
1565 LwInst.addOperand(MCOperand::createExpr(Got16RelocExpr));
1566 Instructions.push_back(LwInst);
1567
1568 MCInst AddiuInst;
1569 AddiuInst.setOpcode(Mips::ADDiu);
1570 AddiuInst.addOperand(MCOperand::createReg(Mips::T9));
1571 AddiuInst.addOperand(MCOperand::createReg(Mips::T9));
1572 AddiuInst.addOperand(MCOperand::createExpr(Lo16RelocExpr));
1573 Instructions.push_back(AddiuInst);
1574 } else if (isABI_N32() || isABI_N64()) {
1575 // If it's a local symbol and the N32/N64 ABIs are being used,
1576 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001577 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001578 // R_(MICRO)MIPS_GOT_DISP label
1579 // jalr $25
1580 const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
1581
1582 MCInst LoadInst;
1583 LoadInst.setOpcode(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW);
1584 LoadInst.addOperand(MCOperand::createReg(Mips::T9));
1585 LoadInst.addOperand(MCOperand::createReg(Mips::GP));
1586 LoadInst.addOperand(MCOperand::createExpr(GotDispRelocExpr));
1587 Instructions.push_back(LoadInst);
1588 }
1589 } else {
1590 // If it's an external/weak symbol, we expand to:
1591 // lw/ld $25, 0($gp)
1592 // R_(MICRO)MIPS_CALL16 label
1593 // jalr $25
1594 const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
1595
1596 MCInst LoadInst;
1597 LoadInst.setOpcode(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW);
1598 LoadInst.addOperand(MCOperand::createReg(Mips::T9));
1599 LoadInst.addOperand(MCOperand::createReg(Mips::GP));
1600 LoadInst.addOperand(MCOperand::createExpr(Call16RelocExpr));
1601 Instructions.push_back(LoadInst);
1602 }
1603
1604 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001605 if (IsCpRestoreSet && inMicroMipsMode())
1606 JalrInst.setOpcode(Mips::JALRS_MM);
1607 else
1608 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001609 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1610 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1611
1612 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1613 // This relocation is supposed to be an optimization hint for the linker
1614 // and is not necessary for correctness.
1615
1616 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001617 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001618 }
1619
Jack Carter9e65aa32013-03-22 00:05:30 +00001620 if (MCID.mayLoad() || MCID.mayStore()) {
1621 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001622 // reference or immediate we may have to expand instructions.
1623 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001624 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001625 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1626 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001627 MCOperand &Op = Inst.getOperand(i);
1628 if (Op.isImm()) {
1629 int MemOffset = Op.getImm();
1630 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001631 // Offset can't exceed 16bit value.
1632 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001633 return false;
1634 }
1635 } else if (Op.isExpr()) {
1636 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001637 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001638 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001639 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001640 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001641 // Expand symbol.
1642 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001643 return false;
1644 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001645 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001646 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001647 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001648 }
1649 }
1650 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001651 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001652 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001653
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001654 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001655 if (MCID.mayLoad()) {
1656 // Try to create 16-bit GP relative load instruction.
1657 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1658 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1659 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1660 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1661 MCOperand &Op = Inst.getOperand(i);
1662 if (Op.isImm()) {
1663 int MemOffset = Op.getImm();
1664 MCOperand &DstReg = Inst.getOperand(0);
1665 MCOperand &BaseReg = Inst.getOperand(1);
1666 if (isIntN(9, MemOffset) && (MemOffset % 4 == 0) &&
1667 getContext().getRegisterInfo()->getRegClass(
1668 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001669 (BaseReg.getReg() == Mips::GP ||
1670 BaseReg.getReg() == Mips::GP_64)) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001671 MCInst TmpInst;
1672 TmpInst.setLoc(IDLoc);
1673 TmpInst.setOpcode(Mips::LWGP_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00001674 TmpInst.addOperand(MCOperand::createReg(DstReg.getReg()));
1675 TmpInst.addOperand(MCOperand::createReg(Mips::GP));
1676 TmpInst.addOperand(MCOperand::createImm(MemOffset));
Jozef Koleke10a02e2015-01-28 17:27:26 +00001677 Instructions.push_back(TmpInst);
1678 return false;
1679 }
1680 }
1681 }
1682 } // for
1683 } // if load
1684
1685 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1686
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001687 MCOperand Opnd;
1688 int Imm;
1689
1690 switch (Inst.getOpcode()) {
1691 default:
1692 break;
1693 case Mips::ADDIUS5_MM:
1694 Opnd = Inst.getOperand(2);
1695 if (!Opnd.isImm())
1696 return Error(IDLoc, "expected immediate operand kind");
1697 Imm = Opnd.getImm();
1698 if (Imm < -8 || Imm > 7)
1699 return Error(IDLoc, "immediate operand value out of range");
1700 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001701 case Mips::ADDIUSP_MM:
1702 Opnd = Inst.getOperand(0);
1703 if (!Opnd.isImm())
1704 return Error(IDLoc, "expected immediate operand kind");
1705 Imm = Opnd.getImm();
1706 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1707 Imm % 4 != 0)
1708 return Error(IDLoc, "immediate operand value out of range");
1709 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001710 case Mips::SLL16_MM:
1711 case Mips::SRL16_MM:
1712 Opnd = Inst.getOperand(2);
1713 if (!Opnd.isImm())
1714 return Error(IDLoc, "expected immediate operand kind");
1715 Imm = Opnd.getImm();
1716 if (Imm < 1 || Imm > 8)
1717 return Error(IDLoc, "immediate operand value out of range");
1718 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001719 case Mips::LI16_MM:
1720 Opnd = Inst.getOperand(1);
1721 if (!Opnd.isImm())
1722 return Error(IDLoc, "expected immediate operand kind");
1723 Imm = Opnd.getImm();
1724 if (Imm < -1 || Imm > 126)
1725 return Error(IDLoc, "immediate operand value out of range");
1726 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001727 case Mips::ADDIUR2_MM:
1728 Opnd = Inst.getOperand(2);
1729 if (!Opnd.isImm())
1730 return Error(IDLoc, "expected immediate operand kind");
1731 Imm = Opnd.getImm();
1732 if (!(Imm == 1 || Imm == -1 ||
1733 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1734 return Error(IDLoc, "immediate operand value out of range");
1735 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001736 case Mips::ADDIUR1SP_MM:
1737 Opnd = Inst.getOperand(1);
1738 if (!Opnd.isImm())
1739 return Error(IDLoc, "expected immediate operand kind");
1740 Imm = Opnd.getImm();
1741 if (OffsetToAlignment(Imm, 4LL))
1742 return Error(IDLoc, "misaligned immediate operand value");
1743 if (Imm < 0 || Imm > 255)
1744 return Error(IDLoc, "immediate operand value out of range");
1745 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001746 case Mips::ANDI16_MM:
1747 Opnd = Inst.getOperand(2);
1748 if (!Opnd.isImm())
1749 return Error(IDLoc, "expected immediate operand kind");
1750 Imm = Opnd.getImm();
1751 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1752 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1753 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1754 return Error(IDLoc, "immediate operand value out of range");
1755 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001756 case Mips::LBU16_MM:
1757 Opnd = Inst.getOperand(2);
1758 if (!Opnd.isImm())
1759 return Error(IDLoc, "expected immediate operand kind");
1760 Imm = Opnd.getImm();
1761 if (Imm < -1 || Imm > 14)
1762 return Error(IDLoc, "immediate operand value out of range");
1763 break;
Zoran Jovanovic7ba636c2015-09-17 10:14:09 +00001764 case Mips::TEQ_MM:
1765 case Mips::TGE_MM:
1766 case Mips::TGEU_MM:
1767 case Mips::TLT_MM:
1768 case Mips::TLTU_MM:
1769 case Mips::TNE_MM:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001770 case Mips::SB16_MM:
1771 Opnd = Inst.getOperand(2);
1772 if (!Opnd.isImm())
1773 return Error(IDLoc, "expected immediate operand kind");
1774 Imm = Opnd.getImm();
1775 if (Imm < 0 || Imm > 15)
1776 return Error(IDLoc, "immediate operand value out of range");
1777 break;
1778 case Mips::LHU16_MM:
1779 case Mips::SH16_MM:
1780 Opnd = Inst.getOperand(2);
1781 if (!Opnd.isImm())
1782 return Error(IDLoc, "expected immediate operand kind");
1783 Imm = Opnd.getImm();
1784 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1785 return Error(IDLoc, "immediate operand value out of range");
1786 break;
1787 case Mips::LW16_MM:
1788 case Mips::SW16_MM:
1789 Opnd = Inst.getOperand(2);
1790 if (!Opnd.isImm())
1791 return Error(IDLoc, "expected immediate operand kind");
1792 Imm = Opnd.getImm();
1793 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1794 return Error(IDLoc, "immediate operand value out of range");
1795 break;
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +00001796 case Mips::PREFX_MM:
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001797 case Mips::CACHE:
1798 case Mips::PREF:
1799 Opnd = Inst.getOperand(2);
1800 if (!Opnd.isImm())
1801 return Error(IDLoc, "expected immediate operand kind");
1802 Imm = Opnd.getImm();
1803 if (!isUInt<5>(Imm))
1804 return Error(IDLoc, "immediate operand value out of range");
1805 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001806 case Mips::ADDIUPC_MM:
1807 MCOperand Opnd = Inst.getOperand(1);
1808 if (!Opnd.isImm())
1809 return Error(IDLoc, "expected immediate operand kind");
1810 int Imm = Opnd.getImm();
1811 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1812 return Error(IDLoc, "immediate operand value out of range");
1813 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001814 }
1815 }
1816
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001817 if (needsExpansion(Inst)) {
1818 if (expandInstruction(Inst, IDLoc, Instructions))
1819 return true;
1820 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001821 Instructions.push_back(Inst);
1822
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001823 // If this instruction has a delay slot and .set reorder is active,
1824 // emit a NOP after it.
1825 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1826 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1827
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001828 if ((Inst.getOpcode() == Mips::JalOneReg ||
1829 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
1830 isPicAndNotNxxAbi()) {
1831 if (IsCpRestoreSet) {
1832 // We need a NOP between the JALR and the LW:
1833 // If .set reorder has been used, we've already emitted a NOP.
1834 // If .set noreorder has been used, we need to emit a NOP at this point.
1835 if (!AssemblerOptions.back()->isReorder())
1836 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1837
1838 // Load the $gp from the stack.
1839 SmallVector<MCInst, 3> LoadInsts;
1840 createCpRestoreMemOp(true /*IsLoad*/, CpRestoreOffset /*StackOffset*/,
1841 IDLoc, LoadInsts);
1842
1843 for (const MCInst &Inst : LoadInsts)
1844 Instructions.push_back(Inst);
1845
1846 } else
1847 Warning(IDLoc, "no .cprestore used in PIC mode");
1848 }
1849
Jack Carter9e65aa32013-03-22 00:05:30 +00001850 return false;
1851}
1852
Jack Carter30a59822012-10-04 04:03:53 +00001853bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1854
Jack Carterd0bd6422013-04-18 00:41:53 +00001855 switch (Inst.getOpcode()) {
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001856 case Mips::LoadImm32:
1857 case Mips::LoadImm64:
1858 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001859 case Mips::LoadAddrImm64:
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001860 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001861 case Mips::LoadAddrReg64:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001862 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001863 case Mips::B_MMR6_Pseudo:
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001864 case Mips::LWM_MM:
1865 case Mips::SWM_MM:
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001866 case Mips::JalOneReg:
1867 case Mips::JalTwoReg:
Toma Tabacue1e460d2015-06-11 10:36:10 +00001868 case Mips::BneImm:
1869 case Mips::BeqImm:
Toma Tabacu1a108322015-06-17 13:20:24 +00001870 case Mips::BLT:
1871 case Mips::BLE:
1872 case Mips::BGE:
1873 case Mips::BGT:
1874 case Mips::BLTU:
1875 case Mips::BLEU:
1876 case Mips::BGEU:
1877 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00001878 case Mips::BLTL:
1879 case Mips::BLEL:
1880 case Mips::BGEL:
1881 case Mips::BGTL:
1882 case Mips::BLTUL:
1883 case Mips::BLEUL:
1884 case Mips::BGEUL:
1885 case Mips::BGTUL:
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00001886 case Mips::SDivMacro:
1887 case Mips::UDivMacro:
1888 case Mips::DSDivMacro:
1889 case Mips::DUDivMacro:
Toma Tabacud88d79c2015-06-23 14:39:42 +00001890 case Mips::Ulhu:
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00001891 case Mips::Ulw:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00001892 case Mips::NORImm:
Jack Carterd0bd6422013-04-18 00:41:53 +00001893 return true;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00001894 case Mips::ADDi:
1895 case Mips::ADDiu:
1896 case Mips::SLTi:
1897 case Mips::SLTiu:
1898 if ((Inst.getNumOperands() == 3) &&
1899 Inst.getOperand(0).isReg() &&
1900 Inst.getOperand(1).isReg() &&
1901 Inst.getOperand(2).isImm()) {
1902 int64_t ImmValue = Inst.getOperand(2).getImm();
1903 return !isInt<16>(ImmValue);
1904 }
1905 return false;
1906 case Mips::ANDi:
1907 case Mips::ORi:
1908 case Mips::XORi:
1909 if ((Inst.getNumOperands() == 3) &&
1910 Inst.getOperand(0).isReg() &&
1911 Inst.getOperand(1).isReg() &&
1912 Inst.getOperand(2).isImm()) {
1913 int64_t ImmValue = Inst.getOperand(2).getImm();
1914 return !isUInt<16>(ImmValue);
1915 }
1916 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001917 default:
1918 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001919 }
1920}
Jack Carter92995f12012-10-06 00:53:28 +00001921
Matheus Almeida3813d572014-06-19 14:39:14 +00001922bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001923 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001924 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001925 default: llvm_unreachable("unimplemented expansion");
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001926 case Mips::LoadImm32:
Toma Tabacu00e98672015-05-01 12:19:27 +00001927 return expandLoadImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001928 case Mips::LoadImm64:
Toma Tabacu00e98672015-05-01 12:19:27 +00001929 return expandLoadImm(Inst, false, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001930 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001931 case Mips::LoadAddrImm64:
1932 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1933 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1934 "expected immediate operand kind");
1935
1936 return expandLoadAddress(
1937 Inst.getOperand(0).getReg(), Mips::NoRegister, Inst.getOperand(1),
1938 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001939 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001940 case Mips::LoadAddrReg64:
1941 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1942 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1943 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
1944 "expected immediate operand kind");
1945
1946 return expandLoadAddress(
1947 Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(), Inst.getOperand(2),
1948 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001949 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001950 case Mips::B_MMR6_Pseudo:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001951 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001952 case Mips::SWM_MM:
1953 case Mips::LWM_MM:
1954 return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001955 case Mips::JalOneReg:
1956 case Mips::JalTwoReg:
1957 return expandJalWithRegs(Inst, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00001958 case Mips::BneImm:
1959 case Mips::BeqImm:
1960 return expandBranchImm(Inst, IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00001961 case Mips::BLT:
1962 case Mips::BLE:
1963 case Mips::BGE:
1964 case Mips::BGT:
1965 case Mips::BLTU:
1966 case Mips::BLEU:
1967 case Mips::BGEU:
1968 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00001969 case Mips::BLTL:
1970 case Mips::BLEL:
1971 case Mips::BGEL:
1972 case Mips::BGTL:
1973 case Mips::BLTUL:
1974 case Mips::BLEUL:
1975 case Mips::BGEUL:
1976 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00001977 return expandCondBranches(Inst, IDLoc, Instructions);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00001978 case Mips::SDivMacro:
1979 return expandDiv(Inst, IDLoc, Instructions, false, true);
1980 case Mips::DSDivMacro:
1981 return expandDiv(Inst, IDLoc, Instructions, true, true);
1982 case Mips::UDivMacro:
1983 return expandDiv(Inst, IDLoc, Instructions, false, false);
1984 case Mips::DUDivMacro:
1985 return expandDiv(Inst, IDLoc, Instructions, true, false);
Toma Tabacud88d79c2015-06-23 14:39:42 +00001986 case Mips::Ulhu:
1987 return expandUlhu(Inst, IDLoc, Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00001988 case Mips::Ulw:
1989 return expandUlw(Inst, IDLoc, Instructions);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00001990 case Mips::ADDi:
1991 case Mips::ADDiu:
1992 case Mips::ANDi:
1993 case Mips::NORImm:
1994 case Mips::ORi:
1995 case Mips::SLTi:
1996 case Mips::SLTiu:
1997 case Mips::XORi:
1998 return expandAliasImmediate(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001999 }
Jack Carter30a59822012-10-04 04:03:53 +00002000}
Jack Carter92995f12012-10-06 00:53:28 +00002001
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00002002namespace {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002003void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc,
Daniel Sanders03f9c012015-07-14 12:24:22 +00002004 SmallVectorImpl<MCInst> &Instructions) {
2005 MCInst tmpInst;
2006 tmpInst.setOpcode(Opcode);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002007 tmpInst.addOperand(MCOperand::createReg(Reg0));
2008 tmpInst.addOperand(Op1);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002009 tmpInst.setLoc(IDLoc);
2010 Instructions.push_back(tmpInst);
2011}
2012
Daniel Sandersf1ae3672015-08-18 09:55:57 +00002013void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc,
Daniel Sanders03f9c012015-07-14 12:24:22 +00002014 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002015 emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002016}
2017
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002018void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc,
2019 SmallVectorImpl<MCInst> &Instructions) {
2020 emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, Instructions);
2021}
2022
2023void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc,
2024 SmallVectorImpl<MCInst> &Instructions) {
2025 MCInst tmpInst;
2026 tmpInst.setOpcode(Opcode);
2027 tmpInst.addOperand(MCOperand::createImm(Imm1));
2028 tmpInst.addOperand(MCOperand::createImm(Imm2));
2029 tmpInst.setLoc(IDLoc);
2030 Instructions.push_back(tmpInst);
2031}
2032
2033void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
2034 SmallVectorImpl<MCInst> &Instructions) {
2035 MCInst tmpInst;
2036 tmpInst.setOpcode(Opcode);
2037 tmpInst.addOperand(MCOperand::createReg(Reg0));
2038 tmpInst.setLoc(IDLoc);
2039 Instructions.push_back(tmpInst);
2040}
2041
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002042void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2,
Daniel Sanders03f9c012015-07-14 12:24:22 +00002043 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
2044 MCInst tmpInst;
2045 tmpInst.setOpcode(Opcode);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002046 tmpInst.addOperand(MCOperand::createReg(Reg0));
2047 tmpInst.addOperand(MCOperand::createReg(Reg1));
2048 tmpInst.addOperand(Op2);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002049 tmpInst.setLoc(IDLoc);
2050 Instructions.push_back(tmpInst);
2051}
2052
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002053void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
Daniel Sanders03f9c012015-07-14 12:24:22 +00002054 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002055 emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc,
Daniel Sanders03f9c012015-07-14 12:24:22 +00002056 Instructions);
2057}
2058
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002059void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
2060 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
2061 emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc,
2062 Instructions);
2063}
Daniel Sanders03f9c012015-07-14 12:24:22 +00002064
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002065void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount,
2066 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
2067 if (ShiftAmount >= 32) {
2068 emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc,
2069 Instructions);
Toma Tabacu7dea2e32015-04-28 14:06:35 +00002070 return;
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002071 }
Toma Tabacu7dea2e32015-04-28 14:06:35 +00002072
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002073 emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00002074}
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002075} // end anonymous namespace.
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00002076
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002077bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
2078 SmallVectorImpl<MCInst> &Instructions) {
2079 // Create a JALR instruction which is going to replace the pseudo-JAL.
2080 MCInst JalrInst;
2081 JalrInst.setLoc(IDLoc);
2082 const MCOperand FirstRegOp = Inst.getOperand(0);
2083 const unsigned Opcode = Inst.getOpcode();
2084
2085 if (Opcode == Mips::JalOneReg) {
2086 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002087 if (IsCpRestoreSet && inMicroMipsMode()) {
2088 JalrInst.setOpcode(Mips::JALRS16_MM);
2089 JalrInst.addOperand(FirstRegOp);
2090 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002091 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002092 JalrInst.addOperand(FirstRegOp);
2093 } else {
2094 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002095 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002096 JalrInst.addOperand(FirstRegOp);
2097 }
2098 } else if (Opcode == Mips::JalTwoReg) {
2099 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002100 if (IsCpRestoreSet && inMicroMipsMode())
2101 JalrInst.setOpcode(Mips::JALRS_MM);
2102 else
2103 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002104 JalrInst.addOperand(FirstRegOp);
2105 const MCOperand SecondRegOp = Inst.getOperand(1);
2106 JalrInst.addOperand(SecondRegOp);
2107 }
2108 Instructions.push_back(JalrInst);
2109
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002110 // If .set reorder is active and branch instruction has a delay slot,
2111 // emit a NOP after it.
2112 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
2113 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002114 createNop(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, Instructions);
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002115 }
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002116
2117 return false;
2118}
2119
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002120/// Can the value be represented by a unsigned N-bit value and a shift left?
2121template<unsigned N>
2122bool isShiftedUIntAtAnyPosition(uint64_t x) {
2123 unsigned BitNum = findFirstSet(x);
2124
2125 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2126}
2127
2128/// Load (or add) an immediate into a register.
2129///
2130/// @param ImmValue The immediate to load.
2131/// @param DstReg The register that will hold the immediate.
2132/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2133/// for a simple initialization.
2134/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2135/// @param IsAddress True if the immediate represents an address. False if it
2136/// is an integer.
2137/// @param IDLoc Location of the immediate in the source file.
2138/// @param Instructions The instructions emitted by this expansion.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002139bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002140 unsigned SrcReg, bool Is32BitImm,
2141 bool IsAddress, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00002142 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00002143 if (!Is32BitImm && !isGP64bit()) {
2144 Error(IDLoc, "instruction requires a 64-bit architecture");
2145 return true;
2146 }
2147
Daniel Sanders03f9c012015-07-14 12:24:22 +00002148 if (Is32BitImm) {
2149 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2150 // Sign extend up to 64-bit so that the predicates match the hardware
2151 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2152 // true.
2153 ImmValue = SignExtend64<32>(ImmValue);
2154 } else {
2155 Error(IDLoc, "instruction requires a 32-bit immediate");
2156 return true;
2157 }
2158 }
2159
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002160 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2161 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2162
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002163 bool UseSrcReg = false;
2164 if (SrcReg != Mips::NoRegister)
2165 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002166
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002167 unsigned TmpReg = DstReg;
2168 if (UseSrcReg && (DstReg == SrcReg)) {
2169 // At this point we need AT to perform the expansions and we exit if it is
2170 // not available.
2171 unsigned ATReg = getATReg(IDLoc);
2172 if (!ATReg)
2173 return true;
2174 TmpReg = ATReg;
2175 }
2176
Daniel Sanders03f9c012015-07-14 12:24:22 +00002177 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002178 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002179 SrcReg = ZeroReg;
2180
2181 // This doesn't quite follow the usual ABI expectations for N32 but matches
2182 // traditional assembler behaviour. N32 would normally use addiu for both
2183 // integers and addresses.
2184 if (IsAddress && !Is32BitImm) {
2185 emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2186 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002187 }
2188
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002189 emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2190 return false;
2191 }
2192
2193 if (isUInt<16>(ImmValue)) {
2194 unsigned TmpReg = DstReg;
2195 if (SrcReg == DstReg) {
2196 TmpReg = getATReg(IDLoc);
2197 if (!TmpReg)
2198 return true;
2199 }
2200
2201 emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002202 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002203 emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2204 return false;
2205 }
2206
2207 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002208 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002209
Toma Tabacu79588102015-04-29 10:19:56 +00002210 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2211 uint16_t Bits15To0 = ImmValue & 0xffff;
2212
Toma Tabacua3d056f2015-05-15 09:42:11 +00002213 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002214 // Traditional behaviour seems to special case this particular value. It's
2215 // not clear why other masks are handled differently.
2216 if (ImmValue == 0xffffffff) {
Daniel Sandersf1ae3672015-08-18 09:55:57 +00002217 emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002218 emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, Instructions);
2219 if (UseSrcReg)
2220 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2221 return false;
2222 }
2223
2224 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002225 // upper 32 bits.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002226 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002227 emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002228 if (Bits15To0)
2229 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
2230 if (UseSrcReg)
2231 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2232 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002233 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002234
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002235 emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions);
2236 if (Bits15To0)
2237 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002238 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002239 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2240 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002241 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002242
2243 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2244 if (Is32BitImm) {
2245 Error(IDLoc, "instruction requires a 32-bit immediate");
2246 return true;
2247 }
2248
2249 // Traditionally, these immediates are shifted as little as possible and as
2250 // such we align the most significant bit to bit 15 of our temporary.
2251 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2252 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2253 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2254 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
2255 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, Instructions);
2256 emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, Instructions);
2257
2258 if (UseSrcReg)
2259 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2260
2261 return false;
2262 }
2263
2264 warnIfNoMacro(IDLoc);
2265
2266 // The remaining case is packed with a sequence of dsll and ori with zeros
2267 // being omitted and any neighbouring dsll's being coalesced.
2268 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2269
2270 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2271 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
2272 IDLoc, Instructions))
2273 return false;
2274
2275 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2276 // skip it and defer the shift to the next chunk.
2277 unsigned ShiftCarriedForwards = 16;
2278 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2279 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2280
2281 if (ImmChunk != 0) {
2282 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2283 Instructions);
2284 emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, Instructions);
2285 ShiftCarriedForwards = 0;
2286 }
2287
2288 ShiftCarriedForwards += 16;
2289 }
2290 ShiftCarriedForwards -= 16;
2291
2292 // Finish any remaining shifts left by trailing zeros.
2293 if (ShiftCarriedForwards)
2294 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2295 Instructions);
2296
2297 if (UseSrcReg)
2298 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2299
Matheus Almeida3813d572014-06-19 14:39:14 +00002300 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002301}
Jack Carter92995f12012-10-06 00:53:28 +00002302
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002303bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
2304 SmallVectorImpl<MCInst> &Instructions) {
2305 const MCOperand &ImmOp = Inst.getOperand(1);
2306 assert(ImmOp.isImm() && "expected immediate operand kind");
2307 const MCOperand &DstRegOp = Inst.getOperand(0);
2308 assert(DstRegOp.isReg() && "expected register operand kind");
2309
2310 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002311 Is32BitImm, false, IDLoc, Instructions))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002312 return true;
2313
2314 return false;
2315}
2316
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002317bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2318 const MCOperand &Offset,
2319 bool Is32BitAddress, SMLoc IDLoc,
2320 SmallVectorImpl<MCInst> &Instructions) {
2321 // la can't produce a usable address when addresses are 64-bit.
2322 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2323 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2324 // We currently can't do this because we depend on the equality
2325 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2326 Error(IDLoc, "la used to load 64-bit address");
2327 // Continue as if we had 'dla' instead.
2328 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002329 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002330
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002331 // dla requires 64-bit addresses.
2332 if (!Is32BitAddress && !ABI.ArePtrs64bit()) {
2333 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002334 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002335 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002336
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002337 if (!Offset.isImm())
2338 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
2339 Is32BitAddress, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002340
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002341 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
2342 IDLoc, Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +00002343}
2344
Toma Tabacuf712ede2015-06-17 14:31:51 +00002345bool MipsAsmParser::loadAndAddSymbolAddress(
2346 const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
2347 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002348 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002349
Daniel Sandersd5a89412015-10-05 13:19:29 +00002350 const MCExpr *Symbol = cast<MCExpr>(SymExpr);
2351 const MipsMCExpr *HiExpr = MipsMCExpr::create(
2352 MCSymbolRefExpr::VK_Mips_ABS_HI, Symbol, getContext());
2353 const MipsMCExpr *LoExpr = MipsMCExpr::create(
2354 MCSymbolRefExpr::VK_Mips_ABS_LO, Symbol, getContext());
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002355
Toma Tabacufb9d1252015-06-22 12:08:39 +00002356 bool UseSrcReg = SrcReg != Mips::NoRegister;
2357
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002358 // This is the 64-bit symbol address expansion.
2359 if (ABI.ArePtrs64bit() && isGP64bit()) {
2360 // We always need AT for the 64-bit expansion.
2361 // If it is not available we exit.
2362 unsigned ATReg = getATReg(IDLoc);
2363 if (!ATReg)
2364 return true;
2365
Daniel Sandersd5a89412015-10-05 13:19:29 +00002366 const MipsMCExpr *HighestExpr = MipsMCExpr::create(
2367 MCSymbolRefExpr::VK_Mips_HIGHEST, Symbol, getContext());
2368 const MipsMCExpr *HigherExpr = MipsMCExpr::create(
2369 MCSymbolRefExpr::VK_Mips_HIGHER, Symbol, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002370
2371 if (UseSrcReg && (DstReg == SrcReg)) {
2372 // If $rs is the same as $rd:
2373 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2374 // daddiu $at, $at, %higher(sym)
2375 // dsll $at, $at, 16
2376 // daddiu $at, $at, %hi(sym)
2377 // dsll $at, $at, 16
2378 // daddiu $at, $at, %lo(sym)
2379 // daddu $rd, $at, $rd
2380 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2381 Instructions);
2382 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr),
2383 IDLoc, Instructions);
2384 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2385 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2386 Instructions);
2387 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2388 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2389 Instructions);
2390 emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions);
2391
2392 return false;
2393 }
2394
2395 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2396 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2397 // lui $at, %hi(sym)
2398 // daddiu $rd, $rd, %higher(sym)
2399 // daddiu $at, $at, %lo(sym)
2400 // dsll32 $rd, $rd, 0
2401 // daddu $rd, $rd, $at
2402 // (daddu $rd, $rd, $rs)
2403 emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2404 Instructions);
2405 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2406 Instructions);
2407 emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr),
2408 IDLoc, Instructions);
2409 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2410 Instructions);
2411 emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions);
2412 emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions);
2413 if (UseSrcReg)
2414 emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions);
2415
2416 return false;
2417 }
2418
2419 // And now, the 32-bit symbol address expansion:
2420 // If $rs is the same as $rd:
2421 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2422 // ori $at, $at, %lo(sym)
2423 // addu $rd, $at, $rd
2424 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2425 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2426 // ori $rd, $rd, %lo(sym)
2427 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002428 unsigned TmpReg = DstReg;
2429 if (UseSrcReg && (DstReg == SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002430 // If $rs is the same as $rd, we need to use AT.
2431 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002432 unsigned ATReg = getATReg(IDLoc);
2433 if (!ATReg)
2434 return true;
2435 TmpReg = ATReg;
2436 }
2437
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002438 emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions);
2439 emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc,
2440 Instructions);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002441
Toma Tabacufb9d1252015-06-22 12:08:39 +00002442 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002443 emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2444 else
2445 assert(DstReg == TmpReg);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002446
Toma Tabacu674825c2015-06-16 12:16:24 +00002447 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002448}
2449
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002450bool MipsAsmParser::expandUncondBranchMMPseudo(
2451 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002452 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2453 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002454
2455 MCOperand Offset = Inst.getOperand(0);
2456 if (Offset.isExpr()) {
2457 Inst.clear();
2458 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002459 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2460 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2461 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002462 } else {
2463 assert(Offset.isImm() && "expected immediate operand kind");
2464 if (isIntN(11, Offset.getImm())) {
2465 // If offset fits into 11 bits then this instruction becomes microMIPS
2466 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002467 if (inMicroMipsMode())
2468 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002469 } else {
2470 if (!isIntN(17, Offset.getImm()))
2471 Error(IDLoc, "branch target out of range");
2472 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2473 Error(IDLoc, "branch to misaligned address");
2474 Inst.clear();
2475 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002476 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2477 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2478 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002479 }
2480 }
2481 Instructions.push_back(Inst);
2482
Zoran Jovanovicada70912015-09-07 11:56:37 +00002483 // If .set reorder is active and branch instruction has a delay slot,
2484 // emit a NOP after it.
2485 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2486 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Toma Tabacu234482a2015-03-16 12:03:39 +00002487 createNop(true, IDLoc, Instructions);
2488
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002489 return false;
2490}
2491
Toma Tabacue1e460d2015-06-11 10:36:10 +00002492bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2493 SmallVectorImpl<MCInst> &Instructions) {
2494 const MCOperand &DstRegOp = Inst.getOperand(0);
2495 assert(DstRegOp.isReg() && "expected register operand kind");
2496
2497 const MCOperand &ImmOp = Inst.getOperand(1);
2498 assert(ImmOp.isImm() && "expected immediate operand kind");
2499
2500 const MCOperand &MemOffsetOp = Inst.getOperand(2);
2501 assert(MemOffsetOp.isImm() && "expected immediate operand kind");
2502
2503 unsigned OpCode = 0;
2504 switch(Inst.getOpcode()) {
2505 case Mips::BneImm:
2506 OpCode = Mips::BNE;
2507 break;
2508 case Mips::BeqImm:
2509 OpCode = Mips::BEQ;
2510 break;
2511 default:
2512 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2513 break;
2514 }
2515
2516 int64_t ImmValue = ImmOp.getImm();
2517 if (ImmValue == 0) {
2518 MCInst BranchInst;
2519 BranchInst.setOpcode(OpCode);
2520 BranchInst.addOperand(DstRegOp);
2521 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2522 BranchInst.addOperand(MemOffsetOp);
2523 Instructions.push_back(BranchInst);
2524 } else {
2525 warnIfNoMacro(IDLoc);
2526
2527 unsigned ATReg = getATReg(IDLoc);
2528 if (!ATReg)
2529 return true;
2530
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002531 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
2532 IDLoc, Instructions))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002533 return true;
2534
2535 MCInst BranchInst;
2536 BranchInst.setOpcode(OpCode);
2537 BranchInst.addOperand(DstRegOp);
2538 BranchInst.addOperand(MCOperand::createReg(ATReg));
2539 BranchInst.addOperand(MemOffsetOp);
2540 Instructions.push_back(BranchInst);
2541 }
2542 return false;
2543}
2544
Jack Carter9e65aa32013-03-22 00:05:30 +00002545void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002546 SmallVectorImpl<MCInst> &Instructions,
2547 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002548 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00002549 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002550 const MCExpr *ExprOffset;
2551 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002552 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002553 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2554 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002555 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002556 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2557 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002558 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002559 if (isImmOpnd) {
2560 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2561 ImmOffset = Inst.getOperand(2).getImm();
2562 LoOffset = ImmOffset & 0x0000ffff;
2563 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002564 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002565 if (LoOffset & 0x8000)
2566 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002567 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002568 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002569 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002570 TempInst.setLoc(IDLoc);
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
Jack Carter9e65aa32013-03-22 00:05:30 +00002609 TempInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00002610 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002611 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002612 TempInst.addOperand(MCOperand::createImm(HiOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002613 else {
Toma Tabacu07c97b32015-06-17 10:43:45 +00002614 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
2615 TempInst.addOperand(MCOperand::createExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002616 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002617 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002618 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002619 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002620 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002621 // Add temp register to base.
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002622 if (BaseRegNum != Mips::ZERO) {
2623 TempInst.setOpcode(Mips::ADDu);
Jim Grosbache9119e42015-05-13 18:37:00 +00002624 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2625 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2626 TempInst.addOperand(MCOperand::createReg(BaseRegNum));
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002627 Instructions.push_back(TempInst);
2628 TempInst.clear();
2629 }
Alp Tokercb402912014-01-24 17:20:08 +00002630 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002631 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002632 TempInst.setOpcode(Inst.getOpcode());
Jim Grosbache9119e42015-05-13 18:37:00 +00002633 TempInst.addOperand(MCOperand::createReg(RegOpNum));
2634 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002635 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002636 TempInst.addOperand(MCOperand::createImm(LoOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002637 else {
Toma Tabacu07c97b32015-06-17 10:43:45 +00002638 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
2639 TempInst.addOperand(MCOperand::createExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002640 }
2641 Instructions.push_back(TempInst);
2642 TempInst.clear();
2643}
2644
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002645bool
2646MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2647 SmallVectorImpl<MCInst> &Instructions) {
2648 unsigned OpNum = Inst.getNumOperands();
2649 unsigned Opcode = Inst.getOpcode();
2650 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2651
2652 assert (Inst.getOperand(OpNum - 1).isImm() &&
2653 Inst.getOperand(OpNum - 2).isReg() &&
2654 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2655
2656 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2657 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2658 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2659 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2660 // It can be implemented as SWM16 or LWM16 instruction.
2661 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2662
2663 Inst.setOpcode(NewOpcode);
2664 Instructions.push_back(Inst);
2665 return false;
2666}
2667
Toma Tabacu1a108322015-06-17 13:20:24 +00002668bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2669 SmallVectorImpl<MCInst> &Instructions) {
2670 unsigned PseudoOpcode = Inst.getOpcode();
2671 unsigned SrcReg = Inst.getOperand(0).getReg();
2672 unsigned TrgReg = Inst.getOperand(1).getReg();
2673 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2674
2675 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002676 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002677
2678 switch (PseudoOpcode) {
2679 case Mips::BLT:
2680 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002681 case Mips::BLTL:
2682 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002683 AcceptsEquality = false;
2684 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002685 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2686 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002687 ZeroSrcOpcode = Mips::BGTZ;
2688 ZeroTrgOpcode = Mips::BLTZ;
2689 break;
2690 case Mips::BLE:
2691 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002692 case Mips::BLEL:
2693 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002694 AcceptsEquality = true;
2695 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002696 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2697 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002698 ZeroSrcOpcode = Mips::BGEZ;
2699 ZeroTrgOpcode = Mips::BLEZ;
2700 break;
2701 case Mips::BGE:
2702 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002703 case Mips::BGEL:
2704 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002705 AcceptsEquality = true;
2706 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002707 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2708 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002709 ZeroSrcOpcode = Mips::BLEZ;
2710 ZeroTrgOpcode = Mips::BGEZ;
2711 break;
2712 case Mips::BGT:
2713 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002714 case Mips::BGTL:
2715 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002716 AcceptsEquality = false;
2717 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002718 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2719 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002720 ZeroSrcOpcode = Mips::BLTZ;
2721 ZeroTrgOpcode = Mips::BGTZ;
2722 break;
2723 default:
2724 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2725 }
2726
2727 MCInst BranchInst;
2728 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2729 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2730 if (IsSrcRegZero && IsTrgRegZero) {
2731 // FIXME: All of these Opcode-specific if's are needed for compatibility
2732 // with GAS' behaviour. However, they may not generate the most efficient
2733 // code in some circumstances.
2734 if (PseudoOpcode == Mips::BLT) {
2735 BranchInst.setOpcode(Mips::BLTZ);
2736 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2737 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2738 Instructions.push_back(BranchInst);
2739 return false;
2740 }
2741 if (PseudoOpcode == Mips::BLE) {
2742 BranchInst.setOpcode(Mips::BLEZ);
2743 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2744 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2745 Instructions.push_back(BranchInst);
2746 Warning(IDLoc, "branch is always taken");
2747 return false;
2748 }
2749 if (PseudoOpcode == Mips::BGE) {
2750 BranchInst.setOpcode(Mips::BGEZ);
2751 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2752 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2753 Instructions.push_back(BranchInst);
2754 Warning(IDLoc, "branch is always taken");
2755 return false;
2756 }
2757 if (PseudoOpcode == Mips::BGT) {
2758 BranchInst.setOpcode(Mips::BGTZ);
2759 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2760 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2761 Instructions.push_back(BranchInst);
2762 return false;
2763 }
2764 if (PseudoOpcode == Mips::BGTU) {
2765 BranchInst.setOpcode(Mips::BNE);
2766 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2767 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2768 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2769 Instructions.push_back(BranchInst);
2770 return false;
2771 }
2772 if (AcceptsEquality) {
2773 // If both registers are $0 and the pseudo-branch accepts equality, it
2774 // will always be taken, so we emit an unconditional branch.
2775 BranchInst.setOpcode(Mips::BEQ);
2776 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2777 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2778 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2779 Instructions.push_back(BranchInst);
2780 Warning(IDLoc, "branch is always taken");
2781 return false;
2782 }
2783 // If both registers are $0 and the pseudo-branch does not accept
2784 // equality, it will never be taken, so we don't have to emit anything.
2785 return false;
2786 }
2787 if (IsSrcRegZero || IsTrgRegZero) {
2788 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2789 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2790 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2791 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2792 // the pseudo-branch will never be taken, so we don't emit anything.
2793 // This only applies to unsigned pseudo-branches.
2794 return false;
2795 }
2796 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2797 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2798 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2799 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2800 // the pseudo-branch will always be taken, so we emit an unconditional
2801 // branch.
2802 // This only applies to unsigned pseudo-branches.
2803 BranchInst.setOpcode(Mips::BEQ);
2804 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2805 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2806 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2807 Instructions.push_back(BranchInst);
2808 Warning(IDLoc, "branch is always taken");
2809 return false;
2810 }
2811 if (IsUnsigned) {
2812 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2813 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2814 // the pseudo-branch will be taken only when the non-zero register is
2815 // different from 0, so we emit a BNEZ.
2816 //
2817 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2818 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2819 // the pseudo-branch will be taken only when the non-zero register is
2820 // equal to 0, so we emit a BEQZ.
2821 //
2822 // Because only BLEU and BGEU branch on equality, we can use the
2823 // AcceptsEquality variable to decide when to emit the BEQZ.
2824 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQ : Mips::BNE);
2825 BranchInst.addOperand(
2826 MCOperand::createReg(IsSrcRegZero ? TrgReg : SrcReg));
2827 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2828 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2829 Instructions.push_back(BranchInst);
2830 return false;
2831 }
2832 // If we have a signed pseudo-branch and one of the registers is $0,
2833 // we can use an appropriate compare-to-zero branch. We select which one
2834 // to use in the switch statement above.
2835 BranchInst.setOpcode(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode);
2836 BranchInst.addOperand(MCOperand::createReg(IsSrcRegZero ? TrgReg : SrcReg));
2837 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2838 Instructions.push_back(BranchInst);
2839 return false;
2840 }
2841
2842 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2843 // expansions. If it is not available, we return.
2844 unsigned ATRegNum = getATReg(IDLoc);
2845 if (!ATRegNum)
2846 return true;
2847
2848 warnIfNoMacro(IDLoc);
2849
2850 // SLT fits well with 2 of our 4 pseudo-branches:
2851 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2852 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2853 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2854 // This is accomplished by using a BNEZ with the result of the SLT.
2855 //
2856 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2857 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2858 // Because only BGE and BLE branch on equality, we can use the
2859 // AcceptsEquality variable to decide when to emit the BEQZ.
2860 // Note that the order of the SLT arguments doesn't change between
2861 // opposites.
2862 //
2863 // The same applies to the unsigned variants, except that SLTu is used
2864 // instead of SLT.
2865 MCInst SetInst;
2866 SetInst.setOpcode(IsUnsigned ? Mips::SLTu : Mips::SLT);
2867 SetInst.addOperand(MCOperand::createReg(ATRegNum));
2868 SetInst.addOperand(MCOperand::createReg(ReverseOrderSLT ? TrgReg : SrcReg));
2869 SetInst.addOperand(MCOperand::createReg(ReverseOrderSLT ? SrcReg : TrgReg));
2870 Instructions.push_back(SetInst);
2871
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002872 if (!IsLikely)
2873 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQ : Mips::BNE);
2874 else
2875 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQL : Mips::BNEL);
Toma Tabacu1a108322015-06-17 13:20:24 +00002876 BranchInst.addOperand(MCOperand::createReg(ATRegNum));
2877 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2878 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2879 Instructions.push_back(BranchInst);
2880 return false;
2881}
2882
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002883bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
2884 SmallVectorImpl<MCInst> &Instructions,
2885 const bool IsMips64, const bool Signed) {
2886 if (hasMips32r6()) {
2887 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2888 return false;
2889 }
2890
2891 warnIfNoMacro(IDLoc);
2892
2893 const MCOperand &RsRegOp = Inst.getOperand(0);
2894 assert(RsRegOp.isReg() && "expected register operand kind");
2895 unsigned RsReg = RsRegOp.getReg();
2896
2897 const MCOperand &RtRegOp = Inst.getOperand(1);
2898 assert(RtRegOp.isReg() && "expected register operand kind");
2899 unsigned RtReg = RtRegOp.getReg();
2900 unsigned DivOp;
2901 unsigned ZeroReg;
2902
2903 if (IsMips64) {
2904 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2905 ZeroReg = Mips::ZERO_64;
2906 } else {
2907 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2908 ZeroReg = Mips::ZERO;
2909 }
2910
2911 bool UseTraps = useTraps();
2912
2913 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2914 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2915 Warning(IDLoc, "dividing zero by zero");
2916 if (IsMips64) {
2917 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2918 if (UseTraps) {
2919 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2920 return false;
2921 }
2922
2923 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2924 return false;
2925 }
2926 } else {
2927 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2928 return false;
2929 }
2930 }
2931
2932 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
2933 Warning(IDLoc, "division by zero");
2934 if (Signed) {
2935 if (UseTraps) {
2936 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2937 return false;
2938 }
2939
2940 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2941 return false;
2942 }
2943 }
2944
2945 // FIXME: The values for these two BranchTarget variables may be different in
2946 // micromips. These magic numbers need to be removed.
2947 unsigned BranchTargetNoTraps;
2948 unsigned BranchTarget;
2949
2950 if (UseTraps) {
2951 BranchTarget = IsMips64 ? 12 : 8;
2952 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2953 } else {
2954 BranchTarget = IsMips64 ? 20 : 16;
2955 BranchTargetNoTraps = 8;
2956 // Branch to the li instruction.
2957 emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc,
2958 Instructions);
2959 }
2960
2961 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2962
2963 if (!UseTraps)
2964 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2965
2966 if (!Signed) {
2967 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
2968 return false;
2969 }
2970
2971 unsigned ATReg = getATReg(IDLoc);
2972 if (!ATReg)
2973 return true;
2974
2975 emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, Instructions);
2976 if (IsMips64) {
2977 // Branch to the mflo instruction.
2978 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
2979 emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, Instructions);
2980 emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, Instructions);
2981 } else {
2982 // Branch to the mflo instruction.
2983 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
2984 emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, Instructions);
2985 }
2986
2987 if (UseTraps)
2988 emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, Instructions);
2989 else {
2990 // Branch to the mflo instruction.
2991 emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, Instructions);
2992 emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, Instructions);
2993 emitII(Mips::BREAK, 0x6, 0, IDLoc, Instructions);
2994 }
2995 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
2996 return false;
2997}
2998
Toma Tabacud88d79c2015-06-23 14:39:42 +00002999bool MipsAsmParser::expandUlhu(MCInst &Inst, SMLoc IDLoc,
3000 SmallVectorImpl<MCInst> &Instructions) {
3001 if (hasMips32r6() || hasMips64r6()) {
3002 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3003 return false;
3004 }
3005
3006 warnIfNoMacro(IDLoc);
3007
3008 const MCOperand &DstRegOp = Inst.getOperand(0);
3009 assert(DstRegOp.isReg() && "expected register operand kind");
3010
3011 const MCOperand &SrcRegOp = Inst.getOperand(1);
3012 assert(SrcRegOp.isReg() && "expected register operand kind");
3013
3014 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3015 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3016
3017 unsigned DstReg = DstRegOp.getReg();
3018 unsigned SrcReg = SrcRegOp.getReg();
3019 int64_t OffsetValue = OffsetImmOp.getImm();
3020
3021 // NOTE: We always need AT for ULHU, as it is always used as the source
3022 // register for one of the LBu's.
3023 unsigned ATReg = getATReg(IDLoc);
3024 if (!ATReg)
3025 return true;
3026
3027 // When the value of offset+1 does not fit in 16 bits, we have to load the
3028 // offset in AT, (D)ADDu the original source register (if there was one), and
3029 // then use AT as the source register for the 2 generated LBu's.
3030 bool LoadedOffsetInAT = false;
3031 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3032 LoadedOffsetInAT = true;
3033
3034 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003035 true, IDLoc, Instructions))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003036 return true;
3037
3038 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3039 // because it will make our output more similar to GAS'. For example,
3040 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3041 // instead of just an "ori $1, $9, 32768".
3042 // NOTE: If there is no source register specified in the ULHU, the parser
3043 // will interpret it as $0.
3044 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3045 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3046 }
3047
3048 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3049 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3050 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3051
3052 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3053 if (isLittle()) {
3054 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3055 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3056 } else {
3057 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3058 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3059 }
3060
3061 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3062
3063 MCInst TmpInst;
3064 TmpInst.setOpcode(Mips::LBu);
3065 TmpInst.addOperand(MCOperand::createReg(FirstLbuDstReg));
3066 TmpInst.addOperand(MCOperand::createReg(LbuSrcReg));
3067 TmpInst.addOperand(MCOperand::createImm(FirstLbuOffset));
3068 Instructions.push_back(TmpInst);
3069
3070 TmpInst.clear();
3071 TmpInst.setOpcode(Mips::LBu);
3072 TmpInst.addOperand(MCOperand::createReg(SecondLbuDstReg));
3073 TmpInst.addOperand(MCOperand::createReg(LbuSrcReg));
3074 TmpInst.addOperand(MCOperand::createImm(SecondLbuOffset));
3075 Instructions.push_back(TmpInst);
3076
3077 TmpInst.clear();
3078 TmpInst.setOpcode(Mips::SLL);
3079 TmpInst.addOperand(MCOperand::createReg(SllReg));
3080 TmpInst.addOperand(MCOperand::createReg(SllReg));
3081 TmpInst.addOperand(MCOperand::createImm(8));
3082 Instructions.push_back(TmpInst);
3083
3084 TmpInst.clear();
3085 TmpInst.setOpcode(Mips::OR);
3086 TmpInst.addOperand(MCOperand::createReg(DstReg));
3087 TmpInst.addOperand(MCOperand::createReg(DstReg));
3088 TmpInst.addOperand(MCOperand::createReg(ATReg));
3089 Instructions.push_back(TmpInst);
3090
3091 return false;
3092}
3093
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003094bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
3095 SmallVectorImpl<MCInst> &Instructions) {
3096 if (hasMips32r6() || hasMips64r6()) {
3097 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3098 return false;
3099 }
3100
3101 const MCOperand &DstRegOp = Inst.getOperand(0);
3102 assert(DstRegOp.isReg() && "expected register operand kind");
3103
3104 const MCOperand &SrcRegOp = Inst.getOperand(1);
3105 assert(SrcRegOp.isReg() && "expected register operand kind");
3106
3107 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3108 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3109
3110 unsigned SrcReg = SrcRegOp.getReg();
3111 int64_t OffsetValue = OffsetImmOp.getImm();
3112 unsigned ATReg = 0;
3113
3114 // When the value of offset+3 does not fit in 16 bits, we have to load the
3115 // offset in AT, (D)ADDu the original source register (if there was one), and
3116 // then use AT as the source register for the generated LWL and LWR.
3117 bool LoadedOffsetInAT = false;
3118 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3119 ATReg = getATReg(IDLoc);
3120 if (!ATReg)
3121 return true;
3122 LoadedOffsetInAT = true;
3123
3124 warnIfNoMacro(IDLoc);
3125
3126 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003127 true, IDLoc, Instructions))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003128 return true;
3129
3130 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3131 // because it will make our output more similar to GAS'. For example,
3132 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3133 // instead of just an "ori $1, $9, 32768".
3134 // NOTE: If there is no source register specified in the ULW, the parser
3135 // will interpret it as $0.
3136 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3137 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3138 }
3139
3140 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3141 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3142 if (isLittle()) {
3143 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3144 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3145 } else {
3146 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3147 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3148 }
3149
3150 MCInst LeftLoadInst;
3151 LeftLoadInst.setOpcode(Mips::LWL);
3152 LeftLoadInst.addOperand(DstRegOp);
3153 LeftLoadInst.addOperand(MCOperand::createReg(FinalSrcReg));
3154 LeftLoadInst.addOperand(MCOperand::createImm(LeftLoadOffset));
3155 Instructions.push_back(LeftLoadInst);
3156
3157 MCInst RightLoadInst;
3158 RightLoadInst.setOpcode(Mips::LWR);
3159 RightLoadInst.addOperand(DstRegOp);
3160 RightLoadInst.addOperand(MCOperand::createReg(FinalSrcReg));
3161 RightLoadInst.addOperand(MCOperand::createImm(RightLoadOffset ));
3162 Instructions.push_back(RightLoadInst);
3163
3164 return false;
3165}
3166
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003167bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
3168 SmallVectorImpl<MCInst> &Instructions) {
3169
3170 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3171 assert (Inst.getOperand(0).isReg() &&
3172 Inst.getOperand(1).isReg() &&
3173 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3174
3175 unsigned ATReg = Mips::NoRegister;
3176 unsigned FinalDstReg = Mips::NoRegister;
3177 unsigned DstReg = Inst.getOperand(0).getReg();
3178 unsigned SrcReg = Inst.getOperand(1).getReg();
3179 int64_t ImmValue = Inst.getOperand(2).getImm();
3180
3181 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3182
3183 unsigned FinalOpcode = Inst.getOpcode();
3184
3185 if (DstReg == SrcReg) {
3186 ATReg = getATReg(Inst.getLoc());
3187 if (!ATReg)
3188 return true;
3189 FinalDstReg = DstReg;
3190 DstReg = ATReg;
3191 }
3192
3193 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Instructions)) {
3194 switch (FinalOpcode) {
3195 default:
3196 llvm_unreachable("unimplemented expansion");
3197 case (Mips::ADDi):
3198 FinalOpcode = Mips::ADD;
3199 break;
3200 case (Mips::ADDiu):
3201 FinalOpcode = Mips::ADDu;
3202 break;
3203 case (Mips::ANDi):
3204 FinalOpcode = Mips::AND;
3205 break;
3206 case (Mips::NORImm):
3207 FinalOpcode = Mips::NOR;
3208 break;
3209 case (Mips::ORi):
3210 FinalOpcode = Mips::OR;
3211 break;
3212 case (Mips::SLTi):
3213 FinalOpcode = Mips::SLT;
3214 break;
3215 case (Mips::SLTiu):
3216 FinalOpcode = Mips::SLTu;
3217 break;
3218 case (Mips::XORi):
3219 FinalOpcode = Mips::XOR;
3220 break;
3221 }
3222
3223 MCInst tmpInst;
3224
3225 tmpInst.clear();
3226 tmpInst.setLoc(Inst.getLoc());
3227 tmpInst.setOpcode(FinalOpcode);
3228 if (FinalDstReg == Mips::NoRegister) {
3229 tmpInst.addOperand(MCOperand::createReg(DstReg));
3230 tmpInst.addOperand(MCOperand::createReg(DstReg));
3231 tmpInst.addOperand(MCOperand::createReg(SrcReg));
3232 } else {
3233 tmpInst.addOperand(MCOperand::createReg(FinalDstReg));
3234 tmpInst.addOperand(MCOperand::createReg(FinalDstReg));
3235 tmpInst.addOperand(MCOperand::createReg(DstReg));
3236 }
3237 Instructions.push_back(tmpInst);
3238 return false;
3239 }
3240 return true;
3241}
3242
Toma Tabacu234482a2015-03-16 12:03:39 +00003243void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
3244 SmallVectorImpl<MCInst> &Instructions) {
3245 MCInst NopInst;
3246 if (hasShortDelaySlot) {
3247 NopInst.setOpcode(Mips::MOVE16_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003248 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
3249 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
Toma Tabacu234482a2015-03-16 12:03:39 +00003250 } else {
3251 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00003252 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
3253 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
3254 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu234482a2015-03-16 12:03:39 +00003255 }
3256 Instructions.push_back(NopInst);
3257}
3258
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003259void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +00003260 unsigned TrgReg, bool Is64Bit,
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003261 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders03f9c012015-07-14 12:24:22 +00003262 emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
3263 Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003264}
3265
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003266void MipsAsmParser::createCpRestoreMemOp(
3267 bool IsLoad, int StackOffset, SMLoc IDLoc,
3268 SmallVectorImpl<MCInst> &Instructions) {
3269 MCInst MemInst;
3270 MemInst.setOpcode(IsLoad ? Mips::LW : Mips::SW);
3271 MemInst.addOperand(MCOperand::createReg(Mips::GP));
3272 MemInst.addOperand(MCOperand::createReg(Mips::SP));
3273 MemInst.addOperand(MCOperand::createImm(StackOffset));
3274
3275 // If the offset can not fit into 16 bits, we need to expand.
3276 if (!isInt<16>(StackOffset))
3277 expandMemInst(MemInst, IDLoc, Instructions, IsLoad, true /*HasImmOpnd*/);
3278 else
3279 Instructions.push_back(MemInst);
3280}
3281
Matheus Almeida595fcab2014-06-11 15:05:56 +00003282unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3283 // As described by the Mips32r2 spec, the registers Rd and Rs for
3284 // jalr.hb must be different.
3285 unsigned Opcode = Inst.getOpcode();
3286
3287 if (Opcode == Mips::JALR_HB &&
3288 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3289 return Match_RequiresDifferentSrcAndDst;
3290
3291 return Match_Success;
3292}
3293
David Blaikie960ea3f2014-06-08 16:18:35 +00003294bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3295 OperandVector &Operands,
3296 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003297 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003298 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003299
Jack Carterb4dbc172012-09-05 23:34:03 +00003300 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00003301 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00003302 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003303 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003304
3305 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003306 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003307 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00003308 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00003309 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00003310 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00003311 return false;
3312 }
3313 case Match_MissingFeature:
3314 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3315 return true;
3316 case Match_InvalidOperand: {
3317 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003318 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003319 if (ErrorInfo >= Operands.size())
3320 return Error(IDLoc, "too few operands for instruction");
3321
David Blaikie960ea3f2014-06-08 16:18:35 +00003322 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003323 if (ErrorLoc == SMLoc())
3324 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003325 }
3326
3327 return Error(ErrorLoc, "invalid operand for instruction");
3328 }
3329 case Match_MnemonicFail:
3330 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003331 case Match_RequiresDifferentSrcAndDst:
3332 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00003333 }
Craig Topper589ceee2015-01-03 08:16:34 +00003334
3335 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003336}
3337
Toma Tabacud9d344b2015-04-27 14:05:04 +00003338void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3339 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3340 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3341 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003342}
3343
Toma Tabacu81496c12015-05-20 08:54:45 +00003344void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3345 if (!AssemblerOptions.back()->isMacro())
3346 Warning(Loc, "macro instruction expanded into multiple instructions");
3347}
3348
Daniel Sandersef638fe2014-10-03 15:37:37 +00003349void
3350MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3351 SMRange Range, bool ShowColors) {
3352 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003353 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003354 ShowColors);
3355}
3356
Jack Carter1ac53222013-02-20 23:11:17 +00003357int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003358 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003359
Vladimir Medic4c299852013-11-06 11:27:05 +00003360 CC = StringSwitch<unsigned>(Name)
3361 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003362 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003363 .Case("a0", 4)
3364 .Case("a1", 5)
3365 .Case("a2", 6)
3366 .Case("a3", 7)
3367 .Case("v0", 2)
3368 .Case("v1", 3)
3369 .Case("s0", 16)
3370 .Case("s1", 17)
3371 .Case("s2", 18)
3372 .Case("s3", 19)
3373 .Case("s4", 20)
3374 .Case("s5", 21)
3375 .Case("s6", 22)
3376 .Case("s7", 23)
3377 .Case("k0", 26)
3378 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003379 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003380 .Case("sp", 29)
3381 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003382 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003383 .Case("ra", 31)
3384 .Case("t0", 8)
3385 .Case("t1", 9)
3386 .Case("t2", 10)
3387 .Case("t3", 11)
3388 .Case("t4", 12)
3389 .Case("t5", 13)
3390 .Case("t6", 14)
3391 .Case("t7", 15)
3392 .Case("t8", 24)
3393 .Case("t9", 25)
3394 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003395
Toma Tabacufda445c2014-09-15 15:33:01 +00003396 if (!(isABI_N32() || isABI_N64()))
3397 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003398
Daniel Sandersef638fe2014-10-03 15:37:37 +00003399 if (12 <= CC && CC <= 15) {
3400 // Name is one of t4-t7
3401 AsmToken RegTok = getLexer().peekTok();
3402 SMRange RegRange = RegTok.getLocRange();
3403
3404 StringRef FixedName = StringSwitch<StringRef>(Name)
3405 .Case("t4", "t0")
3406 .Case("t5", "t1")
3407 .Case("t6", "t2")
3408 .Case("t7", "t3")
3409 .Default("");
3410 assert(FixedName != "" && "Register name is not one of t4-t7.");
3411
3412 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3413 "Did you mean $" + FixedName + "?", RegRange);
3414 }
3415
Toma Tabacufda445c2014-09-15 15:33:01 +00003416 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3417 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3418 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3419 if (8 <= CC && CC <= 11)
3420 CC += 4;
3421
3422 if (CC == -1)
3423 CC = StringSwitch<unsigned>(Name)
3424 .Case("a4", 8)
3425 .Case("a5", 9)
3426 .Case("a6", 10)
3427 .Case("a7", 11)
3428 .Case("kt0", 26)
3429 .Case("kt1", 27)
3430 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003431
3432 return CC;
3433}
Jack Carterd0bd6422013-04-18 00:41:53 +00003434
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003435int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3436 int CC;
3437
3438 CC = StringSwitch<unsigned>(Name)
3439 .Case("hwr_cpunum", 0)
3440 .Case("hwr_synci_step", 1)
3441 .Case("hwr_cc", 2)
3442 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003443 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003444 .Default(-1);
3445
3446 return CC;
3447}
3448
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003449int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003450
Jack Cartera63b16a2012-09-07 00:23:42 +00003451 if (Name[0] == 'f') {
3452 StringRef NumString = Name.substr(1);
3453 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003454 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003455 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003456 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003457 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003458 return IntVal;
3459 }
3460 return -1;
3461}
Jack Cartera63b16a2012-09-07 00:23:42 +00003462
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003463int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3464
3465 if (Name.startswith("fcc")) {
3466 StringRef NumString = Name.substr(3);
3467 unsigned IntVal;
3468 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003469 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003470 if (IntVal > 7) // There are only 8 fcc registers.
3471 return -1;
3472 return IntVal;
3473 }
3474 return -1;
3475}
3476
3477int MipsAsmParser::matchACRegisterName(StringRef Name) {
3478
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003479 if (Name.startswith("ac")) {
3480 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003481 unsigned IntVal;
3482 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003483 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003484 if (IntVal > 3) // There are only 3 acc registers.
3485 return -1;
3486 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003487 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003488 return -1;
3489}
Jack Carterd0bd6422013-04-18 00:41:53 +00003490
Jack Carter5dc8ac92013-09-25 23:50:44 +00003491int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3492 unsigned IntVal;
3493
3494 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3495 return -1;
3496
3497 if (IntVal > 31)
3498 return -1;
3499
3500 return IntVal;
3501}
3502
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003503int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3504 int CC;
3505
3506 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003507 .Case("msair", 0)
3508 .Case("msacsr", 1)
3509 .Case("msaaccess", 2)
3510 .Case("msasave", 3)
3511 .Case("msamodify", 4)
3512 .Case("msarequest", 5)
3513 .Case("msamap", 6)
3514 .Case("msaunmap", 7)
3515 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003516
3517 return CC;
3518}
3519
Toma Tabacu89a712b2015-04-15 10:48:56 +00003520unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00003521 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00003522 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00003523 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00003524 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00003525 return 0;
3526 }
3527 unsigned AT = getReg(
3528 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00003529 return AT;
3530}
Jack Carter0b744b32012-10-04 02:29:46 +00003531
Jack Carterd0bd6422013-04-18 00:41:53 +00003532unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00003533 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00003534}
3535
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003536unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003537 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00003538 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003539}
3540
Jack Carter873c7242013-01-12 01:03:14 +00003541int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003542 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00003543 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00003544 return -1;
3545
Jack Carter873c7242013-01-12 01:03:14 +00003546 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00003547}
3548
Toma Tabacu13964452014-09-04 13:23:44 +00003549bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003550 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003551 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003552
Jack Carter30a59822012-10-04 04:03:53 +00003553 // Check if the current operand has a custom associated parser, if so, try to
3554 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00003555 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3556 if (ResTy == MatchOperand_Success)
3557 return false;
3558 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3559 // there was a match, but an error occurred, in which case, just return that
3560 // the operand parsing failed.
3561 if (ResTy == MatchOperand_ParseFail)
3562 return true;
3563
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003564 DEBUG(dbgs() << ".. Generic Parser\n");
3565
Jack Carterb4dbc172012-09-05 23:34:03 +00003566 switch (getLexer().getKind()) {
3567 default:
3568 Error(Parser.getTok().getLoc(), "unexpected token in operand");
3569 return true;
3570 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003571 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00003572 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00003573
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003574 // Almost all registers have been parsed by custom parsers. There is only
3575 // one exception to this. $zero (and it's alias $0) will reach this point
3576 // for div, divu, and similar instructions because it is not an operand
3577 // to the instruction definition but an explicit register. Special case
3578 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00003579 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00003580 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003581
Jack Carterd0bd6422013-04-18 00:41:53 +00003582 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00003583 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003584 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00003585 return true;
3586
Jack Carter873c7242013-01-12 01:03:14 +00003587 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00003588 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00003589 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00003590 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003591 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00003592
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003593 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003594 return false;
3595 }
Vladimir Medic4c299852013-11-06 11:27:05 +00003596 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00003597 case AsmToken::LParen:
3598 case AsmToken::Minus:
3599 case AsmToken::Plus:
3600 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003601 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00003602 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003603 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003604 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003605 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00003606 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00003607 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003608 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003609 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003610 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00003611 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00003612 return true;
3613
Jack Carter873c7242013-01-12 01:03:14 +00003614 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3615
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003616 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00003617 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003618 } // case AsmToken::Percent
3619 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00003620 return true;
3621}
3622
Vladimir Medic4c299852013-11-06 11:27:05 +00003623const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00003624 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003625 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00003626 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003627 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00003628 // It's a constant, evaluate reloc value.
3629 int16_t Val;
3630 switch (getVariantKind(RelocStr)) {
3631 case MCSymbolRefExpr::VK_Mips_ABS_LO:
3632 // Get the 1st 16-bits.
3633 Val = MCE->getValue() & 0xffff;
3634 break;
3635 case MCSymbolRefExpr::VK_Mips_ABS_HI:
3636 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
3637 // 16 bits being negative.
3638 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
3639 break;
3640 case MCSymbolRefExpr::VK_Mips_HIGHER:
3641 // Get the 3rd 16-bits.
3642 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
3643 break;
3644 case MCSymbolRefExpr::VK_Mips_HIGHEST:
3645 // Get the 4th 16-bits.
3646 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
3647 break;
3648 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00003649 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00003650 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00003651 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003652 }
3653
Jack Carterb5cf5902013-04-17 00:18:04 +00003654 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003655 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00003656 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00003657 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003658 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003659 return Res;
3660 }
3661
3662 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00003663 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
3664
Sasa Stankovic06c47802014-04-03 10:37:45 +00003665 // Try to create target expression.
3666 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00003667 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003668
Jack Carterd0bd6422013-04-18 00:41:53 +00003669 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
3670 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003671 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003672 return Res;
3673 }
3674
3675 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003676 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003677 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00003678 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00003679 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003680 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003681 return Expr;
3682}
3683
3684bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
3685
3686 switch (Expr->getKind()) {
3687 case MCExpr::Constant:
3688 return true;
3689 case MCExpr::SymbolRef:
3690 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
3691 case MCExpr::Binary:
3692 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
3693 if (!isEvaluated(BE->getLHS()))
3694 return false;
3695 return isEvaluated(BE->getRHS());
3696 }
3697 case MCExpr::Unary:
3698 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003699 case MCExpr::Target:
3700 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003701 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003702 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00003703}
Jack Carterd0bd6422013-04-18 00:41:53 +00003704
Jack Carterb5cf5902013-04-17 00:18:04 +00003705bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003706 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003707 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00003708 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00003709 if (Tok.isNot(AsmToken::Identifier))
3710 return true;
3711
Yaron Keren075759a2015-03-30 15:42:36 +00003712 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00003713
Jack Carterd0bd6422013-04-18 00:41:53 +00003714 Parser.Lex(); // Eat the identifier.
3715 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003716 const MCExpr *IdVal;
3717 SMLoc EndLoc;
3718
3719 if (getLexer().getKind() == AsmToken::LParen) {
3720 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003721 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003722 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003723 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003724 const AsmToken &nextTok = Parser.getTok();
3725 if (nextTok.isNot(AsmToken::Identifier))
3726 return true;
3727 Str += "(%";
3728 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00003729 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00003730 if (getLexer().getKind() != AsmToken::LParen)
3731 return true;
3732 } else
3733 break;
3734 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003735 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00003736 return true;
3737
3738 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00003739 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003740
3741 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00003742 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003743
Jack Carterd0bd6422013-04-18 00:41:53 +00003744 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00003745 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003746}
3747
Jack Carterb4dbc172012-09-05 23:34:03 +00003748bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
3749 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003750 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00003751 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003752 if (ResTy == MatchOperand_Success) {
3753 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00003754 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003755 StartLoc = Operand.getStartLoc();
3756 EndLoc = Operand.getEndLoc();
3757
3758 // AFAIK, we only support numeric registers and named GPR's in CFI
3759 // directives.
3760 // Don't worry about eating tokens before failing. Using an unrecognised
3761 // register is a parse error.
3762 if (Operand.isGPRAsmReg()) {
3763 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003764 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003765 }
3766
3767 return (RegNo == (unsigned)-1);
3768 }
3769
3770 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00003771 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00003772}
3773
Jack Carterb5cf5902013-04-17 00:18:04 +00003774bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003775 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00003776 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003777 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003778 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00003779
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003780 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003781 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003782 ++NumOfLParen;
3783 }
Jack Carter873c7242013-01-12 01:03:14 +00003784
Jack Carterd0bd6422013-04-18 00:41:53 +00003785 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003786 default:
3787 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00003788 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00003789 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00003790 case AsmToken::Integer:
3791 case AsmToken::Minus:
3792 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00003793 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003794 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00003795 else
3796 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00003797 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00003798 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003799 break;
Jack Carter873c7242013-01-12 01:03:14 +00003800 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00003801 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003802 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003803 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003804}
3805
David Blaikie960ea3f2014-06-08 16:18:35 +00003806MipsAsmParser::OperandMatchResultTy
3807MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003808 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003809 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00003810 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00003811 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003812 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003813 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00003814 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00003815 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00003816
Jack Carterb5cf5902013-04-17 00:18:04 +00003817 if (getLexer().getKind() == AsmToken::LParen) {
3818 Parser.Lex();
3819 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003820 }
3821
Jack Carterb5cf5902013-04-17 00:18:04 +00003822 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003823 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00003824 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003825
Jack Carterd0bd6422013-04-18 00:41:53 +00003826 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003827 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003828 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003829 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003830 SMLoc E =
3831 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003832 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003833 return MatchOperand_Success;
3834 }
3835 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003836 SMLoc E =
3837 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00003838
Jack Carterd0bd6422013-04-18 00:41:53 +00003839 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003840 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00003841 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003842 S, E, *this);
3843 Operands.push_back(
3844 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003845 return MatchOperand_Success;
3846 }
3847 Error(Parser.getTok().getLoc(), "'(' expected");
3848 return MatchOperand_ParseFail;
3849 }
3850
Jack Carterd0bd6422013-04-18 00:41:53 +00003851 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003852 }
3853
Toma Tabacu13964452014-09-04 13:23:44 +00003854 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003855 if (Res != MatchOperand_Success)
3856 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003857
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003858 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003859 Error(Parser.getTok().getLoc(), "')' expected");
3860 return MatchOperand_ParseFail;
3861 }
3862
Jack Carter873c7242013-01-12 01:03:14 +00003863 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3864
Jack Carterd0bd6422013-04-18 00:41:53 +00003865 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003866
Craig Topper062a2ba2014-04-25 05:30:21 +00003867 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003868 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003869
Jack Carterd0bd6422013-04-18 00:41:53 +00003870 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00003871 std::unique_ptr<MipsOperand> op(
3872 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00003873 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003874 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003875 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00003876 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003877 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
3878 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003879 if (IdVal->evaluateAsAbsolute(Imm))
3880 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003881 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003882 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00003883 getContext());
3884 }
3885
David Blaikie960ea3f2014-06-08 16:18:35 +00003886 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003887 return MatchOperand_Success;
3888}
3889
David Blaikie960ea3f2014-06-08 16:18:35 +00003890bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003891 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00003892 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00003893 if (Sym) {
3894 SMLoc S = Parser.getTok().getLoc();
3895 const MCExpr *Expr;
3896 if (Sym->isVariable())
3897 Expr = Sym->getVariableValue();
3898 else
3899 return false;
3900 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003901 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00003902 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00003903 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003904 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003905 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00003906 if (ResTy == MatchOperand_Success) {
3907 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00003908 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00003909 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003910 llvm_unreachable("Should never ParseFail");
3911 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00003912 }
3913 } else if (Expr->getKind() == MCExpr::Constant) {
3914 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00003915 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00003916 Operands.push_back(
3917 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00003918 return true;
3919 }
3920 }
3921 return false;
3922}
Jack Carterd0bd6422013-04-18 00:41:53 +00003923
Jack Carter873c7242013-01-12 01:03:14 +00003924MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003925MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00003926 StringRef Identifier,
3927 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003928 int Index = matchCPURegisterName(Identifier);
3929 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003930 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003931 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3932 return MatchOperand_Success;
3933 }
3934
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003935 Index = matchHWRegsRegisterName(Identifier);
3936 if (Index != -1) {
3937 Operands.push_back(MipsOperand::createHWRegsReg(
3938 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3939 return MatchOperand_Success;
3940 }
3941
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003942 Index = matchFPURegisterName(Identifier);
3943 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003944 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003945 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3946 return MatchOperand_Success;
3947 }
3948
3949 Index = matchFCCRegisterName(Identifier);
3950 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003951 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003952 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3953 return MatchOperand_Success;
3954 }
3955
3956 Index = matchACRegisterName(Identifier);
3957 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003958 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003959 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3960 return MatchOperand_Success;
3961 }
3962
3963 Index = matchMSA128RegisterName(Identifier);
3964 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003965 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003966 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3967 return MatchOperand_Success;
3968 }
3969
3970 Index = matchMSA128CtrlRegisterName(Identifier);
3971 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003972 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003973 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3974 return MatchOperand_Success;
3975 }
3976
3977 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00003978}
3979
3980MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003981MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003982 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00003983 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003984
3985 if (Token.is(AsmToken::Identifier)) {
3986 DEBUG(dbgs() << ".. identifier\n");
3987 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00003988 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003989 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00003990 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003991 } else if (Token.is(AsmToken::Integer)) {
3992 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003993 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003994 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
3995 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003996 return MatchOperand_Success;
3997 }
3998
3999 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
4000
4001 return MatchOperand_NoMatch;
4002}
4003
David Blaikie960ea3f2014-06-08 16:18:35 +00004004MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004005MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004006 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004007 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004008
4009 auto Token = Parser.getTok();
4010
4011 SMLoc S = Token.getLoc();
4012
4013 if (Token.isNot(AsmToken::Dollar)) {
4014 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4015 if (Token.is(AsmToken::Identifier)) {
4016 if (searchSymbolAlias(Operands))
4017 return MatchOperand_Success;
4018 }
4019 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4020 return MatchOperand_NoMatch;
4021 }
4022 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004023
Toma Tabacu13964452014-09-04 13:23:44 +00004024 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004025 if (ResTy == MatchOperand_Success) {
4026 Parser.Lex(); // $
4027 Parser.Lex(); // identifier
4028 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004029 return ResTy;
4030}
4031
4032MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004033MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004034 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004035 switch (getLexer().getKind()) {
4036 default:
4037 return MatchOperand_NoMatch;
4038 case AsmToken::LParen:
4039 case AsmToken::Minus:
4040 case AsmToken::Plus:
4041 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004042 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004043 case AsmToken::String:
4044 break;
4045 }
4046
4047 const MCExpr *IdVal;
4048 SMLoc S = Parser.getTok().getLoc();
4049 if (getParser().parseExpression(IdVal))
4050 return MatchOperand_ParseFail;
4051
4052 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4053 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4054 return MatchOperand_Success;
4055}
4056
David Blaikie960ea3f2014-06-08 16:18:35 +00004057MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004058MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004059 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004060 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004061
4062 SMLoc S = getLexer().getLoc();
4063
4064 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00004065 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004066 if (ResTy != MatchOperand_NoMatch)
4067 return ResTy;
4068
Daniel Sanders315386c2014-04-01 10:40:14 +00004069 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00004070 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00004071 if (ResTy != MatchOperand_NoMatch)
4072 return ResTy;
4073
Daniel Sandersffd84362014-04-01 10:41:48 +00004074 const MCExpr *Expr = nullptr;
4075 if (Parser.parseExpression(Expr)) {
4076 // We have no way of knowing if a symbol was consumed so we must ParseFail
4077 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004078 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004079 Operands.push_back(
4080 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004081 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004082}
4083
Vladimir Medic2b953d02013-10-01 09:48:56 +00004084MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004085MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004086 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004087 const MCExpr *IdVal;
4088 // If the first token is '$' we may have register operand.
4089 if (Parser.getTok().is(AsmToken::Dollar))
4090 return MatchOperand_NoMatch;
4091 SMLoc S = Parser.getTok().getLoc();
4092 if (getParser().parseExpression(IdVal))
4093 return MatchOperand_ParseFail;
4094 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004095 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004096 int64_t Val = MCE->getValue();
4097 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4098 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004099 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004100 return MatchOperand_Success;
4101}
4102
Matheus Almeida779c5932013-11-18 12:32:49 +00004103MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004104MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004105 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00004106 switch (getLexer().getKind()) {
4107 default:
4108 return MatchOperand_NoMatch;
4109 case AsmToken::LParen:
4110 case AsmToken::Plus:
4111 case AsmToken::Minus:
4112 case AsmToken::Integer:
4113 break;
4114 }
4115
4116 const MCExpr *Expr;
4117 SMLoc S = Parser.getTok().getLoc();
4118
4119 if (getParser().parseExpression(Expr))
4120 return MatchOperand_ParseFail;
4121
4122 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004123 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00004124 Error(S, "expected immediate value");
4125 return MatchOperand_ParseFail;
4126 }
4127
4128 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
4129 // and because the CPU always adds one to the immediate field, the allowed
4130 // range becomes 1..4. We'll only check the range here and will deal
4131 // with the addition/subtraction when actually decoding/encoding
4132 // the instruction.
4133 if (Val < 1 || Val > 4) {
4134 Error(S, "immediate not in range (1..4)");
4135 return MatchOperand_ParseFail;
4136 }
4137
Jack Carter3b2c96e2014-01-22 23:31:38 +00004138 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004139 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00004140 return MatchOperand_Success;
4141}
4142
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004143MipsAsmParser::OperandMatchResultTy
4144MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4145 MCAsmParser &Parser = getParser();
4146 SmallVector<unsigned, 10> Regs;
4147 unsigned RegNo;
4148 unsigned PrevReg = Mips::NoRegister;
4149 bool RegRange = false;
4150 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4151
4152 if (Parser.getTok().isNot(AsmToken::Dollar))
4153 return MatchOperand_ParseFail;
4154
4155 SMLoc S = Parser.getTok().getLoc();
4156 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4157 SMLoc E = getLexer().getLoc();
4158 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4159 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4160 if (RegRange) {
4161 // Remove last register operand because registers from register range
4162 // should be inserted first.
4163 if (RegNo == Mips::RA) {
4164 Regs.push_back(RegNo);
4165 } else {
4166 unsigned TmpReg = PrevReg + 1;
4167 while (TmpReg <= RegNo) {
4168 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
4169 Error(E, "invalid register operand");
4170 return MatchOperand_ParseFail;
4171 }
4172
4173 PrevReg = TmpReg;
4174 Regs.push_back(TmpReg++);
4175 }
4176 }
4177
4178 RegRange = false;
4179 } else {
4180 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
4181 (RegNo != Mips::RA)) {
4182 Error(E, "$16 or $31 expected");
4183 return MatchOperand_ParseFail;
4184 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
4185 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
4186 Error(E, "invalid register operand");
4187 return MatchOperand_ParseFail;
4188 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
4189 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
4190 Error(E, "consecutive register numbers expected");
4191 return MatchOperand_ParseFail;
4192 }
4193
4194 Regs.push_back(RegNo);
4195 }
4196
4197 if (Parser.getTok().is(AsmToken::Minus))
4198 RegRange = true;
4199
4200 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4201 !Parser.getTok().isNot(AsmToken::Comma)) {
4202 Error(E, "',' or '-' expected");
4203 return MatchOperand_ParseFail;
4204 }
4205
4206 Lex(); // Consume comma or minus
4207 if (Parser.getTok().isNot(AsmToken::Dollar))
4208 break;
4209
4210 PrevReg = RegNo;
4211 }
4212
4213 SMLoc E = Parser.getTok().getLoc();
4214 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4215 parseMemOperand(Operands);
4216 return MatchOperand_Success;
4217}
4218
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004219MipsAsmParser::OperandMatchResultTy
4220MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4221 MCAsmParser &Parser = getParser();
4222
4223 SMLoc S = Parser.getTok().getLoc();
4224 if (parseAnyRegister(Operands) != MatchOperand_Success)
4225 return MatchOperand_ParseFail;
4226
4227 SMLoc E = Parser.getTok().getLoc();
4228 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
4229 unsigned Reg = Op.getGPR32Reg();
4230 Operands.pop_back();
4231 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
4232 return MatchOperand_Success;
4233}
4234
Zoran Jovanovic41688672015-02-10 16:36:20 +00004235MipsAsmParser::OperandMatchResultTy
4236MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4237 MCAsmParser &Parser = getParser();
4238 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4239 SmallVector<unsigned, 10> Regs;
4240
4241 if (Parser.getTok().isNot(AsmToken::Dollar))
4242 return MatchOperand_ParseFail;
4243
4244 SMLoc S = Parser.getTok().getLoc();
4245
4246 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4247 return MatchOperand_ParseFail;
4248
4249 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4250 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4251 Regs.push_back(RegNo);
4252
4253 SMLoc E = Parser.getTok().getLoc();
4254 if (Parser.getTok().isNot(AsmToken::Comma)) {
4255 Error(E, "',' expected");
4256 return MatchOperand_ParseFail;
4257 }
4258
4259 // Remove comma.
4260 Parser.Lex();
4261
4262 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4263 return MatchOperand_ParseFail;
4264
4265 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4266 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4267 Regs.push_back(RegNo);
4268
4269 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4270
4271 return MatchOperand_Success;
4272}
4273
Jack Carterdc1e35d2012-09-06 20:00:02 +00004274MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
4275
Vladimir Medic4c299852013-11-06 11:27:05 +00004276 MCSymbolRefExpr::VariantKind VK =
4277 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
4278 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
4279 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
4280 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
4281 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
4282 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
4283 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
4284 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
4285 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
4286 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
4287 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
4288 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
4289 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
4290 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
4291 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
4292 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
4293 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
4294 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00004295 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
4296 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
4297 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
4298 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
4299 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
4300 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00004301 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
4302 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00004303 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004304
Matheus Almeida2852af82014-04-22 10:15:54 +00004305 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00004306
Jack Carterdc1e35d2012-09-06 20:00:02 +00004307 return VK;
4308}
Jack Cartera63b16a2012-09-07 00:23:42 +00004309
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004310/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4311/// either this.
4312/// ::= '(', register, ')'
4313/// handle it before we iterate so we don't get tripped up by the lack of
4314/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004315bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004316 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004317 if (getLexer().is(AsmToken::LParen)) {
4318 Operands.push_back(
4319 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4320 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004321 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004322 SMLoc Loc = getLexer().getLoc();
4323 Parser.eatToEndOfStatement();
4324 return Error(Loc, "unexpected token in argument list");
4325 }
4326 if (Parser.getTok().isNot(AsmToken::RParen)) {
4327 SMLoc Loc = getLexer().getLoc();
4328 Parser.eatToEndOfStatement();
4329 return Error(Loc, "unexpected token, expected ')'");
4330 }
4331 Operands.push_back(
4332 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4333 Parser.Lex();
4334 }
4335 return false;
4336}
4337
4338/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4339/// either one of these.
4340/// ::= '[', register, ']'
4341/// ::= '[', integer, ']'
4342/// handle it before we iterate so we don't get tripped up by the lack of
4343/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004344bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004345 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004346 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004347 if (getLexer().is(AsmToken::LBrac)) {
4348 Operands.push_back(
4349 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4350 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004351 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004352 SMLoc Loc = getLexer().getLoc();
4353 Parser.eatToEndOfStatement();
4354 return Error(Loc, "unexpected token in argument list");
4355 }
4356 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4357 SMLoc Loc = getLexer().getLoc();
4358 Parser.eatToEndOfStatement();
4359 return Error(Loc, "unexpected token, expected ']'");
4360 }
4361 Operands.push_back(
4362 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4363 Parser.Lex();
4364 }
4365 return false;
4366}
4367
David Blaikie960ea3f2014-06-08 16:18:35 +00004368bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4369 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004370 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004371 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004372
4373 // We have reached first instruction, module directive are now forbidden.
4374 getTargetStreamer().forbidModuleDirective();
4375
Vladimir Medic74593e62013-07-17 15:00:42 +00004376 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004377 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004378 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004379 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004380 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004381 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004382 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004383
4384 // Read the remaining operands.
4385 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4386 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004387 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004388 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004389 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004390 return Error(Loc, "unexpected token in argument list");
4391 }
Toma Tabacu13964452014-09-04 13:23:44 +00004392 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004393 return true;
4394 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004395
Jack Carterd0bd6422013-04-18 00:41:53 +00004396 while (getLexer().is(AsmToken::Comma)) {
4397 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004398 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004399 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004400 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004401 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004402 return Error(Loc, "unexpected token in argument list");
4403 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004404 // Parse bracket and parenthesis suffixes before we iterate
4405 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004406 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004407 return true;
4408 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004409 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004410 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004411 }
4412 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004413 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4414 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004415 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004416 return Error(Loc, "unexpected token in argument list");
4417 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004418 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004419 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004420}
4421
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004422bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004423 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004424 SMLoc Loc = getLexer().getLoc();
4425 Parser.eatToEndOfStatement();
4426 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004427}
4428
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004429bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004430 return Error(Loc, ErrorMsg);
4431}
4432
Jack Carter0b744b32012-10-04 02:29:46 +00004433bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004434 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004435 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004436
4437 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004438 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004439
4440 Parser.Lex(); // Eat "noat".
4441
Jack Carterd0bd6422013-04-18 00:41:53 +00004442 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004443 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004444 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004445 return false;
4446 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004447
4448 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004449 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004450 return false;
4451}
Jack Carterd0bd6422013-04-18 00:41:53 +00004452
Jack Carter0b744b32012-10-04 02:29:46 +00004453bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004454 // Line can be: ".set at", which sets $at to $1
4455 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004456 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004457 Parser.Lex(); // Eat "at".
4458
Jack Carter0b744b32012-10-04 02:29:46 +00004459 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004460 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004461 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004462
4463 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004464 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004465 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004466 }
4467
4468 if (getLexer().isNot(AsmToken::Equal)) {
4469 reportParseError("unexpected token, expected equals sign");
4470 return false;
4471 }
4472 Parser.Lex(); // Eat "=".
4473
4474 if (getLexer().isNot(AsmToken::Dollar)) {
4475 if (getLexer().is(AsmToken::EndOfStatement)) {
4476 reportParseError("no register specified");
4477 return false;
4478 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004479 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004480 return false;
4481 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004482 }
4483 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004484
Toma Tabacu16a74492015-02-13 10:30:57 +00004485 // Find out what "reg" is.
4486 unsigned AtRegNo;
4487 const AsmToken &Reg = Parser.getTok();
4488 if (Reg.is(AsmToken::Identifier)) {
4489 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4490 } else if (Reg.is(AsmToken::Integer)) {
4491 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004492 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004493 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004494 return false;
4495 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004496
4497 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004498 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004499 reportParseError("invalid register");
4500 return false;
4501 }
4502 Parser.Lex(); // Eat "reg".
4503
4504 // If this is not the end of the statement, report an error.
4505 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4506 reportParseError("unexpected token, expected end of statement");
4507 return false;
4508 }
4509
4510 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4511
4512 Parser.Lex(); // Consume the EndOfStatement.
4513 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004514}
4515
4516bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004517 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004518 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004519 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004520 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004521 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004522 return false;
4523 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004524 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004525 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004526 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004527 return false;
4528}
4529
4530bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004531 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004532 Parser.Lex();
4533 // If this is not the end of the statement, report an error.
4534 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004535 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004536 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00004537 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004538 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00004539 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004540 Parser.Lex(); // Consume the EndOfStatement.
4541 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004542}
4543
4544bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004545 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004546 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004547 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004548 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004549 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004550 return false;
4551 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004552 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004553 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004554 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004555 return false;
4556}
4557
4558bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004559 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004560 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004561 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004562 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004563 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004564 return false;
4565 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004566 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00004567 reportParseError("`noreorder' must be set before `nomacro'");
4568 return false;
4569 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004570 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004571 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004572 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004573 return false;
4574}
Jack Carterd76b2372013-03-21 21:44:16 +00004575
Daniel Sanders44934432014-08-07 12:03:36 +00004576bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004577 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004578 Parser.Lex();
4579
4580 // If this is not the end of the statement, report an error.
4581 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004582 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004583
4584 setFeatureBits(Mips::FeatureMSA, "msa");
4585 getTargetStreamer().emitDirectiveSetMsa();
4586 return false;
4587}
4588
4589bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004590 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004591 Parser.Lex();
4592
4593 // If this is not the end of the statement, report an error.
4594 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004595 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004596
4597 clearFeatureBits(Mips::FeatureMSA, "msa");
4598 getTargetStreamer().emitDirectiveSetNoMsa();
4599 return false;
4600}
4601
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004602bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004603 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004604 Parser.Lex(); // Eat "nodsp".
4605
4606 // If this is not the end of the statement, report an error.
4607 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4608 reportParseError("unexpected token, expected end of statement");
4609 return false;
4610 }
4611
4612 clearFeatureBits(Mips::FeatureDSP, "dsp");
4613 getTargetStreamer().emitDirectiveSetNoDsp();
4614 return false;
4615}
4616
Toma Tabacucc2502d2014-11-04 17:18:07 +00004617bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004618 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004619 Parser.Lex(); // Eat "mips16".
4620
Jack Carter39536722014-01-22 23:08:42 +00004621 // If this is not the end of the statement, report an error.
4622 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004623 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00004624 return false;
4625 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00004626
4627 setFeatureBits(Mips::FeatureMips16, "mips16");
4628 getTargetStreamer().emitDirectiveSetMips16();
4629 Parser.Lex(); // Consume the EndOfStatement.
4630 return false;
4631}
4632
4633bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004634 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004635 Parser.Lex(); // Eat "nomips16".
4636
4637 // If this is not the end of the statement, report an error.
4638 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4639 reportParseError("unexpected token, expected end of statement");
4640 return false;
4641 }
4642
4643 clearFeatureBits(Mips::FeatureMips16, "mips16");
4644 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00004645 Parser.Lex(); // Consume the EndOfStatement.
4646 return false;
4647}
4648
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004649bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004650 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004651 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004652 // Line can be: .set fp=32
4653 // .set fp=xx
4654 // .set fp=64
4655 Parser.Lex(); // Eat fp token
4656 AsmToken Tok = Parser.getTok();
4657 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004658 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004659 return false;
4660 }
4661 Parser.Lex(); // Eat '=' token.
4662 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004663
4664 if (!parseFpABIValue(FpAbiVal, ".set"))
4665 return false;
4666
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004667 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004668 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004669 return false;
4670 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004671 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004672 Parser.Lex(); // Consume the EndOfStatement.
4673 return false;
4674}
4675
Toma Tabacu32c72aa2015-06-30 09:36:50 +00004676bool MipsAsmParser::parseSetOddSPRegDirective() {
4677 MCAsmParser &Parser = getParser();
4678
4679 Parser.Lex(); // Eat "oddspreg".
4680 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4681 reportParseError("unexpected token, expected end of statement");
4682 return false;
4683 }
4684
4685 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4686 getTargetStreamer().emitDirectiveSetOddSPReg();
4687 return false;
4688}
4689
4690bool MipsAsmParser::parseSetNoOddSPRegDirective() {
4691 MCAsmParser &Parser = getParser();
4692
4693 Parser.Lex(); // Eat "nooddspreg".
4694 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4695 reportParseError("unexpected token, expected end of statement");
4696 return false;
4697 }
4698
4699 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4700 getTargetStreamer().emitDirectiveSetNoOddSPReg();
4701 return false;
4702}
4703
Toma Tabacu9db22db2014-09-09 10:15:38 +00004704bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004705 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004706 SMLoc Loc = getLexer().getLoc();
4707
4708 Parser.Lex();
4709 if (getLexer().isNot(AsmToken::EndOfStatement))
4710 return reportParseError("unexpected token, expected end of statement");
4711
4712 // Always keep an element on the options "stack" to prevent the user
4713 // from changing the initial options. This is how we remember them.
4714 if (AssemblerOptions.size() == 2)
4715 return reportParseError(Loc, ".set pop with no .set push");
4716
4717 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00004718 setAvailableFeatures(
4719 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
4720 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00004721
4722 getTargetStreamer().emitDirectiveSetPop();
4723 return false;
4724}
4725
4726bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004727 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004728 Parser.Lex();
4729 if (getLexer().isNot(AsmToken::EndOfStatement))
4730 return reportParseError("unexpected token, expected end of statement");
4731
4732 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00004733 AssemblerOptions.push_back(
4734 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00004735
4736 getTargetStreamer().emitDirectiveSetPush();
4737 return false;
4738}
4739
Toma Tabacu29696502015-06-02 09:48:04 +00004740bool MipsAsmParser::parseSetSoftFloatDirective() {
4741 MCAsmParser &Parser = getParser();
4742 Parser.Lex();
4743 if (getLexer().isNot(AsmToken::EndOfStatement))
4744 return reportParseError("unexpected token, expected end of statement");
4745
4746 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4747 getTargetStreamer().emitDirectiveSetSoftFloat();
4748 return false;
4749}
4750
4751bool MipsAsmParser::parseSetHardFloatDirective() {
4752 MCAsmParser &Parser = getParser();
4753 Parser.Lex();
4754 if (getLexer().isNot(AsmToken::EndOfStatement))
4755 return reportParseError("unexpected token, expected end of statement");
4756
4757 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4758 getTargetStreamer().emitDirectiveSetHardFloat();
4759 return false;
4760}
4761
Jack Carterd76b2372013-03-21 21:44:16 +00004762bool MipsAsmParser::parseSetAssignment() {
4763 StringRef Name;
4764 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00004765 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00004766
4767 if (Parser.parseIdentifier(Name))
4768 reportParseError("expected identifier after .set");
4769
4770 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004771 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00004772 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00004773
Jack Carter3b2c96e2014-01-22 23:31:38 +00004774 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00004775 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00004776
Jim Grosbach6f482002015-05-18 18:43:14 +00004777 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00004778 Sym->setVariableValue(Value);
4779
4780 return false;
4781}
Jack Carterd0bd6422013-04-18 00:41:53 +00004782
Toma Tabacu26647792014-09-09 12:52:14 +00004783bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004784 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00004785 Parser.Lex();
4786 if (getLexer().isNot(AsmToken::EndOfStatement))
4787 return reportParseError("unexpected token, expected end of statement");
4788
4789 // Reset assembler options to their initial values.
Toma Tabacu465acfd2015-06-09 13:33:26 +00004790 setAvailableFeatures(
4791 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
4792 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00004793 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
4794
4795 getTargetStreamer().emitDirectiveSetMips0();
4796 return false;
4797}
4798
Toma Tabacu85618b32014-08-19 14:22:52 +00004799bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004800 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00004801 Parser.Lex();
4802 if (getLexer().isNot(AsmToken::Equal))
4803 return reportParseError("unexpected token, expected equals sign");
4804
4805 Parser.Lex();
4806 StringRef Arch;
4807 if (Parser.parseIdentifier(Arch))
4808 return reportParseError("expected arch identifier");
4809
4810 StringRef ArchFeatureName =
4811 StringSwitch<StringRef>(Arch)
4812 .Case("mips1", "mips1")
4813 .Case("mips2", "mips2")
4814 .Case("mips3", "mips3")
4815 .Case("mips4", "mips4")
4816 .Case("mips5", "mips5")
4817 .Case("mips32", "mips32")
4818 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004819 .Case("mips32r3", "mips32r3")
4820 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004821 .Case("mips32r6", "mips32r6")
4822 .Case("mips64", "mips64")
4823 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004824 .Case("mips64r3", "mips64r3")
4825 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004826 .Case("mips64r6", "mips64r6")
4827 .Case("cnmips", "cnmips")
4828 .Case("r4000", "mips3") // This is an implementation of Mips3.
4829 .Default("");
4830
4831 if (ArchFeatureName.empty())
4832 return reportParseError("unsupported architecture");
4833
4834 selectArch(ArchFeatureName);
4835 getTargetStreamer().emitDirectiveSetArch(Arch);
4836 return false;
4837}
4838
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004839bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004840 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004841 Parser.Lex();
4842 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004843 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004844
Matheus Almeida2852af82014-04-22 10:15:54 +00004845 switch (Feature) {
4846 default:
4847 llvm_unreachable("Unimplemented feature");
4848 case Mips::FeatureDSP:
4849 setFeatureBits(Mips::FeatureDSP, "dsp");
4850 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004851 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004852 case Mips::FeatureMicroMips:
4853 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004854 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004855 case Mips::FeatureMips1:
4856 selectArch("mips1");
4857 getTargetStreamer().emitDirectiveSetMips1();
4858 break;
4859 case Mips::FeatureMips2:
4860 selectArch("mips2");
4861 getTargetStreamer().emitDirectiveSetMips2();
4862 break;
4863 case Mips::FeatureMips3:
4864 selectArch("mips3");
4865 getTargetStreamer().emitDirectiveSetMips3();
4866 break;
4867 case Mips::FeatureMips4:
4868 selectArch("mips4");
4869 getTargetStreamer().emitDirectiveSetMips4();
4870 break;
4871 case Mips::FeatureMips5:
4872 selectArch("mips5");
4873 getTargetStreamer().emitDirectiveSetMips5();
4874 break;
4875 case Mips::FeatureMips32:
4876 selectArch("mips32");
4877 getTargetStreamer().emitDirectiveSetMips32();
4878 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004879 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004880 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004881 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004882 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004883 case Mips::FeatureMips32r3:
4884 selectArch("mips32r3");
4885 getTargetStreamer().emitDirectiveSetMips32R3();
4886 break;
4887 case Mips::FeatureMips32r5:
4888 selectArch("mips32r5");
4889 getTargetStreamer().emitDirectiveSetMips32R5();
4890 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004891 case Mips::FeatureMips32r6:
4892 selectArch("mips32r6");
4893 getTargetStreamer().emitDirectiveSetMips32R6();
4894 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004895 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004896 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00004897 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00004898 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004899 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004900 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004901 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00004902 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004903 case Mips::FeatureMips64r3:
4904 selectArch("mips64r3");
4905 getTargetStreamer().emitDirectiveSetMips64R3();
4906 break;
4907 case Mips::FeatureMips64r5:
4908 selectArch("mips64r5");
4909 getTargetStreamer().emitDirectiveSetMips64R5();
4910 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004911 case Mips::FeatureMips64r6:
4912 selectArch("mips64r6");
4913 getTargetStreamer().emitDirectiveSetMips64R6();
4914 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004915 }
4916 return false;
4917}
4918
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004919bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004920 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004921 if (getLexer().isNot(AsmToken::Comma)) {
4922 SMLoc Loc = getLexer().getLoc();
4923 Parser.eatToEndOfStatement();
4924 return Error(Loc, ErrorStr);
4925 }
4926
Matheus Almeida2852af82014-04-22 10:15:54 +00004927 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004928 return true;
4929}
4930
Daniel Sanderse2982ad2015-09-17 16:08:39 +00004931// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
4932// In this class, it is only used for .cprestore.
4933// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
4934// MipsTargetELFStreamer and MipsAsmParser.
4935bool MipsAsmParser::isPicAndNotNxxAbi() {
4936 return inPicMode() && !(isABI_N32() || isABI_N64());
4937}
4938
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004939bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00004940 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00004941 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004942
Toma Tabacudde4c462014-11-06 10:02:45 +00004943 if (inMips16Mode()) {
4944 reportParseError(".cpload is not supported in Mips16 mode");
4945 return false;
4946 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004947
David Blaikie960ea3f2014-06-08 16:18:35 +00004948 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00004949 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004950 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4951 reportParseError("expected register containing function address");
4952 return false;
4953 }
4954
David Blaikie960ea3f2014-06-08 16:18:35 +00004955 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
4956 if (!RegOpnd.isGPRAsmReg()) {
4957 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004958 return false;
4959 }
4960
Toma Tabacudde4c462014-11-06 10:02:45 +00004961 // If this is not the end of the statement, report an error.
4962 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4963 reportParseError("unexpected token, expected end of statement");
4964 return false;
4965 }
4966
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004967 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004968 return false;
4969}
4970
Daniel Sanderse2982ad2015-09-17 16:08:39 +00004971bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
4972 MCAsmParser &Parser = getParser();
4973
4974 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
4975 // is used in non-PIC mode.
4976
4977 if (inMips16Mode()) {
4978 reportParseError(".cprestore is not supported in Mips16 mode");
4979 return false;
4980 }
4981
4982 // Get the stack offset value.
4983 const MCExpr *StackOffset;
4984 int64_t StackOffsetVal;
4985 if (Parser.parseExpression(StackOffset)) {
4986 reportParseError("expected stack offset value");
4987 return false;
4988 }
4989
4990 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
4991 reportParseError("stack offset is not an absolute expression");
4992 return false;
4993 }
4994
4995 if (StackOffsetVal < 0) {
4996 Warning(Loc, ".cprestore with negative stack offset has no effect");
4997 IsCpRestoreSet = false;
4998 } else {
4999 IsCpRestoreSet = true;
5000 CpRestoreOffset = StackOffsetVal;
5001 }
5002
5003 // If this is not the end of the statement, report an error.
5004 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5005 reportParseError("unexpected token, expected end of statement");
5006 return false;
5007 }
5008
5009 // Store the $gp on the stack.
5010 SmallVector<MCInst, 3> StoreInsts;
5011 createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc,
5012 StoreInsts);
5013
5014 getTargetStreamer().emitDirectiveCpRestore(StoreInsts, CpRestoreOffset);
5015 Parser.Lex(); // Consume the EndOfStatement.
5016 return false;
5017}
5018
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005019bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005020 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005021 unsigned FuncReg;
5022 unsigned Save;
5023 bool SaveIsReg = true;
5024
Matheus Almeida7e815762014-06-18 13:08:59 +00005025 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005026 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005027 if (ResTy == MatchOperand_NoMatch) {
5028 reportParseError("expected register containing function address");
5029 Parser.eatToEndOfStatement();
5030 return false;
5031 }
5032
5033 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5034 if (!FuncRegOpnd.isGPRAsmReg()) {
5035 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
5036 Parser.eatToEndOfStatement();
5037 return false;
5038 }
5039
5040 FuncReg = FuncRegOpnd.getGPR32Reg();
5041 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005042
Toma Tabacu65f10572014-09-16 15:00:52 +00005043 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005044 return true;
5045
Toma Tabacu13964452014-09-04 13:23:44 +00005046 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005047 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005048 const MCExpr *OffsetExpr;
5049 int64_t OffsetVal;
5050 SMLoc ExprLoc = getLexer().getLoc();
5051
5052 if (Parser.parseExpression(OffsetExpr) ||
5053 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5054 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005055 Parser.eatToEndOfStatement();
5056 return false;
5057 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005058
5059 Save = OffsetVal;
5060 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005061 } else {
5062 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5063 if (!SaveOpnd.isGPRAsmReg()) {
5064 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5065 Parser.eatToEndOfStatement();
5066 return false;
5067 }
5068 Save = SaveOpnd.getGPR32Reg();
5069 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005070
Toma Tabacu65f10572014-09-16 15:00:52 +00005071 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005072 return true;
5073
Toma Tabacu8874eac2015-02-18 13:46:53 +00005074 const MCExpr *Expr;
5075 if (Parser.parseExpression(Expr)) {
5076 reportParseError("expected expression");
5077 return false;
5078 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005079
Toma Tabacu8874eac2015-02-18 13:46:53 +00005080 if (Expr->getKind() != MCExpr::SymbolRef) {
5081 reportParseError("expected symbol");
5082 return false;
5083 }
5084 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5085
Daniel Sandersf173dda2015-09-22 10:50:09 +00005086 CpSaveLocation = Save;
5087 CpSaveLocationIsRegister = SaveIsReg;
5088
Toma Tabacu8874eac2015-02-18 13:46:53 +00005089 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5090 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005091 return false;
5092}
5093
Daniel Sandersf173dda2015-09-22 10:50:09 +00005094bool MipsAsmParser::parseDirectiveCPReturn() {
5095 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5096 CpSaveLocationIsRegister);
5097 return false;
5098}
5099
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005100bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005101 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005102 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5103 const AsmToken &Tok = Parser.getTok();
5104
5105 if (Tok.getString() == "2008") {
5106 Parser.Lex();
5107 getTargetStreamer().emitDirectiveNaN2008();
5108 return false;
5109 } else if (Tok.getString() == "legacy") {
5110 Parser.Lex();
5111 getTargetStreamer().emitDirectiveNaNLegacy();
5112 return false;
5113 }
5114 }
5115 // If we don't recognize the option passed to the .nan
5116 // directive (e.g. no option or unknown option), emit an error.
5117 reportParseError("invalid option in .nan directive");
5118 return false;
5119}
5120
Jack Carter0b744b32012-10-04 02:29:46 +00005121bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005122 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005123 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005124 const AsmToken &Tok = Parser.getTok();
5125
5126 if (Tok.getString() == "noat") {
5127 return parseSetNoAtDirective();
5128 } else if (Tok.getString() == "at") {
5129 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005130 } else if (Tok.getString() == "arch") {
5131 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005132 } else if (Tok.getString() == "fp") {
5133 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005134 } else if (Tok.getString() == "oddspreg") {
5135 return parseSetOddSPRegDirective();
5136 } else if (Tok.getString() == "nooddspreg") {
5137 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005138 } else if (Tok.getString() == "pop") {
5139 return parseSetPopDirective();
5140 } else if (Tok.getString() == "push") {
5141 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005142 } else if (Tok.getString() == "reorder") {
5143 return parseSetReorderDirective();
5144 } else if (Tok.getString() == "noreorder") {
5145 return parseSetNoReorderDirective();
5146 } else if (Tok.getString() == "macro") {
5147 return parseSetMacroDirective();
5148 } else if (Tok.getString() == "nomacro") {
5149 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005150 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005151 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005152 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005153 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005154 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005155 getTargetStreamer().emitDirectiveSetNoMicroMips();
5156 Parser.eatToEndOfStatement();
5157 return false;
5158 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005159 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005160 } else if (Tok.getString() == "mips0") {
5161 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005162 } else if (Tok.getString() == "mips1") {
5163 return parseSetFeature(Mips::FeatureMips1);
5164 } else if (Tok.getString() == "mips2") {
5165 return parseSetFeature(Mips::FeatureMips2);
5166 } else if (Tok.getString() == "mips3") {
5167 return parseSetFeature(Mips::FeatureMips3);
5168 } else if (Tok.getString() == "mips4") {
5169 return parseSetFeature(Mips::FeatureMips4);
5170 } else if (Tok.getString() == "mips5") {
5171 return parseSetFeature(Mips::FeatureMips5);
5172 } else if (Tok.getString() == "mips32") {
5173 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005174 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005175 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005176 } else if (Tok.getString() == "mips32r3") {
5177 return parseSetFeature(Mips::FeatureMips32r3);
5178 } else if (Tok.getString() == "mips32r5") {
5179 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005180 } else if (Tok.getString() == "mips32r6") {
5181 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005182 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005183 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005184 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005185 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005186 } else if (Tok.getString() == "mips64r3") {
5187 return parseSetFeature(Mips::FeatureMips64r3);
5188 } else if (Tok.getString() == "mips64r5") {
5189 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005190 } else if (Tok.getString() == "mips64r6") {
5191 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005192 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005193 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005194 } else if (Tok.getString() == "nodsp") {
5195 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005196 } else if (Tok.getString() == "msa") {
5197 return parseSetMsaDirective();
5198 } else if (Tok.getString() == "nomsa") {
5199 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005200 } else if (Tok.getString() == "softfloat") {
5201 return parseSetSoftFloatDirective();
5202 } else if (Tok.getString() == "hardfloat") {
5203 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005204 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005205 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005206 parseSetAssignment();
5207 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005208 }
Jack Carter07c818d2013-01-25 01:31:34 +00005209
Jack Carter0b744b32012-10-04 02:29:46 +00005210 return true;
5211}
5212
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005213/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005214/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005215bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005216 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005217 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5218 for (;;) {
5219 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005220 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005221 return true;
5222
5223 getParser().getStreamer().EmitValue(Value, Size);
5224
5225 if (getLexer().is(AsmToken::EndOfStatement))
5226 break;
5227
Jack Carter07c818d2013-01-25 01:31:34 +00005228 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005229 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005230 Parser.Lex();
5231 }
5232 }
5233
5234 Parser.Lex();
5235 return false;
5236}
5237
Vladimir Medic4c299852013-11-06 11:27:05 +00005238/// parseDirectiveGpWord
5239/// ::= .gpword local_sym
5240bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005241 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005242 const MCExpr *Value;
5243 // EmitGPRel32Value requires an expression, so we are using base class
5244 // method to evaluate the expression.
5245 if (getParser().parseExpression(Value))
5246 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005247 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005248
Vladimir Medice10c1122013-11-13 13:18:04 +00005249 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005250 return Error(getLexer().getLoc(),
5251 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005252 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005253 return false;
5254}
5255
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005256/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005257/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005258bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005259 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005260 const MCExpr *Value;
5261 // EmitGPRel64Value requires an expression, so we are using base class
5262 // method to evaluate the expression.
5263 if (getParser().parseExpression(Value))
5264 return true;
5265 getParser().getStreamer().EmitGPRel64Value(Value);
5266
5267 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005268 return Error(getLexer().getLoc(),
5269 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005270 Parser.Lex(); // Eat EndOfStatement token.
5271 return false;
5272}
5273
Jack Carter0cd3c192014-01-06 23:27:31 +00005274bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005275 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005276 // Get the option token.
5277 AsmToken Tok = Parser.getTok();
5278 // At the moment only identifiers are supported.
5279 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005280 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005281 Parser.eatToEndOfStatement();
5282 return false;
5283 }
5284
5285 StringRef Option = Tok.getIdentifier();
5286
5287 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005288 // MipsAsmParser needs to know if the current PIC mode changes.
5289 IsPicEnabled = false;
5290
Jack Carter0cd3c192014-01-06 23:27:31 +00005291 getTargetStreamer().emitDirectiveOptionPic0();
5292 Parser.Lex();
5293 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5294 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005295 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005296 Parser.eatToEndOfStatement();
5297 }
5298 return false;
5299 }
5300
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005301 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005302 // MipsAsmParser needs to know if the current PIC mode changes.
5303 IsPicEnabled = true;
5304
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005305 getTargetStreamer().emitDirectiveOptionPic2();
5306 Parser.Lex();
5307 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5308 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005309 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005310 Parser.eatToEndOfStatement();
5311 }
5312 return false;
5313 }
5314
Jack Carter0cd3c192014-01-06 23:27:31 +00005315 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005316 Warning(Parser.getTok().getLoc(),
5317 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005318 Parser.eatToEndOfStatement();
5319 return false;
5320}
5321
Toma Tabacu9ca50962015-04-16 09:53:47 +00005322/// parseInsnDirective
5323/// ::= .insn
5324bool MipsAsmParser::parseInsnDirective() {
5325 // If this is not the end of the statement, report an error.
5326 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5327 reportParseError("unexpected token, expected end of statement");
5328 return false;
5329 }
5330
5331 // The actual label marking happens in
5332 // MipsELFStreamer::createPendingLabelRelocs().
5333 getTargetStreamer().emitDirectiveInsn();
5334
5335 getParser().Lex(); // Eat EndOfStatement token.
5336 return false;
5337}
5338
Daniel Sanders7e527422014-07-10 13:38:23 +00005339/// parseDirectiveModule
5340/// ::= .module oddspreg
5341/// ::= .module nooddspreg
5342/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005343/// ::= .module softfloat
5344/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005345bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005346 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005347 MCAsmLexer &Lexer = getLexer();
5348 SMLoc L = Lexer.getLoc();
5349
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005350 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005351 // TODO : get a better message.
5352 reportParseError(".module directive must appear before any code");
5353 return false;
5354 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005355
Toma Tabacuc405c822015-01-23 10:40:19 +00005356 StringRef Option;
5357 if (Parser.parseIdentifier(Option)) {
5358 reportParseError("expected .module option identifier");
5359 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005360 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005361
Toma Tabacuc405c822015-01-23 10:40:19 +00005362 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005363 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005364
Toma Tabacu3c499582015-06-25 10:56:57 +00005365 // Synchronize the abiflags information with the FeatureBits information we
5366 // changed above.
5367 getTargetStreamer().updateABIInfo(*this);
5368
5369 // If printing assembly, use the recently updated abiflags information.
5370 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5371 // emitted at the end).
5372 getTargetStreamer().emitDirectiveModuleOddSPReg();
5373
Toma Tabacuc405c822015-01-23 10:40:19 +00005374 // If this is not the end of the statement, report an error.
5375 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5376 reportParseError("unexpected token, expected end of statement");
5377 return false;
5378 }
5379
5380 return false; // parseDirectiveModule has finished successfully.
5381 } else if (Option == "nooddspreg") {
5382 if (!isABI_O32()) {
5383 Error(L, "'.module nooddspreg' requires the O32 ABI");
5384 return false;
5385 }
5386
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005387 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005388
Toma Tabacu3c499582015-06-25 10:56:57 +00005389 // Synchronize the abiflags information with the FeatureBits information we
5390 // changed above.
5391 getTargetStreamer().updateABIInfo(*this);
5392
5393 // If printing assembly, use the recently updated abiflags information.
5394 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5395 // emitted at the end).
5396 getTargetStreamer().emitDirectiveModuleOddSPReg();
5397
Toma Tabacuc405c822015-01-23 10:40:19 +00005398 // If this is not the end of the statement, report an error.
5399 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5400 reportParseError("unexpected token, expected end of statement");
5401 return false;
5402 }
5403
5404 return false; // parseDirectiveModule has finished successfully.
5405 } else if (Option == "fp") {
5406 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005407 } else if (Option == "softfloat") {
5408 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5409
5410 // Synchronize the ABI Flags information with the FeatureBits information we
5411 // updated above.
5412 getTargetStreamer().updateABIInfo(*this);
5413
5414 // If printing assembly, use the recently updated ABI Flags information.
5415 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5416 // emitted later).
5417 getTargetStreamer().emitDirectiveModuleSoftFloat();
5418
5419 // If this is not the end of the statement, report an error.
5420 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5421 reportParseError("unexpected token, expected end of statement");
5422 return false;
5423 }
5424
5425 return false; // parseDirectiveModule has finished successfully.
5426 } else if (Option == "hardfloat") {
5427 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5428
5429 // Synchronize the ABI Flags information with the FeatureBits information we
5430 // updated above.
5431 getTargetStreamer().updateABIInfo(*this);
5432
5433 // If printing assembly, use the recently updated ABI Flags information.
5434 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5435 // emitted later).
5436 getTargetStreamer().emitDirectiveModuleHardFloat();
5437
5438 // If this is not the end of the statement, report an error.
5439 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5440 reportParseError("unexpected token, expected end of statement");
5441 return false;
5442 }
5443
5444 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005445 } else {
5446 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5447 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005448}
5449
5450/// parseDirectiveModuleFP
5451/// ::= =32
5452/// ::= =xx
5453/// ::= =64
5454bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005455 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005456 MCAsmLexer &Lexer = getLexer();
5457
5458 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005459 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005460 return false;
5461 }
5462 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005463
Daniel Sanders7e527422014-07-10 13:38:23 +00005464 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005465 if (!parseFpABIValue(FpABI, ".module"))
5466 return false;
5467
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005468 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005469 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005470 return false;
5471 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005472
Toma Tabacua64e5402015-06-25 12:44:38 +00005473 // Synchronize the abiflags information with the FeatureBits information we
5474 // changed above.
5475 getTargetStreamer().updateABIInfo(*this);
5476
5477 // If printing assembly, use the recently updated abiflags information.
5478 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5479 // emitted at the end).
5480 getTargetStreamer().emitDirectiveModuleFP();
5481
Daniel Sanders7e527422014-07-10 13:38:23 +00005482 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005483 return false;
5484}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005485
Daniel Sanders7e527422014-07-10 13:38:23 +00005486bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005487 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005488 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005489 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005490 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005491
5492 if (Lexer.is(AsmToken::Identifier)) {
5493 StringRef Value = Parser.getTok().getString();
5494 Parser.Lex();
5495
5496 if (Value != "xx") {
5497 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5498 return false;
5499 }
5500
5501 if (!isABI_O32()) {
5502 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5503 return false;
5504 }
5505
Daniel Sanders7e527422014-07-10 13:38:23 +00005506 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005507 if (ModuleLevelOptions) {
5508 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5509 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5510 } else {
5511 setFeatureBits(Mips::FeatureFPXX, "fpxx");
5512 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5513 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005514 return true;
5515 }
5516
5517 if (Lexer.is(AsmToken::Integer)) {
5518 unsigned Value = Parser.getTok().getIntVal();
5519 Parser.Lex();
5520
5521 if (Value != 32 && Value != 64) {
5522 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5523 return false;
5524 }
5525
5526 if (Value == 32) {
5527 if (!isABI_O32()) {
5528 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
5529 return false;
5530 }
5531
Daniel Sanders7e527422014-07-10 13:38:23 +00005532 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005533 if (ModuleLevelOptions) {
5534 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5535 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5536 } else {
5537 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5538 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5539 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005540 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00005541 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005542 if (ModuleLevelOptions) {
5543 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5544 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5545 } else {
5546 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5547 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
5548 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005549 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005550
Daniel Sanders7e527422014-07-10 13:38:23 +00005551 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005552 }
5553
5554 return false;
5555}
5556
Jack Carter0b744b32012-10-04 02:29:46 +00005557bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005558 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005559 StringRef IDVal = DirectiveID.getString();
5560
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005561 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005562 return parseDirectiveCpLoad(DirectiveID.getLoc());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005563 if (IDVal == ".cprestore")
5564 return parseDirectiveCpRestore(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00005565 if (IDVal == ".dword") {
5566 parseDataDirective(8, DirectiveID.getLoc());
5567 return false;
5568 }
Jack Carterd0bd6422013-04-18 00:41:53 +00005569 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005570 StringRef SymbolName;
5571
5572 if (Parser.parseIdentifier(SymbolName)) {
5573 reportParseError("expected identifier after .ent");
5574 return false;
5575 }
5576
5577 // There's an undocumented extension that allows an integer to
5578 // follow the name of the procedure which AFAICS is ignored by GAS.
5579 // Example: .ent foo,2
5580 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5581 if (getLexer().isNot(AsmToken::Comma)) {
5582 // Even though we accept this undocumented extension for compatibility
5583 // reasons, the additional integer argument does not actually change
5584 // the behaviour of the '.ent' directive, so we would like to discourage
5585 // its use. We do this by not referring to the extended version in
5586 // error messages which are not directly related to its use.
5587 reportParseError("unexpected token, expected end of statement");
5588 return false;
5589 }
5590 Parser.Lex(); // Eat the comma.
5591 const MCExpr *DummyNumber;
5592 int64_t DummyNumberVal;
5593 // If the user was explicitly trying to use the extended version,
5594 // we still give helpful extension-related error messages.
5595 if (Parser.parseExpression(DummyNumber)) {
5596 reportParseError("expected number after comma");
5597 return false;
5598 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00005599 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005600 reportParseError("expected an absolute expression after comma");
5601 return false;
5602 }
5603 }
5604
5605 // If this is not the end of the statement, report an error.
5606 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5607 reportParseError("unexpected token, expected end of statement");
5608 return false;
5609 }
5610
Jim Grosbach6f482002015-05-18 18:43:14 +00005611 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005612
5613 getTargetStreamer().emitDirectiveEnt(*Sym);
5614 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005615 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005616 return false;
5617 }
5618
Jack Carter07c818d2013-01-25 01:31:34 +00005619 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005620 StringRef SymbolName;
5621
5622 if (Parser.parseIdentifier(SymbolName)) {
5623 reportParseError("expected identifier after .end");
5624 return false;
5625 }
5626
5627 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5628 reportParseError("unexpected token, expected end of statement");
5629 return false;
5630 }
5631
5632 if (CurrentFn == nullptr) {
5633 reportParseError(".end used without .ent");
5634 return false;
5635 }
5636
5637 if ((SymbolName != CurrentFn->getName())) {
5638 reportParseError(".end symbol does not match .ent symbol");
5639 return false;
5640 }
5641
5642 getTargetStreamer().emitDirectiveEnd(SymbolName);
5643 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005644 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005645 return false;
5646 }
5647
Jack Carter07c818d2013-01-25 01:31:34 +00005648 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005649 // .frame $stack_reg, frame_size_in_bytes, $return_reg
5650 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005651 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005652 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5653 reportParseError("expected stack register");
5654 return false;
5655 }
5656
5657 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5658 if (!StackRegOpnd.isGPRAsmReg()) {
5659 reportParseError(StackRegOpnd.getStartLoc(),
5660 "expected general purpose register");
5661 return false;
5662 }
5663 unsigned StackReg = StackRegOpnd.getGPR32Reg();
5664
5665 if (Parser.getTok().is(AsmToken::Comma))
5666 Parser.Lex();
5667 else {
5668 reportParseError("unexpected token, expected comma");
5669 return false;
5670 }
5671
5672 // Parse the frame size.
5673 const MCExpr *FrameSize;
5674 int64_t FrameSizeVal;
5675
5676 if (Parser.parseExpression(FrameSize)) {
5677 reportParseError("expected frame size value");
5678 return false;
5679 }
5680
Jim Grosbach13760bd2015-05-30 01:25:56 +00005681 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005682 reportParseError("frame size not an absolute expression");
5683 return false;
5684 }
5685
5686 if (Parser.getTok().is(AsmToken::Comma))
5687 Parser.Lex();
5688 else {
5689 reportParseError("unexpected token, expected comma");
5690 return false;
5691 }
5692
5693 // Parse the return register.
5694 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00005695 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005696 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5697 reportParseError("expected return register");
5698 return false;
5699 }
5700
5701 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5702 if (!ReturnRegOpnd.isGPRAsmReg()) {
5703 reportParseError(ReturnRegOpnd.getStartLoc(),
5704 "expected general purpose register");
5705 return false;
5706 }
5707
5708 // If this is not the end of the statement, report an error.
5709 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5710 reportParseError("unexpected token, expected end of statement");
5711 return false;
5712 }
5713
5714 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
5715 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005716 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005717 return false;
5718 }
5719
Jack Carter07c818d2013-01-25 01:31:34 +00005720 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00005721 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00005722 }
5723
Daniel Sandersd97a6342014-08-13 10:07:34 +00005724 if (IDVal == ".mask" || IDVal == ".fmask") {
5725 // .mask bitmask, frame_offset
5726 // bitmask: One bit for each register used.
5727 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
5728 // first register is expected to be saved.
5729 // Examples:
5730 // .mask 0x80000000, -4
5731 // .fmask 0x80000000, -4
5732 //
Jack Carterbe332172012-09-07 00:48:02 +00005733
Daniel Sandersd97a6342014-08-13 10:07:34 +00005734 // Parse the bitmask
5735 const MCExpr *BitMask;
5736 int64_t BitMaskVal;
5737
5738 if (Parser.parseExpression(BitMask)) {
5739 reportParseError("expected bitmask value");
5740 return false;
5741 }
5742
Jim Grosbach13760bd2015-05-30 01:25:56 +00005743 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005744 reportParseError("bitmask not an absolute expression");
5745 return false;
5746 }
5747
5748 if (Parser.getTok().is(AsmToken::Comma))
5749 Parser.Lex();
5750 else {
5751 reportParseError("unexpected token, expected comma");
5752 return false;
5753 }
5754
5755 // Parse the frame_offset
5756 const MCExpr *FrameOffset;
5757 int64_t FrameOffsetVal;
5758
5759 if (Parser.parseExpression(FrameOffset)) {
5760 reportParseError("expected frame offset value");
5761 return false;
5762 }
5763
Jim Grosbach13760bd2015-05-30 01:25:56 +00005764 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005765 reportParseError("frame offset not an absolute expression");
5766 return false;
5767 }
5768
5769 // If this is not the end of the statement, report an error.
5770 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5771 reportParseError("unexpected token, expected end of statement");
5772 return false;
5773 }
5774
5775 if (IDVal == ".mask")
5776 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
5777 else
5778 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00005779 return false;
5780 }
5781
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005782 if (IDVal == ".nan")
5783 return parseDirectiveNaN();
5784
Jack Carter07c818d2013-01-25 01:31:34 +00005785 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005786 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00005787 return false;
5788 }
5789
Rafael Espindolab59fb732014-03-28 18:50:26 +00005790 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005791 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005792 return false;
5793 }
5794
Jack Carter07c818d2013-01-25 01:31:34 +00005795 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005796 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00005797 return false;
5798 }
5799
Jack Carter0cd3c192014-01-06 23:27:31 +00005800 if (IDVal == ".option")
5801 return parseDirectiveOption();
5802
5803 if (IDVal == ".abicalls") {
5804 getTargetStreamer().emitDirectiveAbiCalls();
5805 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005806 Error(Parser.getTok().getLoc(),
5807 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005808 // Clear line
5809 Parser.eatToEndOfStatement();
5810 }
5811 return false;
5812 }
5813
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005814 if (IDVal == ".cpsetup")
5815 return parseDirectiveCPSetup();
5816
Daniel Sandersf173dda2015-09-22 10:50:09 +00005817 if (IDVal == ".cpreturn")
5818 return parseDirectiveCPReturn();
5819
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005820 if (IDVal == ".module")
5821 return parseDirectiveModule();
5822
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005823 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
5824 return parseInternalDirectiveReallowModule();
5825
Toma Tabacu9ca50962015-04-16 09:53:47 +00005826 if (IDVal == ".insn")
5827 return parseInsnDirective();
5828
Rafael Espindola870c4e92012-01-11 03:56:41 +00005829 return true;
5830}
5831
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005832bool MipsAsmParser::parseInternalDirectiveReallowModule() {
5833 // If this is not the end of the statement, report an error.
5834 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5835 reportParseError("unexpected token, expected end of statement");
5836 return false;
5837 }
5838
5839 getTargetStreamer().reallowModuleDirective();
5840
5841 getParser().Lex(); // Eat EndOfStatement token.
5842 return false;
5843}
5844
Rafael Espindola870c4e92012-01-11 03:56:41 +00005845extern "C" void LLVMInitializeMipsAsmParser() {
5846 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
5847 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
5848 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
5849 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
5850}
Jack Carterb4dbc172012-09-05 23:34:03 +00005851
5852#define GET_REGISTER_MATCHER
5853#define GET_MATCHER_IMPLEMENTATION
5854#include "MipsGenAsmMatcher.inc"