blob: 132b5f354e3bb72c0b57353583548969483b6bce [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
Eric Christophera5762812015-01-26 17:33:46 +0000110 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000111 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000112 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
113 // nullptr, which indicates that no function is currently
114 // selected. This usually happens after an '.end func'
115 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000116 bool IsLittleEndian;
Daniel Sandersa6994442015-08-18 12:33:54 +0000117 bool IsPicEnabled;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000118 bool IsCpRestoreSet;
119 int CpRestoreOffset;
Daniel Sandersf173dda2015-09-22 10:50:09 +0000120 unsigned CpSaveLocation;
121 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
122 bool CpSaveLocationIsRegister;
Jack Carter0b744b32012-10-04 02:29:46 +0000123
Daniel Sandersef638fe2014-10-03 15:37:37 +0000124 // Print a warning along with its fix-it message at the given range.
125 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
126 SMRange Range, bool ShowColors = true);
127
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000128#define GET_ASSEMBLER_HEADER
129#include "MipsGenAsmMatcher.inc"
130
Matheus Almeida595fcab2014-06-11 15:05:56 +0000131 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
132
Chad Rosier49963552012-10-13 00:26:04 +0000133 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000134 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000135 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000136 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000137
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000138 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000139 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000140
Toma Tabacu13964452014-09-04 13:23:44 +0000141 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000142
Toma Tabacu13964452014-09-04 13:23:44 +0000143 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000144
David Blaikie960ea3f2014-06-08 16:18:35 +0000145 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
146 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000147
Craig Topper56c590a2014-04-29 07:58:02 +0000148 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000149
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000150 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
151 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000152 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000153 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000154 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
155 SMLoc S);
156 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
157 OperandMatchResultTy parseImm(OperandVector &Operands);
158 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
159 OperandMatchResultTy parseInvNum(OperandVector &Operands);
160 OperandMatchResultTy parseLSAImm(OperandVector &Operands);
161 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
162 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
163 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000164
David Blaikie960ea3f2014-06-08 16:18:35 +0000165 bool searchSymbolAlias(OperandVector &Operands);
166
Toma Tabacu13964452014-09-04 13:23:44 +0000167 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000168
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000169 enum MacroExpanderResultTy {
170 MER_NotAMacro,
171 MER_Success,
172 MER_Fail,
173 };
Jack Carter30a59822012-10-04 04:03:53 +0000174
Matheus Almeida3813d572014-06-19 14:39:14 +0000175 // Expands assembly pseudo instructions.
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000176 MacroExpanderResultTy
177 tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
178 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000179
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000180 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
181 SmallVectorImpl<MCInst> &Instructions);
182
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000183 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000184 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000185 SmallVectorImpl<MCInst> &Instructions);
186
Toma Tabacuf712ede2015-06-17 14:31:51 +0000187 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
188 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
189 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacu674825c2015-06-16 12:16:24 +0000190
Toma Tabacu00e98672015-05-01 12:19:27 +0000191 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000192 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000193
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000194 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
195 const MCOperand &Offset, bool Is32BitAddress,
196 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000197
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000198 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
199 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000200
Jack Carter9e65aa32013-03-22 00:05:30 +0000201 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000202 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
203 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000204
205 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
206 SmallVectorImpl<MCInst> &Instructions);
207
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000208 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
209 SmallVectorImpl<MCInst> &Instructions);
210
Toma Tabacue1e460d2015-06-11 10:36:10 +0000211 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc,
212 SmallVectorImpl<MCInst> &Instructions);
213
Toma Tabacu1a108322015-06-17 13:20:24 +0000214 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc,
215 SmallVectorImpl<MCInst> &Instructions);
216
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000217 bool expandDiv(MCInst &Inst, SMLoc IDLoc,
218 SmallVectorImpl<MCInst> &Instructions, const bool IsMips64,
219 const bool Signed);
220
Daniel Sanders6394ee52015-10-15 14:52:58 +0000221 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
222 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000223
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000224 bool expandUlw(MCInst &Inst, SMLoc IDLoc,
225 SmallVectorImpl<MCInst> &Instructions);
226
Toma Tabacu234482a2015-03-16 12:03:39 +0000227 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
228 SmallVectorImpl<MCInst> &Instructions);
229
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000230 void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +0000231 bool Is64Bit, SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000232
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000233 void createCpRestoreMemOp(bool IsLoad, int StackOffset, SMLoc IDLoc,
234 SmallVectorImpl<MCInst> &Instructions);
235
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000236 bool reportParseError(Twine ErrorMsg);
237 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000238
Jack Carterb5cf5902013-04-17 00:18:04 +0000239 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000240 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000241
Vladimir Medic4c299852013-11-06 11:27:05 +0000242 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000243
244 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000245 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000246 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000247 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000248 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000249 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000250 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000251 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000252 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000253 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000254 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000255 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000256 bool parseInsnDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000257
258 bool parseSetAtDirective();
259 bool parseSetNoAtDirective();
260 bool parseSetMacroDirective();
261 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000262 bool parseSetMsaDirective();
263 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000264 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000265 bool parseSetReorderDirective();
266 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000267 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000268 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000269 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000270 bool parseSetOddSPRegDirective();
271 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000272 bool parseSetPopDirective();
273 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000274 bool parseSetSoftFloatDirective();
275 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000276
Jack Carterd76b2372013-03-21 21:44:16 +0000277 bool parseSetAssignment();
278
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000279 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000280 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000281 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000282 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000283 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000284 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
285 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000286
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000287 bool parseInternalDirectiveReallowModule();
288
Jack Carterdc1e35d2012-09-06 20:00:02 +0000289 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000290
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000291 bool eatComma(StringRef ErrorStr);
292
Jack Carter1ac53222013-02-20 23:11:17 +0000293 int matchCPURegisterName(StringRef Symbol);
294
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000295 int matchHWRegsRegisterName(StringRef Symbol);
296
Jack Carter873c7242013-01-12 01:03:14 +0000297 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000298
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000299 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000300
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000301 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000302
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000303 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000304
Jack Carter5dc8ac92013-09-25 23:50:44 +0000305 int matchMSA128RegisterName(StringRef Name);
306
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000307 int matchMSA128CtrlRegisterName(StringRef Name);
308
Jack Carterd0bd6422013-04-18 00:41:53 +0000309 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000310
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000311 unsigned getGPR(int RegNo);
312
Toma Tabacu89a712b2015-04-15 10:48:56 +0000313 /// Returns the internal register number for the current AT. Also checks if
314 /// the current AT is unavailable (set to $0) and gives an error if it is.
315 /// This should be used in pseudo-instruction expansions which need AT.
316 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000317
318 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000319 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000320
321 // Helper function that checks if the value of a vector index is within the
322 // boundaries of accepted values for each RegisterKind
323 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
324 bool validateMSAIndex(int Val, int RegKind);
325
Daniel Sandersf0df2212014-08-04 12:20:00 +0000326 // Selects a new architecture by updating the FeatureBits with the necessary
327 // info including implied dependencies.
328 // Internally, it clears all the feature bits related to *any* architecture
329 // and selects the new one using the ToggleFeature functionality of the
330 // MCSubtargetInfo object that handles implied dependencies. The reason we
331 // clear all the arch related bits manually is because ToggleFeature only
332 // clears the features that imply the feature being cleared and not the
333 // features implied by the feature being cleared. This is easier to see
334 // with an example:
335 // --------------------------------------------------
336 // | Feature | Implies |
337 // | -------------------------------------------------|
338 // | FeatureMips1 | None |
339 // | FeatureMips2 | FeatureMips1 |
340 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
341 // | FeatureMips4 | FeatureMips3 |
342 // | ... | |
343 // --------------------------------------------------
344 //
345 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
346 // FeatureMipsGP64 | FeatureMips1)
347 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
348 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000349 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000350 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000351 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
352 STI.setFeatureBits(FeatureBits);
353 setAvailableFeatures(
354 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000355 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000356 }
357
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000358 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000359 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000360 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000361 setAvailableFeatures(
362 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000363 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000364 }
365 }
366
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000367 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000368 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000369 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000370 setAvailableFeatures(
371 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000372 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000373 }
374 }
375
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000376 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
377 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000378 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000379 }
380
381 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
382 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000383 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000384 }
385
Rafael Espindola870c4e92012-01-11 03:56:41 +0000386public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000387 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000388 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000389#define GET_OPERAND_DIAGNOSTIC_TYPES
390#include "MipsGenAsmMatcher.inc"
391#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000392 };
393
Akira Hatanakab11ef082015-11-14 06:35:56 +0000394 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000395 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000396 : MCTargetAsmParser(Options, sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000397 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
398 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000399 MCAsmParserExtension::Initialize(parser);
400
Toma Tabacu11e14a92015-04-21 11:50:52 +0000401 parser.addAliasForDirective(".asciiz", ".asciz");
402
Jack Carterb4dbc172012-09-05 23:34:03 +0000403 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000404 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000405
Toma Tabacu9db22db2014-09-09 10:15:38 +0000406 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000407 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000408 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000409
Toma Tabacu9db22db2014-09-09 10:15:38 +0000410 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000411 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000412 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000413
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000414 getTargetStreamer().updateABIInfo(*this);
415
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000416 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000417 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000418
419 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000420
Daniel Sandersa6994442015-08-18 12:33:54 +0000421 IsPicEnabled =
422 (getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_);
423
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000424 IsCpRestoreSet = false;
425 CpRestoreOffset = -1;
426
Daniel Sanders50f17232015-09-15 16:17:27 +0000427 Triple TheTriple(sti.getTargetTriple());
428 if ((TheTriple.getArch() == Triple::mips) ||
429 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000430 IsLittleEndian = false;
431 else
432 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000433 }
434
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000435 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
436 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
437
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000438 bool isGP64bit() const {
439 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
440 }
441 bool isFP64bit() const {
442 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
443 }
Eric Christophera5762812015-01-26 17:33:46 +0000444 const MipsABIInfo &getABI() const { return ABI; }
445 bool isABI_N32() const { return ABI.IsN32(); }
446 bool isABI_N64() const { return ABI.IsN64(); }
447 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000448 bool isABI_FPXX() const {
449 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
450 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000451
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000452 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000453 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000454 }
455
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000456 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000457 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000458 }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000459 bool hasMips1() const {
460 return getSTI().getFeatureBits()[Mips::FeatureMips1];
461 }
462 bool hasMips2() const {
463 return getSTI().getFeatureBits()[Mips::FeatureMips2];
464 }
465 bool hasMips3() const {
466 return getSTI().getFeatureBits()[Mips::FeatureMips3];
467 }
468 bool hasMips4() const {
469 return getSTI().getFeatureBits()[Mips::FeatureMips4];
470 }
471 bool hasMips5() const {
472 return getSTI().getFeatureBits()[Mips::FeatureMips5];
473 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000474 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000475 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000476 }
477 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000478 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000479 }
480 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000481 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000482 }
483 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000484 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000485 }
Daniel Sanders17793142015-02-18 16:24:50 +0000486 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000487 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000488 }
489 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000490 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000491 }
492 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000493 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000494 }
495 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000496 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000497 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000498 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000499 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000500 }
501 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000502 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000503 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000504
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000505 bool hasDSP() const {
506 return getSTI().getFeatureBits()[Mips::FeatureDSP];
507 }
508 bool hasDSPR2() const {
509 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
510 }
511 bool hasDSPR3() const {
512 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
513 }
514 bool hasMSA() const {
515 return getSTI().getFeatureBits()[Mips::FeatureMSA];
516 }
Kai Nackee0245392015-01-27 19:11:28 +0000517 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000518 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000519 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000520
Daniel Sandersa6994442015-08-18 12:33:54 +0000521 bool inPicMode() {
522 return IsPicEnabled;
523 }
524
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000525 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000526 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000527 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000528
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000529 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000530 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000531 }
532
Eric Christophere8ae3e32015-05-07 23:10:21 +0000533 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000534 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000535 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000536
Toma Tabacud9d344b2015-04-27 14:05:04 +0000537 /// Warn if RegIndex is the same as the current AT.
538 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000539
540 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000541
542 bool isLittle() const { return IsLittleEndian; }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000543};
544}
545
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000546namespace {
547
548/// MipsOperand - Instances of this class represent a parsed Mips machine
549/// instruction.
550class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000551public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000552 /// Broad categories of register classes
553 /// The exact class is finalized by the render method.
554 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000555 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000556 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000557 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000558 RegKind_FCC = 4, /// FCC
559 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
560 RegKind_MSACtrl = 16, /// MSA control registers
561 RegKind_COP2 = 32, /// COP2
562 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
563 /// context).
564 RegKind_CCR = 128, /// CCR
565 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000566 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000567 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000568 /// Potentially any (e.g. $1)
569 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
570 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000571 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000572 };
573
574private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000575 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000576 k_Immediate, /// An immediate (possibly involving symbol references)
577 k_Memory, /// Base + Offset Memory Address
578 k_PhysRegister, /// A physical register from the Mips namespace
579 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000580 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000581 k_RegList, /// A physical register list
582 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000583 } Kind;
584
David Blaikie960ea3f2014-06-08 16:18:35 +0000585public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000586 MipsOperand(KindTy K, MipsAsmParser &Parser)
587 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
588
David Blaikie960ea3f2014-06-08 16:18:35 +0000589private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000590 /// For diagnostics, and checking the assembler temporary
591 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000592
Eric Christopher8996c5d2013-03-15 00:42:55 +0000593 struct Token {
594 const char *Data;
595 unsigned Length;
596 };
597
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000598 struct PhysRegOp {
599 unsigned Num; /// Register Number
600 };
601
602 struct RegIdxOp {
603 unsigned Index; /// Index into the register class
604 RegKind Kind; /// Bitfield of the kinds it could possibly be
605 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000606 };
607
608 struct ImmOp {
609 const MCExpr *Val;
610 };
611
612 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000613 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000614 const MCExpr *Off;
615 };
616
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000617 struct RegListOp {
618 SmallVector<unsigned, 10> *List;
619 };
620
Jack Carterb4dbc172012-09-05 23:34:03 +0000621 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000622 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000623 struct PhysRegOp PhysReg;
624 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000625 struct ImmOp Imm;
626 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000627 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000628 };
629
630 SMLoc StartLoc, EndLoc;
631
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000632 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000633 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
634 const MCRegisterInfo *RegInfo,
635 SMLoc S, SMLoc E,
636 MipsAsmParser &Parser) {
637 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000638 Op->RegIdx.Index = Index;
639 Op->RegIdx.RegInfo = RegInfo;
640 Op->RegIdx.Kind = RegKind;
641 Op->StartLoc = S;
642 Op->EndLoc = E;
643 return Op;
644 }
645
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000646public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000647 /// Coerce the register to GPR32 and return the real register for the current
648 /// target.
649 unsigned getGPR32Reg() const {
650 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000651 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000652 unsigned ClassID = Mips::GPR32RegClassID;
653 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000654 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000655
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000656 /// Coerce the register to GPR32 and return the real register for the current
657 /// target.
658 unsigned getGPRMM16Reg() const {
659 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
660 unsigned ClassID = Mips::GPR32RegClassID;
661 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
662 }
663
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000664 /// Coerce the register to GPR64 and return the real register for the current
665 /// target.
666 unsigned getGPR64Reg() const {
667 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
668 unsigned ClassID = Mips::GPR64RegClassID;
669 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000670 }
671
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000672private:
673 /// Coerce the register to AFGR64 and return the real register for the current
674 /// target.
675 unsigned getAFGR64Reg() const {
676 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
677 if (RegIdx.Index % 2 != 0)
678 AsmParser.Warning(StartLoc, "Float register should be even.");
679 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
680 .getRegister(RegIdx.Index / 2);
681 }
682
683 /// Coerce the register to FGR64 and return the real register for the current
684 /// target.
685 unsigned getFGR64Reg() const {
686 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
687 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
688 .getRegister(RegIdx.Index);
689 }
690
691 /// Coerce the register to FGR32 and return the real register for the current
692 /// target.
693 unsigned getFGR32Reg() const {
694 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
695 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
696 .getRegister(RegIdx.Index);
697 }
698
699 /// Coerce the register to FGRH32 and return the real register for the current
700 /// target.
701 unsigned getFGRH32Reg() const {
702 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
703 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
704 .getRegister(RegIdx.Index);
705 }
706
707 /// Coerce the register to FCC and return the real register for the current
708 /// target.
709 unsigned getFCCReg() const {
710 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
711 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
712 .getRegister(RegIdx.Index);
713 }
714
715 /// Coerce the register to MSA128 and return the real register for the current
716 /// target.
717 unsigned getMSA128Reg() const {
718 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
719 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
720 // identical
721 unsigned ClassID = Mips::MSA128BRegClassID;
722 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
723 }
724
725 /// Coerce the register to MSACtrl and return the real register for the
726 /// current target.
727 unsigned getMSACtrlReg() const {
728 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
729 unsigned ClassID = Mips::MSACtrlRegClassID;
730 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
731 }
732
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000733 /// Coerce the register to COP0 and return the real register for the
734 /// current target.
735 unsigned getCOP0Reg() const {
736 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
737 unsigned ClassID = Mips::COP0RegClassID;
738 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
739 }
740
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000741 /// Coerce the register to COP2 and return the real register for the
742 /// current target.
743 unsigned getCOP2Reg() const {
744 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
745 unsigned ClassID = Mips::COP2RegClassID;
746 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
747 }
748
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000749 /// Coerce the register to COP3 and return the real register for the
750 /// current target.
751 unsigned getCOP3Reg() const {
752 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
753 unsigned ClassID = Mips::COP3RegClassID;
754 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
755 }
756
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000757 /// Coerce the register to ACC64DSP and return the real register for the
758 /// current target.
759 unsigned getACC64DSPReg() const {
760 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
761 unsigned ClassID = Mips::ACC64DSPRegClassID;
762 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
763 }
764
765 /// Coerce the register to HI32DSP and return the real register for the
766 /// current target.
767 unsigned getHI32DSPReg() const {
768 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
769 unsigned ClassID = Mips::HI32DSPRegClassID;
770 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
771 }
772
773 /// Coerce the register to LO32DSP and return the real register for the
774 /// current target.
775 unsigned getLO32DSPReg() const {
776 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
777 unsigned ClassID = Mips::LO32DSPRegClassID;
778 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
779 }
780
781 /// Coerce the register to CCR and return the real register for the
782 /// current target.
783 unsigned getCCRReg() const {
784 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
785 unsigned ClassID = Mips::CCRRegClassID;
786 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
787 }
788
789 /// Coerce the register to HWRegs and return the real register for the
790 /// current target.
791 unsigned getHWRegsReg() const {
792 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
793 unsigned ClassID = Mips::HWRegsRegClassID;
794 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
795 }
796
797public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000798 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000799 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000800 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000801 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000802 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000803 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000804 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000805 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000806 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000807
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000808 void addRegOperands(MCInst &Inst, unsigned N) const {
809 llvm_unreachable("Use a custom parser instead");
810 }
811
Daniel Sanders21bce302014-04-01 12:35:23 +0000812 /// Render the operand to an MCInst as a GPR32
813 /// Asserts if the wrong number of operands are requested, or the operand
814 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000815 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
816 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000817 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000818 }
819
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000820 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
821 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000822 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000823 }
824
Jozef Kolek1904fa22014-11-24 14:25:53 +0000825 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
826 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000827 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000828 }
829
Zoran Jovanovic41688672015-02-10 16:36:20 +0000830 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
831 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000832 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000833 }
834
Daniel Sanders21bce302014-04-01 12:35:23 +0000835 /// Render the operand to an MCInst as a GPR64
836 /// Asserts if the wrong number of operands are requested, or the operand
837 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000838 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
839 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000840 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000841 }
842
843 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
844 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000845 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000846 }
847
848 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
849 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000850 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000851 }
852
853 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
854 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000855 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000856 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000857 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000858 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
859 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000860 }
861
862 void addFGRH32AsmRegOperands(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(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000865 }
866
867 void addFCCAsmRegOperands(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(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000870 }
871
872 void addMSA128AsmRegOperands(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(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000875 }
876
877 void addMSACtrlAsmRegOperands(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(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000880 }
881
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000882 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
883 assert(N == 1 && "Invalid number of operands!");
884 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
885 }
886
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000887 void addCOP2AsmRegOperands(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(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000890 }
891
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000892 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
893 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000894 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000895 }
896
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000897 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
898 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000899 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000900 }
901
902 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
903 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000904 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000905 }
906
907 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
908 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000909 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000910 }
911
912 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
913 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000914 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000915 }
916
917 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
918 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000919 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000920 }
921
Daniel Sandersea4f6532015-11-06 12:22:31 +0000922 template <unsigned Bits, int Offset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +0000923 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
924 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +0000925 uint64_t Imm = getConstantImm() - Offset;
926 Imm &= (1 << Bits) - 1;
927 Imm += Offset;
Daniel Sanders52da7af2015-11-06 12:11:03 +0000928 Inst.addOperand(MCOperand::createImm(Imm));
929 }
930
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000931 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000932 assert(N == 1 && "Invalid number of operands!");
933 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000934 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000935 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000936
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000937 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000938 assert(N == 2 && "Invalid number of operands!");
939
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000940 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
941 ? getMemBase()->getGPR64Reg()
942 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000943
944 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000945 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000946 }
947
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000948 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
949 assert(N == 2 && "Invalid number of operands!");
950
Jim Grosbache9119e42015-05-13 18:37:00 +0000951 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000952
953 const MCExpr *Expr = getMemOff();
954 addExpr(Inst, Expr);
955 }
956
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000957 void addRegListOperands(MCInst &Inst, unsigned N) const {
958 assert(N == 1 && "Invalid number of operands!");
959
960 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000961 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000962 }
963
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000964 void addRegPairOperands(MCInst &Inst, unsigned N) const {
965 assert(N == 2 && "Invalid number of operands!");
966 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +0000967 Inst.addOperand(MCOperand::createReg(RegNo++));
968 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000969 }
970
Zoran Jovanovic41688672015-02-10 16:36:20 +0000971 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
972 assert(N == 2 && "Invalid number of operands!");
973 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000974 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000975 }
976
Craig Topper56c590a2014-04-29 07:58:02 +0000977 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000978 // As a special case until we sort out the definition of div/divu, pretend
979 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
980 if (isGPRAsmReg() && RegIdx.Index == 0)
981 return true;
982
983 return Kind == k_PhysRegister;
984 }
985 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000986 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000987 bool isConstantImm() const {
Craig Topper66059c92015-11-18 07:07:59 +0000988 return isImm() && isa<MCConstantExpr>(getImm());
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000989 }
Daniel Sanders52da7af2015-11-06 12:11:03 +0000990 bool isConstantImmz() const {
991 return isConstantImm() && getConstantImm() == 0;
992 }
Daniel Sandersea4f6532015-11-06 12:22:31 +0000993 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
994 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
995 }
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +0000996 template <unsigned Bits> bool isUImm() const {
997 return isImm() && isConstantImm() && isUInt<Bits>(getConstantImm());
998 }
Craig Topper56c590a2014-04-29 07:58:02 +0000999 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001000 // Note: It's not possible to pretend that other operand kinds are tokens.
1001 // The matcher emitter checks tokens first.
1002 return Kind == k_Token;
1003 }
Craig Topper56c590a2014-04-29 07:58:02 +00001004 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001005 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001006 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001007 }
1008 template <unsigned Bits> bool isMemWithSimmOffset() const {
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001009 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1010 && getMemBase()->isGPRAsmReg();
1011 }
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +00001012 template <unsigned Bits> bool isMemWithSimmOffsetGPR() const {
1013 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) &&
1014 getMemBase()->isGPRAsmReg();
1015 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001016 bool isMemWithGRPMM16Base() const {
1017 return isMem() && getMemBase()->isMM16AsmReg();
1018 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001019 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1020 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1021 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1022 }
Jozef Kolek12c69822014-12-23 16:16:33 +00001023 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1024 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1025 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1026 && (getMemBase()->getGPR32Reg() == Mips::SP);
1027 }
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001028 bool isUImm5Lsl2() const {
1029 return (isImm() && isConstantImm() && isShiftedUInt<5, 2>(getConstantImm()));
1030 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001031 bool isRegList16() const {
1032 if (!isRegList())
1033 return false;
1034
1035 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001036 if (Size < 2 || Size > 5)
1037 return false;
1038
1039 unsigned R0 = RegList.List->front();
1040 unsigned R1 = RegList.List->back();
1041 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1042 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001043 return false;
1044
1045 int PrevReg = *RegList.List->begin();
1046 for (int i = 1; i < Size - 1; i++) {
1047 int Reg = (*(RegList.List))[i];
1048 if ( Reg != PrevReg + 1)
1049 return false;
1050 PrevReg = Reg;
1051 }
1052
1053 return true;
1054 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001055 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001056 bool isLSAImm() const {
1057 if (!isConstantImm())
1058 return false;
1059 int64_t Val = getConstantImm();
1060 return 1 <= Val && Val <= 4;
1061 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001062 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001063 bool isMovePRegPair() const {
1064 if (Kind != k_RegList || RegList.List->size() != 2)
1065 return false;
1066
1067 unsigned R0 = RegList.List->front();
1068 unsigned R1 = RegList.List->back();
1069
1070 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1071 (R0 == Mips::A1 && R1 == Mips::A3) ||
1072 (R0 == Mips::A2 && R1 == Mips::A3) ||
1073 (R0 == Mips::A0 && R1 == Mips::S5) ||
1074 (R0 == Mips::A0 && R1 == Mips::S6) ||
1075 (R0 == Mips::A0 && R1 == Mips::A1) ||
1076 (R0 == Mips::A0 && R1 == Mips::A2) ||
1077 (R0 == Mips::A0 && R1 == Mips::A3))
1078 return true;
1079
1080 return false;
1081 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001082
1083 StringRef getToken() const {
1084 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001085 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001086 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001087 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001088
Craig Topper56c590a2014-04-29 07:58:02 +00001089 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001090 // As a special case until we sort out the definition of div/divu, pretend
1091 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1092 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1093 RegIdx.Kind & RegKind_GPR)
1094 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001095
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001096 assert(Kind == k_PhysRegister && "Invalid access!");
1097 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001098 }
1099
Jack Carterb4dbc172012-09-05 23:34:03 +00001100 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001101 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001102 return Imm.Val;
1103 }
1104
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001105 int64_t getConstantImm() const {
1106 const MCExpr *Val = getImm();
1107 return static_cast<const MCConstantExpr *>(Val)->getValue();
1108 }
1109
1110 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001111 assert((Kind == k_Memory) && "Invalid access!");
1112 return Mem.Base;
1113 }
1114
1115 const MCExpr *getMemOff() const {
1116 assert((Kind == k_Memory) && "Invalid access!");
1117 return Mem.Off;
1118 }
1119
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001120 int64_t getConstantMemOff() const {
1121 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1122 }
1123
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001124 const SmallVectorImpl<unsigned> &getRegList() const {
1125 assert((Kind == k_RegList) && "Invalid access!");
1126 return *(RegList.List);
1127 }
1128
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001129 unsigned getRegPair() const {
1130 assert((Kind == k_RegPair) && "Invalid access!");
1131 return RegIdx.Index;
1132 }
1133
David Blaikie960ea3f2014-06-08 16:18:35 +00001134 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1135 MipsAsmParser &Parser) {
1136 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001137 Op->Tok.Data = Str.data();
1138 Op->Tok.Length = Str.size();
1139 Op->StartLoc = S;
1140 Op->EndLoc = S;
1141 return Op;
1142 }
1143
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001144 /// Create a numeric register (e.g. $1). The exact register remains
1145 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001146 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001147 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001148 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001149 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001150 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001151 }
1152
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001153 /// Create a register that is definitely a GPR.
1154 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001155 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001156 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001157 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001158 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001159 }
1160
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001161 /// Create a register that is definitely a FGR.
1162 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001163 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001164 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001165 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001166 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1167 }
1168
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001169 /// Create a register that is definitely a HWReg.
1170 /// This is typically only used for named registers such as $hwr_cpunum.
1171 static std::unique_ptr<MipsOperand>
1172 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1173 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1174 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1175 }
1176
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001177 /// Create a register that is definitely an FCC.
1178 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001179 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001180 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001181 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001182 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1183 }
1184
1185 /// Create a register that is definitely an ACC.
1186 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001187 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001188 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001189 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001190 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1191 }
1192
1193 /// Create a register that is definitely an MSA128.
1194 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001195 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001196 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001197 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001198 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1199 }
1200
1201 /// Create a register that is definitely an MSACtrl.
1202 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001203 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001204 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001205 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001206 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1207 }
1208
David Blaikie960ea3f2014-06-08 16:18:35 +00001209 static std::unique_ptr<MipsOperand>
1210 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1211 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001212 Op->Imm.Val = Val;
1213 Op->StartLoc = S;
1214 Op->EndLoc = E;
1215 return Op;
1216 }
1217
David Blaikie960ea3f2014-06-08 16:18:35 +00001218 static std::unique_ptr<MipsOperand>
1219 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1220 SMLoc E, MipsAsmParser &Parser) {
1221 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1222 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001223 Op->Mem.Off = Off;
1224 Op->StartLoc = S;
1225 Op->EndLoc = E;
1226 return Op;
1227 }
1228
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001229 static std::unique_ptr<MipsOperand>
1230 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1231 MipsAsmParser &Parser) {
1232 assert (Regs.size() > 0 && "Empty list not allowed");
1233
1234 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001235 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001236 Op->StartLoc = StartLoc;
1237 Op->EndLoc = EndLoc;
1238 return Op;
1239 }
1240
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001241 static std::unique_ptr<MipsOperand>
1242 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1243 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1244 Op->RegIdx.Index = RegNo;
1245 Op->StartLoc = S;
1246 Op->EndLoc = E;
1247 return Op;
1248 }
1249
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001250 bool isGPRAsmReg() const {
1251 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001252 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001253 bool isMM16AsmReg() const {
1254 if (!(isRegIdx() && RegIdx.Kind))
1255 return false;
1256 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1257 || RegIdx.Index == 16 || RegIdx.Index == 17);
1258 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001259 bool isMM16AsmRegZero() const {
1260 if (!(isRegIdx() && RegIdx.Kind))
1261 return false;
1262 return (RegIdx.Index == 0 ||
1263 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1264 RegIdx.Index == 17);
1265 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001266 bool isMM16AsmRegMoveP() const {
1267 if (!(isRegIdx() && RegIdx.Kind))
1268 return false;
1269 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1270 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1271 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001272 bool isFGRAsmReg() const {
1273 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1274 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001275 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001276 bool isHWRegsAsmReg() const {
1277 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001278 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001279 bool isCCRAsmReg() const {
1280 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001281 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001282 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001283 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1284 return false;
1285 if (!AsmParser.hasEightFccRegisters())
1286 return RegIdx.Index == 0;
1287 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001288 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001289 bool isACCAsmReg() const {
1290 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001291 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001292 bool isCOP0AsmReg() const {
1293 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1294 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001295 bool isCOP2AsmReg() const {
1296 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001297 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001298 bool isCOP3AsmReg() const {
1299 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1300 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001301 bool isMSA128AsmReg() const {
1302 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001303 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001304 bool isMSACtrlAsmReg() const {
1305 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001306 }
1307
Jack Carterb4dbc172012-09-05 23:34:03 +00001308 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001309 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001310 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001311 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001312
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001313 virtual ~MipsOperand() {
1314 switch (Kind) {
1315 case k_Immediate:
1316 break;
1317 case k_Memory:
1318 delete Mem.Base;
1319 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001320 case k_RegList:
1321 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001322 case k_PhysRegister:
1323 case k_RegisterIndex:
1324 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001325 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001326 break;
1327 }
1328 }
1329
Craig Topper56c590a2014-04-29 07:58:02 +00001330 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001331 switch (Kind) {
1332 case k_Immediate:
1333 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001334 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001335 OS << ">";
1336 break;
1337 case k_Memory:
1338 OS << "Mem<";
1339 Mem.Base->print(OS);
1340 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001341 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001342 OS << ">";
1343 break;
1344 case k_PhysRegister:
1345 OS << "PhysReg<" << PhysReg.Num << ">";
1346 break;
1347 case k_RegisterIndex:
1348 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1349 break;
1350 case k_Token:
1351 OS << Tok.Data;
1352 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001353 case k_RegList:
1354 OS << "RegList< ";
1355 for (auto Reg : (*RegList.List))
1356 OS << Reg << " ";
1357 OS << ">";
1358 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001359 case k_RegPair:
1360 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1361 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001362 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001363 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001364}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001365} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001366
Jack Carter9e65aa32013-03-22 00:05:30 +00001367namespace llvm {
1368extern const MCInstrDesc MipsInsts[];
1369}
1370static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1371 return MipsInsts[Opcode];
1372}
1373
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001374static bool hasShortDelaySlot(unsigned Opcode) {
1375 switch (Opcode) {
1376 case Mips::JALS_MM:
1377 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001378 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001379 case Mips::BGEZALS_MM:
1380 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001381 return true;
1382 default:
1383 return false;
1384 }
1385}
1386
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001387static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1388 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1389 return &SRExpr->getSymbol();
1390 }
1391
1392 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1393 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1394 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1395
1396 if (LHSSym)
1397 return LHSSym;
1398
1399 if (RHSSym)
1400 return RHSSym;
1401
1402 return nullptr;
1403 }
1404
1405 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1406 return getSingleMCSymbol(UExpr->getSubExpr());
1407
1408 return nullptr;
1409}
1410
1411static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1412 if (isa<MCSymbolRefExpr>(Expr))
1413 return 1;
1414
1415 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1416 return countMCSymbolRefExpr(BExpr->getLHS()) +
1417 countMCSymbolRefExpr(BExpr->getRHS());
1418
1419 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1420 return countMCSymbolRefExpr(UExpr->getSubExpr());
1421
1422 return 0;
1423}
1424
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001425namespace {
1426void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc,
1427 SmallVectorImpl<MCInst> &Instructions) {
1428 MCInst tmpInst;
1429 tmpInst.setOpcode(Opcode);
1430 tmpInst.addOperand(MCOperand::createReg(Reg0));
1431 tmpInst.addOperand(Op1);
1432 tmpInst.setLoc(IDLoc);
1433 Instructions.push_back(tmpInst);
1434}
1435
1436void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc,
1437 SmallVectorImpl<MCInst> &Instructions) {
1438 emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions);
1439}
1440
1441void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc,
1442 SmallVectorImpl<MCInst> &Instructions) {
1443 emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, Instructions);
1444}
1445
1446void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc,
1447 SmallVectorImpl<MCInst> &Instructions) {
1448 MCInst tmpInst;
1449 tmpInst.setOpcode(Opcode);
1450 tmpInst.addOperand(MCOperand::createImm(Imm1));
1451 tmpInst.addOperand(MCOperand::createImm(Imm2));
1452 tmpInst.setLoc(IDLoc);
1453 Instructions.push_back(tmpInst);
1454}
1455
1456void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
1457 SmallVectorImpl<MCInst> &Instructions) {
1458 MCInst tmpInst;
1459 tmpInst.setOpcode(Opcode);
1460 tmpInst.addOperand(MCOperand::createReg(Reg0));
1461 tmpInst.setLoc(IDLoc);
1462 Instructions.push_back(tmpInst);
1463}
1464
1465void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2,
1466 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1467 MCInst tmpInst;
1468 tmpInst.setOpcode(Opcode);
1469 tmpInst.addOperand(MCOperand::createReg(Reg0));
1470 tmpInst.addOperand(MCOperand::createReg(Reg1));
1471 tmpInst.addOperand(Op2);
1472 tmpInst.setLoc(IDLoc);
1473 Instructions.push_back(tmpInst);
1474}
1475
1476void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
1477 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1478 emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc,
1479 Instructions);
1480}
1481
1482void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
1483 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1484 emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc,
1485 Instructions);
1486}
1487
1488void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount,
1489 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1490 if (ShiftAmount >= 32) {
1491 emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc,
1492 Instructions);
1493 return;
1494 }
1495
1496 emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions);
1497}
1498} // end anonymous namespace.
1499
Jack Carter9e65aa32013-03-22 00:05:30 +00001500bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001501 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001502 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001503 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001504
Jack Carter9e65aa32013-03-22 00:05:30 +00001505 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001506
1507 if (MCID.isBranch() || MCID.isCall()) {
1508 const unsigned Opcode = Inst.getOpcode();
1509 MCOperand Offset;
1510
1511 switch (Opcode) {
1512 default:
1513 break;
Kai Nackee0245392015-01-27 19:11:28 +00001514 case Mips::BBIT0:
1515 case Mips::BBIT032:
1516 case Mips::BBIT1:
1517 case Mips::BBIT132:
1518 assert(hasCnMips() && "instruction only valid for octeon cpus");
1519 // Fall through
1520
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001521 case Mips::BEQ:
1522 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001523 case Mips::BEQ_MM:
1524 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001525 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001526 Offset = Inst.getOperand(2);
1527 if (!Offset.isImm())
1528 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001529 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001530 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001531 if (OffsetToAlignment(Offset.getImm(),
1532 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001533 return Error(IDLoc, "branch to misaligned address");
1534 break;
1535 case Mips::BGEZ:
1536 case Mips::BGTZ:
1537 case Mips::BLEZ:
1538 case Mips::BLTZ:
1539 case Mips::BGEZAL:
1540 case Mips::BLTZAL:
1541 case Mips::BC1F:
1542 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001543 case Mips::BGEZ_MM:
1544 case Mips::BGTZ_MM:
1545 case Mips::BLEZ_MM:
1546 case Mips::BLTZ_MM:
1547 case Mips::BGEZAL_MM:
1548 case Mips::BLTZAL_MM:
1549 case Mips::BC1F_MM:
1550 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001551 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001552 Offset = Inst.getOperand(1);
1553 if (!Offset.isImm())
1554 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001555 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001556 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001557 if (OffsetToAlignment(Offset.getImm(),
1558 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001559 return Error(IDLoc, "branch to misaligned address");
1560 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001561 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001562 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001563 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001564 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001565 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1566 Offset = Inst.getOperand(1);
1567 if (!Offset.isImm())
1568 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001569 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001570 return Error(IDLoc, "branch target out of range");
1571 if (OffsetToAlignment(Offset.getImm(), 2LL))
1572 return Error(IDLoc, "branch to misaligned address");
1573 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001574 }
1575 }
1576
Daniel Sandersa84989a2014-06-16 13:25:35 +00001577 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1578 // We still accept it but it is a normal nop.
1579 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1580 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1581 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1582 "nop instruction");
1583 }
1584
Kai Nackee0245392015-01-27 19:11:28 +00001585 if (hasCnMips()) {
1586 const unsigned Opcode = Inst.getOpcode();
1587 MCOperand Opnd;
1588 int Imm;
1589
1590 switch (Opcode) {
1591 default:
1592 break;
1593
1594 case Mips::BBIT0:
1595 case Mips::BBIT032:
1596 case Mips::BBIT1:
1597 case Mips::BBIT132:
1598 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1599 // The offset is handled above
1600 Opnd = Inst.getOperand(1);
1601 if (!Opnd.isImm())
1602 return Error(IDLoc, "expected immediate operand kind");
1603 Imm = Opnd.getImm();
1604 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1605 Opcode == Mips::BBIT1 ? 63 : 31))
1606 return Error(IDLoc, "immediate operand value out of range");
1607 if (Imm > 31) {
1608 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1609 : Mips::BBIT132);
1610 Inst.getOperand(1).setImm(Imm - 32);
1611 }
1612 break;
1613
1614 case Mips::CINS:
1615 case Mips::CINS32:
1616 case Mips::EXTS:
1617 case Mips::EXTS32:
1618 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1619 // Check length
1620 Opnd = Inst.getOperand(3);
1621 if (!Opnd.isImm())
1622 return Error(IDLoc, "expected immediate operand kind");
1623 Imm = Opnd.getImm();
1624 if (Imm < 0 || Imm > 31)
1625 return Error(IDLoc, "immediate operand value out of range");
1626 // Check position
1627 Opnd = Inst.getOperand(2);
1628 if (!Opnd.isImm())
1629 return Error(IDLoc, "expected immediate operand kind");
1630 Imm = Opnd.getImm();
1631 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1632 Opcode == Mips::EXTS ? 63 : 31))
1633 return Error(IDLoc, "immediate operand value out of range");
1634 if (Imm > 31) {
1635 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1636 Inst.getOperand(2).setImm(Imm - 32);
1637 }
1638 break;
1639
1640 case Mips::SEQi:
1641 case Mips::SNEi:
1642 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1643 Opnd = Inst.getOperand(2);
1644 if (!Opnd.isImm())
1645 return Error(IDLoc, "expected immediate operand kind");
1646 Imm = Opnd.getImm();
1647 if (!isInt<10>(Imm))
1648 return Error(IDLoc, "immediate operand value out of range");
1649 break;
1650 }
1651 }
1652
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001653 // This expansion is not in a function called by tryExpandInstruction()
1654 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001655 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1656 inPicMode()) {
1657 warnIfNoMacro(IDLoc);
1658
1659 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1660
1661 // We can do this expansion if there's only 1 symbol in the argument
1662 // expression.
1663 if (countMCSymbolRefExpr(JalExpr) > 1)
1664 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1665
1666 // FIXME: This is checking the expression can be handled by the later stages
1667 // of the assembler. We ought to leave it to those later stages but
1668 // we can't do that until we stop evaluateRelocExpr() rewriting the
1669 // expressions into non-equivalent forms.
1670 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1671
1672 // FIXME: Add support for label+offset operands (currently causes an error).
1673 // FIXME: Add support for forward-declared local symbols.
1674 // FIXME: Add expansion for when the LargeGOT option is enabled.
1675 if (JalSym->isInSection() || JalSym->isTemporary()) {
1676 if (isABI_O32()) {
1677 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001678 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001679 // R_(MICRO)MIPS_GOT16 label
1680 // addiu $25, $25, 0
1681 // R_(MICRO)MIPS_LO16 label
1682 // jalr $25
1683 const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
1684 const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
1685
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001686 emitRRX(Mips::LW, Mips::T9, Mips::GP,
1687 MCOperand::createExpr(Got16RelocExpr), IDLoc, Instructions);
1688 emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1689 MCOperand::createExpr(Lo16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001690 } else if (isABI_N32() || isABI_N64()) {
1691 // If it's a local symbol and the N32/N64 ABIs are being used,
1692 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001693 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001694 // R_(MICRO)MIPS_GOT_DISP label
1695 // jalr $25
1696 const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
1697
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001698 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1699 MCOperand::createExpr(GotDispRelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001700 }
1701 } else {
1702 // If it's an external/weak symbol, we expand to:
1703 // lw/ld $25, 0($gp)
1704 // R_(MICRO)MIPS_CALL16 label
1705 // jalr $25
1706 const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
1707
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001708 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1709 MCOperand::createExpr(Call16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001710 }
1711
1712 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001713 if (IsCpRestoreSet && inMicroMipsMode())
1714 JalrInst.setOpcode(Mips::JALRS_MM);
1715 else
1716 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001717 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1718 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1719
1720 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1721 // This relocation is supposed to be an optimization hint for the linker
1722 // and is not necessary for correctness.
1723
1724 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001725 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001726 }
1727
Jack Carter9e65aa32013-03-22 00:05:30 +00001728 if (MCID.mayLoad() || MCID.mayStore()) {
1729 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001730 // reference or immediate we may have to expand instructions.
1731 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001732 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001733 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1734 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001735 MCOperand &Op = Inst.getOperand(i);
1736 if (Op.isImm()) {
1737 int MemOffset = Op.getImm();
1738 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001739 // Offset can't exceed 16bit value.
1740 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001741 return false;
1742 }
1743 } else if (Op.isExpr()) {
1744 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001745 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001746 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001747 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001748 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001749 // Expand symbol.
1750 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001751 return false;
1752 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001753 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001754 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001755 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001756 }
1757 }
1758 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001759 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001760 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001761
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001762 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001763 if (MCID.mayLoad()) {
1764 // Try to create 16-bit GP relative load instruction.
1765 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1766 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1767 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1768 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1769 MCOperand &Op = Inst.getOperand(i);
1770 if (Op.isImm()) {
1771 int MemOffset = Op.getImm();
1772 MCOperand &DstReg = Inst.getOperand(0);
1773 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00001774 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00001775 getContext().getRegisterInfo()->getRegClass(
1776 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001777 (BaseReg.getReg() == Mips::GP ||
1778 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001779
1780 emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
1781 IDLoc, Instructions);
Jozef Koleke10a02e2015-01-28 17:27:26 +00001782 return false;
1783 }
1784 }
1785 }
1786 } // for
1787 } // if load
1788
1789 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1790
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001791 MCOperand Opnd;
1792 int Imm;
1793
1794 switch (Inst.getOpcode()) {
1795 default:
1796 break;
1797 case Mips::ADDIUS5_MM:
1798 Opnd = Inst.getOperand(2);
1799 if (!Opnd.isImm())
1800 return Error(IDLoc, "expected immediate operand kind");
1801 Imm = Opnd.getImm();
1802 if (Imm < -8 || Imm > 7)
1803 return Error(IDLoc, "immediate operand value out of range");
1804 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001805 case Mips::ADDIUSP_MM:
1806 Opnd = Inst.getOperand(0);
1807 if (!Opnd.isImm())
1808 return Error(IDLoc, "expected immediate operand kind");
1809 Imm = Opnd.getImm();
1810 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1811 Imm % 4 != 0)
1812 return Error(IDLoc, "immediate operand value out of range");
1813 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001814 case Mips::SLL16_MM:
1815 case Mips::SRL16_MM:
1816 Opnd = Inst.getOperand(2);
1817 if (!Opnd.isImm())
1818 return Error(IDLoc, "expected immediate operand kind");
1819 Imm = Opnd.getImm();
1820 if (Imm < 1 || Imm > 8)
1821 return Error(IDLoc, "immediate operand value out of range");
1822 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001823 case Mips::LI16_MM:
1824 Opnd = Inst.getOperand(1);
1825 if (!Opnd.isImm())
1826 return Error(IDLoc, "expected immediate operand kind");
1827 Imm = Opnd.getImm();
1828 if (Imm < -1 || Imm > 126)
1829 return Error(IDLoc, "immediate operand value out of range");
1830 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001831 case Mips::ADDIUR2_MM:
1832 Opnd = Inst.getOperand(2);
1833 if (!Opnd.isImm())
1834 return Error(IDLoc, "expected immediate operand kind");
1835 Imm = Opnd.getImm();
1836 if (!(Imm == 1 || Imm == -1 ||
1837 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1838 return Error(IDLoc, "immediate operand value out of range");
1839 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001840 case Mips::ADDIUR1SP_MM:
1841 Opnd = Inst.getOperand(1);
1842 if (!Opnd.isImm())
1843 return Error(IDLoc, "expected immediate operand kind");
1844 Imm = Opnd.getImm();
1845 if (OffsetToAlignment(Imm, 4LL))
1846 return Error(IDLoc, "misaligned immediate operand value");
1847 if (Imm < 0 || Imm > 255)
1848 return Error(IDLoc, "immediate operand value out of range");
1849 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001850 case Mips::ANDI16_MM:
1851 Opnd = Inst.getOperand(2);
1852 if (!Opnd.isImm())
1853 return Error(IDLoc, "expected immediate operand kind");
1854 Imm = Opnd.getImm();
1855 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1856 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1857 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1858 return Error(IDLoc, "immediate operand value out of range");
1859 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001860 case Mips::LBU16_MM:
1861 Opnd = Inst.getOperand(2);
1862 if (!Opnd.isImm())
1863 return Error(IDLoc, "expected immediate operand kind");
1864 Imm = Opnd.getImm();
1865 if (Imm < -1 || Imm > 14)
1866 return Error(IDLoc, "immediate operand value out of range");
1867 break;
Zoran Jovanovic7ba636c2015-09-17 10:14:09 +00001868 case Mips::TEQ_MM:
1869 case Mips::TGE_MM:
1870 case Mips::TGEU_MM:
1871 case Mips::TLT_MM:
1872 case Mips::TLTU_MM:
1873 case Mips::TNE_MM:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001874 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001875 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001876 Opnd = Inst.getOperand(2);
1877 if (!Opnd.isImm())
1878 return Error(IDLoc, "expected immediate operand kind");
1879 Imm = Opnd.getImm();
1880 if (Imm < 0 || Imm > 15)
1881 return Error(IDLoc, "immediate operand value out of range");
1882 break;
1883 case Mips::LHU16_MM:
1884 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001885 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001886 Opnd = Inst.getOperand(2);
1887 if (!Opnd.isImm())
1888 return Error(IDLoc, "expected immediate operand kind");
1889 Imm = Opnd.getImm();
1890 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1891 return Error(IDLoc, "immediate operand value out of range");
1892 break;
1893 case Mips::LW16_MM:
1894 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001895 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001896 Opnd = Inst.getOperand(2);
1897 if (!Opnd.isImm())
1898 return Error(IDLoc, "expected immediate operand kind");
1899 Imm = Opnd.getImm();
1900 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1901 return Error(IDLoc, "immediate operand value out of range");
1902 break;
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +00001903 case Mips::PREFX_MM:
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001904 case Mips::CACHE:
1905 case Mips::PREF:
1906 Opnd = Inst.getOperand(2);
1907 if (!Opnd.isImm())
1908 return Error(IDLoc, "expected immediate operand kind");
1909 Imm = Opnd.getImm();
1910 if (!isUInt<5>(Imm))
1911 return Error(IDLoc, "immediate operand value out of range");
1912 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001913 case Mips::ADDIUPC_MM:
1914 MCOperand Opnd = Inst.getOperand(1);
1915 if (!Opnd.isImm())
1916 return Error(IDLoc, "expected immediate operand kind");
1917 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00001918 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001919 return Error(IDLoc, "immediate operand value out of range");
1920 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001921 }
1922 }
1923
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001924 MacroExpanderResultTy ExpandResult =
1925 tryExpandInstruction(Inst, IDLoc, Instructions);
1926 switch (ExpandResult) {
1927 case MER_NotAMacro:
Jack Carter9e65aa32013-03-22 00:05:30 +00001928 Instructions.push_back(Inst);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001929 break;
1930 case MER_Success:
1931 break;
1932 case MER_Fail:
1933 return true;
1934 }
Jack Carter9e65aa32013-03-22 00:05:30 +00001935
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001936 // If this instruction has a delay slot and .set reorder is active,
1937 // emit a NOP after it.
1938 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1939 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1940
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001941 if ((Inst.getOpcode() == Mips::JalOneReg ||
1942 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
1943 isPicAndNotNxxAbi()) {
1944 if (IsCpRestoreSet) {
1945 // We need a NOP between the JALR and the LW:
1946 // If .set reorder has been used, we've already emitted a NOP.
1947 // If .set noreorder has been used, we need to emit a NOP at this point.
1948 if (!AssemblerOptions.back()->isReorder())
1949 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1950
1951 // Load the $gp from the stack.
1952 SmallVector<MCInst, 3> LoadInsts;
1953 createCpRestoreMemOp(true /*IsLoad*/, CpRestoreOffset /*StackOffset*/,
1954 IDLoc, LoadInsts);
1955
1956 for (const MCInst &Inst : LoadInsts)
1957 Instructions.push_back(Inst);
1958
1959 } else
1960 Warning(IDLoc, "no .cprestore used in PIC mode");
1961 }
1962
Jack Carter9e65aa32013-03-22 00:05:30 +00001963 return false;
1964}
1965
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001966MipsAsmParser::MacroExpanderResultTy
1967MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
1968 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001969 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001970 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001971 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001972 case Mips::LoadImm32:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001973 return expandLoadImm(Inst, true, IDLoc, Instructions) ? MER_Fail
1974 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001975 case Mips::LoadImm64:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001976 return expandLoadImm(Inst, false, IDLoc, Instructions) ? MER_Fail
1977 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001978 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001979 case Mips::LoadAddrImm64:
1980 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1981 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1982 "expected immediate operand kind");
1983
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001984 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
1985 Inst.getOperand(1),
1986 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
1987 Instructions)
1988 ? MER_Fail
1989 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001990 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001991 case Mips::LoadAddrReg64:
1992 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1993 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1994 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
1995 "expected immediate operand kind");
1996
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001997 return expandLoadAddress(Inst.getOperand(0).getReg(),
1998 Inst.getOperand(1).getReg(), Inst.getOperand(2),
1999 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
2000 Instructions)
2001 ? MER_Fail
2002 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002003 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002004 case Mips::B_MMR6_Pseudo:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002005 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions) ? MER_Fail
2006 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002007 case Mips::SWM_MM:
2008 case Mips::LWM_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002009 return expandLoadStoreMultiple(Inst, IDLoc, Instructions) ? MER_Fail
2010 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002011 case Mips::JalOneReg:
2012 case Mips::JalTwoReg:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002013 return expandJalWithRegs(Inst, IDLoc, Instructions) ? MER_Fail
2014 : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002015 case Mips::BneImm:
2016 case Mips::BeqImm:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002017 return expandBranchImm(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002018 case Mips::BLT:
2019 case Mips::BLE:
2020 case Mips::BGE:
2021 case Mips::BGT:
2022 case Mips::BLTU:
2023 case Mips::BLEU:
2024 case Mips::BGEU:
2025 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002026 case Mips::BLTL:
2027 case Mips::BLEL:
2028 case Mips::BGEL:
2029 case Mips::BGTL:
2030 case Mips::BLTUL:
2031 case Mips::BLEUL:
2032 case Mips::BGEUL:
2033 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002034 case Mips::BLTImmMacro:
2035 case Mips::BLEImmMacro:
2036 case Mips::BGEImmMacro:
2037 case Mips::BGTImmMacro:
2038 case Mips::BLTUImmMacro:
2039 case Mips::BLEUImmMacro:
2040 case Mips::BGEUImmMacro:
2041 case Mips::BGTUImmMacro:
2042 case Mips::BLTLImmMacro:
2043 case Mips::BLELImmMacro:
2044 case Mips::BGELImmMacro:
2045 case Mips::BGTLImmMacro:
2046 case Mips::BLTULImmMacro:
2047 case Mips::BLEULImmMacro:
2048 case Mips::BGEULImmMacro:
2049 case Mips::BGTULImmMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002050 return expandCondBranches(Inst, IDLoc, Instructions) ? MER_Fail
2051 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002052 case Mips::SDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002053 return expandDiv(Inst, IDLoc, Instructions, false, true) ? MER_Fail
2054 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002055 case Mips::DSDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002056 return expandDiv(Inst, IDLoc, Instructions, true, true) ? MER_Fail
2057 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002058 case Mips::UDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002059 return expandDiv(Inst, IDLoc, Instructions, false, false) ? MER_Fail
2060 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002061 case Mips::DUDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002062 return expandDiv(Inst, IDLoc, Instructions, true, false) ? MER_Fail
2063 : MER_Success;
Daniel Sanders6394ee52015-10-15 14:52:58 +00002064 case Mips::Ulh:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002065 return expandUlh(Inst, true, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacud88d79c2015-06-23 14:39:42 +00002066 case Mips::Ulhu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002067 return expandUlh(Inst, false, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00002068 case Mips::Ulw:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002069 return expandUlw(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
2070 case Mips::NORImm:
2071 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2072 : MER_Success;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002073 case Mips::ADDi:
2074 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002075 case Mips::SLTi:
2076 case Mips::SLTiu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002077 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2078 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2079 int64_t ImmValue = Inst.getOperand(2).getImm();
2080 if (isInt<16>(ImmValue))
2081 return MER_NotAMacro;
2082 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2083 : MER_Success;
2084 }
2085 return MER_NotAMacro;
2086 case Mips::ANDi:
2087 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002088 case Mips::XORi:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002089 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2090 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2091 int64_t ImmValue = Inst.getOperand(2).getImm();
2092 if (isUInt<16>(ImmValue))
2093 return MER_NotAMacro;
2094 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2095 : MER_Success;
2096 }
2097 return MER_NotAMacro;
Jack Carterd0bd6422013-04-18 00:41:53 +00002098 }
Jack Carter30a59822012-10-04 04:03:53 +00002099}
Jack Carter92995f12012-10-06 00:53:28 +00002100
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002101bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
2102 SmallVectorImpl<MCInst> &Instructions) {
2103 // Create a JALR instruction which is going to replace the pseudo-JAL.
2104 MCInst JalrInst;
2105 JalrInst.setLoc(IDLoc);
2106 const MCOperand FirstRegOp = Inst.getOperand(0);
2107 const unsigned Opcode = Inst.getOpcode();
2108
2109 if (Opcode == Mips::JalOneReg) {
2110 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002111 if (IsCpRestoreSet && inMicroMipsMode()) {
2112 JalrInst.setOpcode(Mips::JALRS16_MM);
2113 JalrInst.addOperand(FirstRegOp);
2114 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002115 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002116 JalrInst.addOperand(FirstRegOp);
2117 } else {
2118 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002119 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002120 JalrInst.addOperand(FirstRegOp);
2121 }
2122 } else if (Opcode == Mips::JalTwoReg) {
2123 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002124 if (IsCpRestoreSet && inMicroMipsMode())
2125 JalrInst.setOpcode(Mips::JALRS_MM);
2126 else
2127 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002128 JalrInst.addOperand(FirstRegOp);
2129 const MCOperand SecondRegOp = Inst.getOperand(1);
2130 JalrInst.addOperand(SecondRegOp);
2131 }
2132 Instructions.push_back(JalrInst);
2133
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002134 // If .set reorder is active and branch instruction has a delay slot,
2135 // emit a NOP after it.
2136 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
2137 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002138 createNop(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, Instructions);
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002139 }
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002140
2141 return false;
2142}
2143
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002144/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002145template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002146 unsigned BitNum = findFirstSet(x);
2147
2148 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2149}
2150
2151/// Load (or add) an immediate into a register.
2152///
2153/// @param ImmValue The immediate to load.
2154/// @param DstReg The register that will hold the immediate.
2155/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2156/// for a simple initialization.
2157/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2158/// @param IsAddress True if the immediate represents an address. False if it
2159/// is an integer.
2160/// @param IDLoc Location of the immediate in the source file.
2161/// @param Instructions The instructions emitted by this expansion.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002162bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002163 unsigned SrcReg, bool Is32BitImm,
2164 bool IsAddress, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00002165 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00002166 if (!Is32BitImm && !isGP64bit()) {
2167 Error(IDLoc, "instruction requires a 64-bit architecture");
2168 return true;
2169 }
2170
Daniel Sanders03f9c012015-07-14 12:24:22 +00002171 if (Is32BitImm) {
2172 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2173 // Sign extend up to 64-bit so that the predicates match the hardware
2174 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2175 // true.
2176 ImmValue = SignExtend64<32>(ImmValue);
2177 } else {
2178 Error(IDLoc, "instruction requires a 32-bit immediate");
2179 return true;
2180 }
2181 }
2182
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002183 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2184 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2185
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002186 bool UseSrcReg = false;
2187 if (SrcReg != Mips::NoRegister)
2188 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002189
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002190 unsigned TmpReg = DstReg;
2191 if (UseSrcReg && (DstReg == SrcReg)) {
2192 // At this point we need AT to perform the expansions and we exit if it is
2193 // not available.
2194 unsigned ATReg = getATReg(IDLoc);
2195 if (!ATReg)
2196 return true;
2197 TmpReg = ATReg;
2198 }
2199
Daniel Sanders03f9c012015-07-14 12:24:22 +00002200 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002201 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002202 SrcReg = ZeroReg;
2203
2204 // This doesn't quite follow the usual ABI expectations for N32 but matches
2205 // traditional assembler behaviour. N32 would normally use addiu for both
2206 // integers and addresses.
2207 if (IsAddress && !Is32BitImm) {
2208 emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2209 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002210 }
2211
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002212 emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2213 return false;
2214 }
2215
2216 if (isUInt<16>(ImmValue)) {
2217 unsigned TmpReg = DstReg;
2218 if (SrcReg == DstReg) {
2219 TmpReg = getATReg(IDLoc);
2220 if (!TmpReg)
2221 return true;
2222 }
2223
2224 emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002225 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002226 emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2227 return false;
2228 }
2229
2230 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002231 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002232
Toma Tabacu79588102015-04-29 10:19:56 +00002233 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2234 uint16_t Bits15To0 = ImmValue & 0xffff;
2235
Toma Tabacua3d056f2015-05-15 09:42:11 +00002236 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002237 // Traditional behaviour seems to special case this particular value. It's
2238 // not clear why other masks are handled differently.
2239 if (ImmValue == 0xffffffff) {
Daniel Sandersf1ae3672015-08-18 09:55:57 +00002240 emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002241 emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, Instructions);
2242 if (UseSrcReg)
2243 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2244 return false;
2245 }
2246
2247 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002248 // upper 32 bits.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002249 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002250 emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002251 if (Bits15To0)
2252 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
2253 if (UseSrcReg)
2254 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2255 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002256 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002257
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002258 emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions);
2259 if (Bits15To0)
2260 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002261 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002262 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2263 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002264 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002265
2266 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2267 if (Is32BitImm) {
2268 Error(IDLoc, "instruction requires a 32-bit immediate");
2269 return true;
2270 }
2271
2272 // Traditionally, these immediates are shifted as little as possible and as
2273 // such we align the most significant bit to bit 15 of our temporary.
2274 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2275 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2276 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2277 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
2278 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, Instructions);
2279 emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, Instructions);
2280
2281 if (UseSrcReg)
2282 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2283
2284 return false;
2285 }
2286
2287 warnIfNoMacro(IDLoc);
2288
2289 // The remaining case is packed with a sequence of dsll and ori with zeros
2290 // being omitted and any neighbouring dsll's being coalesced.
2291 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2292
2293 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2294 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
2295 IDLoc, Instructions))
2296 return false;
2297
2298 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2299 // skip it and defer the shift to the next chunk.
2300 unsigned ShiftCarriedForwards = 16;
2301 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2302 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2303
2304 if (ImmChunk != 0) {
2305 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2306 Instructions);
2307 emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, Instructions);
2308 ShiftCarriedForwards = 0;
2309 }
2310
2311 ShiftCarriedForwards += 16;
2312 }
2313 ShiftCarriedForwards -= 16;
2314
2315 // Finish any remaining shifts left by trailing zeros.
2316 if (ShiftCarriedForwards)
2317 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2318 Instructions);
2319
2320 if (UseSrcReg)
2321 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2322
Matheus Almeida3813d572014-06-19 14:39:14 +00002323 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002324}
Jack Carter92995f12012-10-06 00:53:28 +00002325
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002326bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
2327 SmallVectorImpl<MCInst> &Instructions) {
2328 const MCOperand &ImmOp = Inst.getOperand(1);
2329 assert(ImmOp.isImm() && "expected immediate operand kind");
2330 const MCOperand &DstRegOp = Inst.getOperand(0);
2331 assert(DstRegOp.isReg() && "expected register operand kind");
2332
2333 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002334 Is32BitImm, false, IDLoc, Instructions))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002335 return true;
2336
2337 return false;
2338}
2339
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002340bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2341 const MCOperand &Offset,
2342 bool Is32BitAddress, SMLoc IDLoc,
2343 SmallVectorImpl<MCInst> &Instructions) {
2344 // la can't produce a usable address when addresses are 64-bit.
2345 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2346 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2347 // We currently can't do this because we depend on the equality
2348 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2349 Error(IDLoc, "la used to load 64-bit address");
2350 // Continue as if we had 'dla' instead.
2351 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002352 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002353
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002354 // dla requires 64-bit addresses.
2355 if (!Is32BitAddress && !ABI.ArePtrs64bit()) {
2356 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002357 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002358 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002359
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002360 if (!Offset.isImm())
2361 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
2362 Is32BitAddress, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002363
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002364 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
2365 IDLoc, Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +00002366}
2367
Toma Tabacuf712ede2015-06-17 14:31:51 +00002368bool MipsAsmParser::loadAndAddSymbolAddress(
2369 const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
2370 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002371 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002372
Daniel Sandersd5a89412015-10-05 13:19:29 +00002373 const MCExpr *Symbol = cast<MCExpr>(SymExpr);
2374 const MipsMCExpr *HiExpr = MipsMCExpr::create(
2375 MCSymbolRefExpr::VK_Mips_ABS_HI, Symbol, getContext());
2376 const MipsMCExpr *LoExpr = MipsMCExpr::create(
2377 MCSymbolRefExpr::VK_Mips_ABS_LO, Symbol, getContext());
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002378
Toma Tabacufb9d1252015-06-22 12:08:39 +00002379 bool UseSrcReg = SrcReg != Mips::NoRegister;
2380
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002381 // This is the 64-bit symbol address expansion.
2382 if (ABI.ArePtrs64bit() && isGP64bit()) {
2383 // We always need AT for the 64-bit expansion.
2384 // If it is not available we exit.
2385 unsigned ATReg = getATReg(IDLoc);
2386 if (!ATReg)
2387 return true;
2388
Daniel Sandersd5a89412015-10-05 13:19:29 +00002389 const MipsMCExpr *HighestExpr = MipsMCExpr::create(
2390 MCSymbolRefExpr::VK_Mips_HIGHEST, Symbol, getContext());
2391 const MipsMCExpr *HigherExpr = MipsMCExpr::create(
2392 MCSymbolRefExpr::VK_Mips_HIGHER, Symbol, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002393
2394 if (UseSrcReg && (DstReg == SrcReg)) {
2395 // If $rs is the same as $rd:
2396 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2397 // daddiu $at, $at, %higher(sym)
2398 // dsll $at, $at, 16
2399 // daddiu $at, $at, %hi(sym)
2400 // dsll $at, $at, 16
2401 // daddiu $at, $at, %lo(sym)
2402 // daddu $rd, $at, $rd
2403 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2404 Instructions);
2405 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr),
2406 IDLoc, Instructions);
2407 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2408 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2409 Instructions);
2410 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2411 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2412 Instructions);
2413 emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions);
2414
2415 return false;
2416 }
2417
2418 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2419 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2420 // lui $at, %hi(sym)
2421 // daddiu $rd, $rd, %higher(sym)
2422 // daddiu $at, $at, %lo(sym)
2423 // dsll32 $rd, $rd, 0
2424 // daddu $rd, $rd, $at
2425 // (daddu $rd, $rd, $rs)
2426 emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2427 Instructions);
2428 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2429 Instructions);
2430 emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr),
2431 IDLoc, Instructions);
2432 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2433 Instructions);
2434 emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions);
2435 emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions);
2436 if (UseSrcReg)
2437 emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions);
2438
2439 return false;
2440 }
2441
2442 // And now, the 32-bit symbol address expansion:
2443 // If $rs is the same as $rd:
2444 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2445 // ori $at, $at, %lo(sym)
2446 // addu $rd, $at, $rd
2447 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2448 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2449 // ori $rd, $rd, %lo(sym)
2450 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002451 unsigned TmpReg = DstReg;
2452 if (UseSrcReg && (DstReg == SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002453 // If $rs is the same as $rd, we need to use AT.
2454 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002455 unsigned ATReg = getATReg(IDLoc);
2456 if (!ATReg)
2457 return true;
2458 TmpReg = ATReg;
2459 }
2460
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002461 emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions);
2462 emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc,
2463 Instructions);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002464
Toma Tabacufb9d1252015-06-22 12:08:39 +00002465 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002466 emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2467 else
2468 assert(DstReg == TmpReg);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002469
Toma Tabacu674825c2015-06-16 12:16:24 +00002470 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002471}
2472
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002473bool MipsAsmParser::expandUncondBranchMMPseudo(
2474 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002475 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2476 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002477
2478 MCOperand Offset = Inst.getOperand(0);
2479 if (Offset.isExpr()) {
2480 Inst.clear();
2481 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002482 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2483 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2484 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002485 } else {
2486 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002487 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002488 // If offset fits into 11 bits then this instruction becomes microMIPS
2489 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002490 if (inMicroMipsMode())
2491 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002492 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002493 if (!isInt<17>(Offset.getImm()))
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002494 Error(IDLoc, "branch target out of range");
2495 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2496 Error(IDLoc, "branch to misaligned address");
2497 Inst.clear();
2498 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002499 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2500 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2501 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002502 }
2503 }
2504 Instructions.push_back(Inst);
2505
Zoran Jovanovicada70912015-09-07 11:56:37 +00002506 // If .set reorder is active and branch instruction has a delay slot,
2507 // emit a NOP after it.
2508 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2509 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Toma Tabacu234482a2015-03-16 12:03:39 +00002510 createNop(true, IDLoc, Instructions);
2511
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002512 return false;
2513}
2514
Toma Tabacue1e460d2015-06-11 10:36:10 +00002515bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2516 SmallVectorImpl<MCInst> &Instructions) {
2517 const MCOperand &DstRegOp = Inst.getOperand(0);
2518 assert(DstRegOp.isReg() && "expected register operand kind");
2519
2520 const MCOperand &ImmOp = Inst.getOperand(1);
2521 assert(ImmOp.isImm() && "expected immediate operand kind");
2522
2523 const MCOperand &MemOffsetOp = Inst.getOperand(2);
2524 assert(MemOffsetOp.isImm() && "expected immediate operand kind");
2525
2526 unsigned OpCode = 0;
2527 switch(Inst.getOpcode()) {
2528 case Mips::BneImm:
2529 OpCode = Mips::BNE;
2530 break;
2531 case Mips::BeqImm:
2532 OpCode = Mips::BEQ;
2533 break;
2534 default:
2535 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2536 break;
2537 }
2538
2539 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002540 if (ImmValue == 0)
2541 emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2542 Instructions);
2543 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002544 warnIfNoMacro(IDLoc);
2545
2546 unsigned ATReg = getATReg(IDLoc);
2547 if (!ATReg)
2548 return true;
2549
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002550 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
2551 IDLoc, Instructions))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002552 return true;
2553
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002554 emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002555 }
2556 return false;
2557}
2558
Jack Carter9e65aa32013-03-22 00:05:30 +00002559void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002560 SmallVectorImpl<MCInst> &Instructions,
2561 bool isLoad, bool isImmOpnd) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002562 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002563 const MCExpr *ExprOffset;
2564 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002565 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002566 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2567 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002568 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002569 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2570 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002571 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002572 if (isImmOpnd) {
2573 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2574 ImmOffset = Inst.getOperand(2).getImm();
2575 LoOffset = ImmOffset & 0x0000ffff;
2576 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002577 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002578 if (LoOffset & 0x8000)
2579 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002580 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002581 ExprOffset = Inst.getOperand(2).getExpr();
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002582 // These are some of the types of expansions we perform here:
2583 // 1) lw $8, sym => lui $8, %hi(sym)
2584 // lw $8, %lo(sym)($8)
2585 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2586 // add $8, $8, $9
2587 // lw $8, %lo(offset)($9)
2588 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2589 // add $at, $at, $8
2590 // lw $8, %lo(offset)($at)
2591 // 4) sw $8, sym => lui $at, %hi(sym)
2592 // sw $8, %lo(sym)($at)
2593 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2594 // add $at, $at, $8
2595 // sw $8, %lo(offset)($at)
2596 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2597 // ldc1 $f0, %lo(sym)($at)
2598 //
2599 // For load instructions we can use the destination register as a temporary
2600 // if base and dst are different (examples 1 and 2) and if the base register
2601 // is general purpose otherwise we must use $at (example 6) and error if it's
2602 // not available. For stores we must use $at (examples 4 and 5) because we
2603 // must not clobber the source register setting up the offset.
2604 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2605 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2606 unsigned RegClassIDOp0 =
2607 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2608 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2609 (RegClassIDOp0 == Mips::GPR64RegClassID);
2610 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002611 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002612 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002613 // At this point we need AT to perform the expansions and we exit if it is
2614 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002615 TmpRegNum = getATReg(IDLoc);
2616 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002617 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002618 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002619
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002620 emitRX(Mips::LUi, TmpRegNum,
2621 isImmOpnd ? MCOperand::createImm(HiOffset)
2622 : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "hi")),
2623 IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00002624 // Add temp register to base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002625 if (BaseRegNum != Mips::ZERO)
2626 emitRRR(Mips::ADDu, TmpRegNum, TmpRegNum, BaseRegNum, IDLoc, Instructions);
Alp Tokercb402912014-01-24 17:20:08 +00002627 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002628 // of offset and new base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002629 emitRRX(Inst.getOpcode(), RegOpNum, TmpRegNum,
2630 isImmOpnd
2631 ? MCOperand::createImm(LoOffset)
2632 : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "lo")),
2633 IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00002634}
2635
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002636bool
2637MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2638 SmallVectorImpl<MCInst> &Instructions) {
2639 unsigned OpNum = Inst.getNumOperands();
2640 unsigned Opcode = Inst.getOpcode();
2641 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2642
2643 assert (Inst.getOperand(OpNum - 1).isImm() &&
2644 Inst.getOperand(OpNum - 2).isReg() &&
2645 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2646
2647 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2648 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002649 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
2650 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
2651 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
2652 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002653 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002654 if (inMicroMipsMode() && hasMips32r6())
2655 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
2656 else
2657 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2658 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002659
2660 Inst.setOpcode(NewOpcode);
2661 Instructions.push_back(Inst);
2662 return false;
2663}
2664
Toma Tabacu1a108322015-06-17 13:20:24 +00002665bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2666 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002667 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00002668 unsigned PseudoOpcode = Inst.getOpcode();
2669 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002670 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00002671 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2672
2673 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002674 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002675
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002676 unsigned TrgReg;
2677 if (TrgOp.isReg())
2678 TrgReg = TrgOp.getReg();
2679 else if (TrgOp.isImm()) {
2680 warnIfNoMacro(IDLoc);
2681 EmittedNoMacroWarning = true;
2682
2683 TrgReg = getATReg(IDLoc);
2684 if (!TrgReg)
2685 return true;
2686
2687 switch(PseudoOpcode) {
2688 default:
2689 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2690 case Mips::BLTImmMacro:
2691 PseudoOpcode = Mips::BLT;
2692 break;
2693 case Mips::BLEImmMacro:
2694 PseudoOpcode = Mips::BLE;
2695 break;
2696 case Mips::BGEImmMacro:
2697 PseudoOpcode = Mips::BGE;
2698 break;
2699 case Mips::BGTImmMacro:
2700 PseudoOpcode = Mips::BGT;
2701 break;
2702 case Mips::BLTUImmMacro:
2703 PseudoOpcode = Mips::BLTU;
2704 break;
2705 case Mips::BLEUImmMacro:
2706 PseudoOpcode = Mips::BLEU;
2707 break;
2708 case Mips::BGEUImmMacro:
2709 PseudoOpcode = Mips::BGEU;
2710 break;
2711 case Mips::BGTUImmMacro:
2712 PseudoOpcode = Mips::BGTU;
2713 break;
2714 case Mips::BLTLImmMacro:
2715 PseudoOpcode = Mips::BLTL;
2716 break;
2717 case Mips::BLELImmMacro:
2718 PseudoOpcode = Mips::BLEL;
2719 break;
2720 case Mips::BGELImmMacro:
2721 PseudoOpcode = Mips::BGEL;
2722 break;
2723 case Mips::BGTLImmMacro:
2724 PseudoOpcode = Mips::BGTL;
2725 break;
2726 case Mips::BLTULImmMacro:
2727 PseudoOpcode = Mips::BLTUL;
2728 break;
2729 case Mips::BLEULImmMacro:
2730 PseudoOpcode = Mips::BLEUL;
2731 break;
2732 case Mips::BGEULImmMacro:
2733 PseudoOpcode = Mips::BGEUL;
2734 break;
2735 case Mips::BGTULImmMacro:
2736 PseudoOpcode = Mips::BGTUL;
2737 break;
2738 }
2739
2740 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
2741 false, IDLoc, Instructions))
2742 return true;
2743 }
2744
Toma Tabacu1a108322015-06-17 13:20:24 +00002745 switch (PseudoOpcode) {
2746 case Mips::BLT:
2747 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002748 case Mips::BLTL:
2749 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002750 AcceptsEquality = false;
2751 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002752 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2753 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002754 ZeroSrcOpcode = Mips::BGTZ;
2755 ZeroTrgOpcode = Mips::BLTZ;
2756 break;
2757 case Mips::BLE:
2758 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002759 case Mips::BLEL:
2760 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002761 AcceptsEquality = true;
2762 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002763 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2764 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002765 ZeroSrcOpcode = Mips::BGEZ;
2766 ZeroTrgOpcode = Mips::BLEZ;
2767 break;
2768 case Mips::BGE:
2769 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002770 case Mips::BGEL:
2771 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002772 AcceptsEquality = true;
2773 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002774 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2775 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002776 ZeroSrcOpcode = Mips::BLEZ;
2777 ZeroTrgOpcode = Mips::BGEZ;
2778 break;
2779 case Mips::BGT:
2780 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002781 case Mips::BGTL:
2782 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002783 AcceptsEquality = false;
2784 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002785 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2786 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002787 ZeroSrcOpcode = Mips::BLTZ;
2788 ZeroTrgOpcode = Mips::BGTZ;
2789 break;
2790 default:
2791 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2792 }
2793
Toma Tabacu1a108322015-06-17 13:20:24 +00002794 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2795 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2796 if (IsSrcRegZero && IsTrgRegZero) {
2797 // FIXME: All of these Opcode-specific if's are needed for compatibility
2798 // with GAS' behaviour. However, they may not generate the most efficient
2799 // code in some circumstances.
2800 if (PseudoOpcode == Mips::BLT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002801 emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2802 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002803 return false;
2804 }
2805 if (PseudoOpcode == Mips::BLE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002806 emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2807 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002808 Warning(IDLoc, "branch is always taken");
2809 return false;
2810 }
2811 if (PseudoOpcode == Mips::BGE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002812 emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2813 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002814 Warning(IDLoc, "branch is always taken");
2815 return false;
2816 }
2817 if (PseudoOpcode == Mips::BGT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002818 emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2819 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002820 return false;
2821 }
2822 if (PseudoOpcode == Mips::BGTU) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002823 emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
2824 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002825 return false;
2826 }
2827 if (AcceptsEquality) {
2828 // If both registers are $0 and the pseudo-branch accepts equality, it
2829 // will always be taken, so we emit an unconditional branch.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002830 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2831 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002832 Warning(IDLoc, "branch is always taken");
2833 return false;
2834 }
2835 // If both registers are $0 and the pseudo-branch does not accept
2836 // equality, it will never be taken, so we don't have to emit anything.
2837 return false;
2838 }
2839 if (IsSrcRegZero || IsTrgRegZero) {
2840 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2841 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2842 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2843 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2844 // the pseudo-branch will never be taken, so we don't emit anything.
2845 // This only applies to unsigned pseudo-branches.
2846 return false;
2847 }
2848 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2849 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2850 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2851 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2852 // the pseudo-branch will always be taken, so we emit an unconditional
2853 // branch.
2854 // This only applies to unsigned pseudo-branches.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002855 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2856 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002857 Warning(IDLoc, "branch is always taken");
2858 return false;
2859 }
2860 if (IsUnsigned) {
2861 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2862 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2863 // the pseudo-branch will be taken only when the non-zero register is
2864 // different from 0, so we emit a BNEZ.
2865 //
2866 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2867 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2868 // the pseudo-branch will be taken only when the non-zero register is
2869 // equal to 0, so we emit a BEQZ.
2870 //
2871 // Because only BLEU and BGEU branch on equality, we can use the
2872 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002873 emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
2874 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
2875 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002876 return false;
2877 }
2878 // If we have a signed pseudo-branch and one of the registers is $0,
2879 // we can use an appropriate compare-to-zero branch. We select which one
2880 // to use in the switch statement above.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002881 emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
2882 IsSrcRegZero ? TrgReg : SrcReg, MCOperand::createExpr(OffsetExpr),
2883 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002884 return false;
2885 }
2886
2887 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2888 // expansions. If it is not available, we return.
2889 unsigned ATRegNum = getATReg(IDLoc);
2890 if (!ATRegNum)
2891 return true;
2892
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002893 if (!EmittedNoMacroWarning)
2894 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00002895
2896 // SLT fits well with 2 of our 4 pseudo-branches:
2897 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2898 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2899 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2900 // This is accomplished by using a BNEZ with the result of the SLT.
2901 //
2902 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2903 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2904 // Because only BGE and BLE branch on equality, we can use the
2905 // AcceptsEquality variable to decide when to emit the BEQZ.
2906 // Note that the order of the SLT arguments doesn't change between
2907 // opposites.
2908 //
2909 // The same applies to the unsigned variants, except that SLTu is used
2910 // instead of SLT.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002911 emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
2912 ReverseOrderSLT ? TrgReg : SrcReg, ReverseOrderSLT ? SrcReg : TrgReg,
2913 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002914
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002915 emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
2916 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
2917 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2918 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002919 return false;
2920}
2921
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002922bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
2923 SmallVectorImpl<MCInst> &Instructions,
2924 const bool IsMips64, const bool Signed) {
2925 if (hasMips32r6()) {
2926 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2927 return false;
2928 }
2929
2930 warnIfNoMacro(IDLoc);
2931
2932 const MCOperand &RsRegOp = Inst.getOperand(0);
2933 assert(RsRegOp.isReg() && "expected register operand kind");
2934 unsigned RsReg = RsRegOp.getReg();
2935
2936 const MCOperand &RtRegOp = Inst.getOperand(1);
2937 assert(RtRegOp.isReg() && "expected register operand kind");
2938 unsigned RtReg = RtRegOp.getReg();
2939 unsigned DivOp;
2940 unsigned ZeroReg;
2941
2942 if (IsMips64) {
2943 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2944 ZeroReg = Mips::ZERO_64;
2945 } else {
2946 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2947 ZeroReg = Mips::ZERO;
2948 }
2949
2950 bool UseTraps = useTraps();
2951
2952 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2953 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2954 Warning(IDLoc, "dividing zero by zero");
2955 if (IsMips64) {
2956 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2957 if (UseTraps) {
2958 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2959 return false;
2960 }
2961
2962 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2963 return false;
2964 }
2965 } else {
2966 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2967 return false;
2968 }
2969 }
2970
2971 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
2972 Warning(IDLoc, "division by zero");
2973 if (Signed) {
2974 if (UseTraps) {
2975 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2976 return false;
2977 }
2978
2979 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2980 return false;
2981 }
2982 }
2983
2984 // FIXME: The values for these two BranchTarget variables may be different in
2985 // micromips. These magic numbers need to be removed.
2986 unsigned BranchTargetNoTraps;
2987 unsigned BranchTarget;
2988
2989 if (UseTraps) {
2990 BranchTarget = IsMips64 ? 12 : 8;
2991 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2992 } else {
2993 BranchTarget = IsMips64 ? 20 : 16;
2994 BranchTargetNoTraps = 8;
2995 // Branch to the li instruction.
2996 emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc,
2997 Instructions);
2998 }
2999
3000 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
3001
3002 if (!UseTraps)
3003 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
3004
3005 if (!Signed) {
3006 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
3007 return false;
3008 }
3009
3010 unsigned ATReg = getATReg(IDLoc);
3011 if (!ATReg)
3012 return true;
3013
3014 emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, Instructions);
3015 if (IsMips64) {
3016 // Branch to the mflo instruction.
3017 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
3018 emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, Instructions);
3019 emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, Instructions);
3020 } else {
3021 // Branch to the mflo instruction.
3022 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
3023 emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, Instructions);
3024 }
3025
3026 if (UseTraps)
3027 emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, Instructions);
3028 else {
3029 // Branch to the mflo instruction.
3030 emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, Instructions);
3031 emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, Instructions);
3032 emitII(Mips::BREAK, 0x6, 0, IDLoc, Instructions);
3033 }
3034 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
3035 return false;
3036}
3037
Daniel Sanders6394ee52015-10-15 14:52:58 +00003038bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
3039 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00003040 if (hasMips32r6() || hasMips64r6()) {
3041 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3042 return false;
3043 }
3044
3045 warnIfNoMacro(IDLoc);
3046
3047 const MCOperand &DstRegOp = Inst.getOperand(0);
3048 assert(DstRegOp.isReg() && "expected register operand kind");
3049
3050 const MCOperand &SrcRegOp = Inst.getOperand(1);
3051 assert(SrcRegOp.isReg() && "expected register operand kind");
3052
3053 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3054 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3055
3056 unsigned DstReg = DstRegOp.getReg();
3057 unsigned SrcReg = SrcRegOp.getReg();
3058 int64_t OffsetValue = OffsetImmOp.getImm();
3059
3060 // NOTE: We always need AT for ULHU, as it is always used as the source
3061 // register for one of the LBu's.
3062 unsigned ATReg = getATReg(IDLoc);
3063 if (!ATReg)
3064 return true;
3065
3066 // When the value of offset+1 does not fit in 16 bits, we have to load the
3067 // offset in AT, (D)ADDu the original source register (if there was one), and
3068 // then use AT as the source register for the 2 generated LBu's.
3069 bool LoadedOffsetInAT = false;
3070 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3071 LoadedOffsetInAT = true;
3072
3073 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003074 true, IDLoc, Instructions))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003075 return true;
3076
3077 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3078 // because it will make our output more similar to GAS'. For example,
3079 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3080 // instead of just an "ori $1, $9, 32768".
3081 // NOTE: If there is no source register specified in the ULHU, the parser
3082 // will interpret it as $0.
3083 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3084 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3085 }
3086
3087 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3088 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3089 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3090
3091 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3092 if (isLittle()) {
3093 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3094 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3095 } else {
3096 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3097 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3098 }
3099
3100 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3101
Daniel Sanders6394ee52015-10-15 14:52:58 +00003102 emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
3103 FirstLbuOffset, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003104
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003105 emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
3106 Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003107
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003108 emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003109
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003110 emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003111
3112 return false;
3113}
3114
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003115bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
3116 SmallVectorImpl<MCInst> &Instructions) {
3117 if (hasMips32r6() || hasMips64r6()) {
3118 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3119 return false;
3120 }
3121
3122 const MCOperand &DstRegOp = Inst.getOperand(0);
3123 assert(DstRegOp.isReg() && "expected register operand kind");
3124
3125 const MCOperand &SrcRegOp = Inst.getOperand(1);
3126 assert(SrcRegOp.isReg() && "expected register operand kind");
3127
3128 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3129 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3130
3131 unsigned SrcReg = SrcRegOp.getReg();
3132 int64_t OffsetValue = OffsetImmOp.getImm();
3133 unsigned ATReg = 0;
3134
3135 // When the value of offset+3 does not fit in 16 bits, we have to load the
3136 // offset in AT, (D)ADDu the original source register (if there was one), and
3137 // then use AT as the source register for the generated LWL and LWR.
3138 bool LoadedOffsetInAT = false;
3139 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3140 ATReg = getATReg(IDLoc);
3141 if (!ATReg)
3142 return true;
3143 LoadedOffsetInAT = true;
3144
3145 warnIfNoMacro(IDLoc);
3146
3147 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003148 true, IDLoc, Instructions))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003149 return true;
3150
3151 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3152 // because it will make our output more similar to GAS'. For example,
3153 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3154 // instead of just an "ori $1, $9, 32768".
3155 // NOTE: If there is no source register specified in the ULW, the parser
3156 // will interpret it as $0.
3157 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3158 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3159 }
3160
3161 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3162 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3163 if (isLittle()) {
3164 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3165 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3166 } else {
3167 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3168 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3169 }
3170
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003171 emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
3172 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003173
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003174 emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset, IDLoc,
3175 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003176
3177 return false;
3178}
3179
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003180bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
3181 SmallVectorImpl<MCInst> &Instructions) {
3182
3183 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3184 assert (Inst.getOperand(0).isReg() &&
3185 Inst.getOperand(1).isReg() &&
3186 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3187
3188 unsigned ATReg = Mips::NoRegister;
3189 unsigned FinalDstReg = Mips::NoRegister;
3190 unsigned DstReg = Inst.getOperand(0).getReg();
3191 unsigned SrcReg = Inst.getOperand(1).getReg();
3192 int64_t ImmValue = Inst.getOperand(2).getImm();
3193
3194 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3195
3196 unsigned FinalOpcode = Inst.getOpcode();
3197
3198 if (DstReg == SrcReg) {
3199 ATReg = getATReg(Inst.getLoc());
3200 if (!ATReg)
3201 return true;
3202 FinalDstReg = DstReg;
3203 DstReg = ATReg;
3204 }
3205
3206 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Instructions)) {
3207 switch (FinalOpcode) {
3208 default:
3209 llvm_unreachable("unimplemented expansion");
3210 case (Mips::ADDi):
3211 FinalOpcode = Mips::ADD;
3212 break;
3213 case (Mips::ADDiu):
3214 FinalOpcode = Mips::ADDu;
3215 break;
3216 case (Mips::ANDi):
3217 FinalOpcode = Mips::AND;
3218 break;
3219 case (Mips::NORImm):
3220 FinalOpcode = Mips::NOR;
3221 break;
3222 case (Mips::ORi):
3223 FinalOpcode = Mips::OR;
3224 break;
3225 case (Mips::SLTi):
3226 FinalOpcode = Mips::SLT;
3227 break;
3228 case (Mips::SLTiu):
3229 FinalOpcode = Mips::SLTu;
3230 break;
3231 case (Mips::XORi):
3232 FinalOpcode = Mips::XOR;
3233 break;
3234 }
3235
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003236 if (FinalDstReg == Mips::NoRegister)
3237 emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, Instructions);
3238 else
3239 emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc,
3240 Instructions);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003241 return false;
3242 }
3243 return true;
3244}
3245
Toma Tabacu234482a2015-03-16 12:03:39 +00003246void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
3247 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003248 if (hasShortDelaySlot)
3249 emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, Instructions);
3250 else
3251 emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, Instructions);
Toma Tabacu234482a2015-03-16 12:03:39 +00003252}
3253
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003254void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +00003255 unsigned TrgReg, bool Is64Bit,
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003256 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders03f9c012015-07-14 12:24:22 +00003257 emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
3258 Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003259}
3260
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003261void MipsAsmParser::createCpRestoreMemOp(
3262 bool IsLoad, int StackOffset, SMLoc IDLoc,
3263 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003264 // If the offset can not fit into 16 bits, we need to expand.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003265 if (!isInt<16>(StackOffset)) {
3266 MCInst MemInst;
3267 MemInst.setOpcode(IsLoad ? Mips::LW : Mips::SW);
3268 MemInst.addOperand(MCOperand::createReg(Mips::GP));
3269 MemInst.addOperand(MCOperand::createReg(Mips::SP));
3270 MemInst.addOperand(MCOperand::createImm(StackOffset));
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003271 expandMemInst(MemInst, IDLoc, Instructions, IsLoad, true /*HasImmOpnd*/);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003272 return;
3273 }
3274
3275 emitRRI(IsLoad ? Mips::LW : Mips::SW, Mips::GP, Mips::SP, StackOffset, IDLoc,
3276 Instructions);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003277}
3278
Matheus Almeida595fcab2014-06-11 15:05:56 +00003279unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3280 // As described by the Mips32r2 spec, the registers Rd and Rs for
3281 // jalr.hb must be different.
3282 unsigned Opcode = Inst.getOpcode();
3283
3284 if (Opcode == Mips::JALR_HB &&
3285 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3286 return Match_RequiresDifferentSrcAndDst;
3287
3288 return Match_Success;
3289}
3290
Daniel Sanders52da7af2015-11-06 12:11:03 +00003291static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
3292 uint64_t ErrorInfo) {
3293 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
3294 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
3295 if (ErrorLoc == SMLoc())
3296 return Loc;
3297 return ErrorLoc;
3298 }
3299 return Loc;
3300}
3301
David Blaikie960ea3f2014-06-08 16:18:35 +00003302bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3303 OperandVector &Operands,
3304 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003305 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003306 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003307
Jack Carterb4dbc172012-09-05 23:34:03 +00003308 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00003309 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00003310 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003311 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003312
3313 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003314 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003315 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00003316 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00003317 for (unsigned i = 0; i < Instructions.size(); i++)
Akira Hatanakabd9fc282015-11-14 05:20:05 +00003318 Out.EmitInstruction(Instructions[i], getSTI());
Jack Carterb4dbc172012-09-05 23:34:03 +00003319 return false;
3320 }
3321 case Match_MissingFeature:
3322 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3323 return true;
3324 case Match_InvalidOperand: {
3325 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003326 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003327 if (ErrorInfo >= Operands.size())
3328 return Error(IDLoc, "too few operands for instruction");
3329
Daniel Sanders52da7af2015-11-06 12:11:03 +00003330 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003331 if (ErrorLoc == SMLoc())
3332 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003333 }
3334
3335 return Error(ErrorLoc, "invalid operand for instruction");
3336 }
3337 case Match_MnemonicFail:
3338 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003339 case Match_RequiresDifferentSrcAndDst:
3340 return Error(IDLoc, "source and destination must be different");
Daniel Sanders52da7af2015-11-06 12:11:03 +00003341 case Match_Immz:
3342 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003343 case Match_UImm1_0:
3344 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3345 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00003346 case Match_UImm2_0:
3347 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3348 "expected 2-bit unsigned immediate");
3349 case Match_UImm2_1:
3350 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3351 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00003352 case Match_UImm3_0:
3353 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3354 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003355 case Match_UImm4_0:
3356 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3357 "expected 4-bit unsigned immediate");
Jack Carterb4dbc172012-09-05 23:34:03 +00003358 }
Craig Topper589ceee2015-01-03 08:16:34 +00003359
3360 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003361}
3362
Toma Tabacud9d344b2015-04-27 14:05:04 +00003363void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3364 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3365 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3366 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003367}
3368
Toma Tabacu81496c12015-05-20 08:54:45 +00003369void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3370 if (!AssemblerOptions.back()->isMacro())
3371 Warning(Loc, "macro instruction expanded into multiple instructions");
3372}
3373
Daniel Sandersef638fe2014-10-03 15:37:37 +00003374void
3375MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3376 SMRange Range, bool ShowColors) {
3377 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003378 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003379 ShowColors);
3380}
3381
Jack Carter1ac53222013-02-20 23:11:17 +00003382int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003383 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003384
Vladimir Medic4c299852013-11-06 11:27:05 +00003385 CC = StringSwitch<unsigned>(Name)
3386 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003387 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003388 .Case("a0", 4)
3389 .Case("a1", 5)
3390 .Case("a2", 6)
3391 .Case("a3", 7)
3392 .Case("v0", 2)
3393 .Case("v1", 3)
3394 .Case("s0", 16)
3395 .Case("s1", 17)
3396 .Case("s2", 18)
3397 .Case("s3", 19)
3398 .Case("s4", 20)
3399 .Case("s5", 21)
3400 .Case("s6", 22)
3401 .Case("s7", 23)
3402 .Case("k0", 26)
3403 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003404 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003405 .Case("sp", 29)
3406 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003407 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003408 .Case("ra", 31)
3409 .Case("t0", 8)
3410 .Case("t1", 9)
3411 .Case("t2", 10)
3412 .Case("t3", 11)
3413 .Case("t4", 12)
3414 .Case("t5", 13)
3415 .Case("t6", 14)
3416 .Case("t7", 15)
3417 .Case("t8", 24)
3418 .Case("t9", 25)
3419 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003420
Toma Tabacufda445c2014-09-15 15:33:01 +00003421 if (!(isABI_N32() || isABI_N64()))
3422 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003423
Daniel Sandersef638fe2014-10-03 15:37:37 +00003424 if (12 <= CC && CC <= 15) {
3425 // Name is one of t4-t7
3426 AsmToken RegTok = getLexer().peekTok();
3427 SMRange RegRange = RegTok.getLocRange();
3428
3429 StringRef FixedName = StringSwitch<StringRef>(Name)
3430 .Case("t4", "t0")
3431 .Case("t5", "t1")
3432 .Case("t6", "t2")
3433 .Case("t7", "t3")
3434 .Default("");
3435 assert(FixedName != "" && "Register name is not one of t4-t7.");
3436
3437 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3438 "Did you mean $" + FixedName + "?", RegRange);
3439 }
3440
Toma Tabacufda445c2014-09-15 15:33:01 +00003441 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3442 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3443 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3444 if (8 <= CC && CC <= 11)
3445 CC += 4;
3446
3447 if (CC == -1)
3448 CC = StringSwitch<unsigned>(Name)
3449 .Case("a4", 8)
3450 .Case("a5", 9)
3451 .Case("a6", 10)
3452 .Case("a7", 11)
3453 .Case("kt0", 26)
3454 .Case("kt1", 27)
3455 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003456
3457 return CC;
3458}
Jack Carterd0bd6422013-04-18 00:41:53 +00003459
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003460int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3461 int CC;
3462
3463 CC = StringSwitch<unsigned>(Name)
3464 .Case("hwr_cpunum", 0)
3465 .Case("hwr_synci_step", 1)
3466 .Case("hwr_cc", 2)
3467 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003468 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003469 .Default(-1);
3470
3471 return CC;
3472}
3473
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003474int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003475
Jack Cartera63b16a2012-09-07 00:23:42 +00003476 if (Name[0] == 'f') {
3477 StringRef NumString = Name.substr(1);
3478 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003479 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003480 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003481 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003482 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003483 return IntVal;
3484 }
3485 return -1;
3486}
Jack Cartera63b16a2012-09-07 00:23:42 +00003487
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003488int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3489
3490 if (Name.startswith("fcc")) {
3491 StringRef NumString = Name.substr(3);
3492 unsigned IntVal;
3493 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003494 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003495 if (IntVal > 7) // There are only 8 fcc registers.
3496 return -1;
3497 return IntVal;
3498 }
3499 return -1;
3500}
3501
3502int MipsAsmParser::matchACRegisterName(StringRef Name) {
3503
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003504 if (Name.startswith("ac")) {
3505 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003506 unsigned IntVal;
3507 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003508 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003509 if (IntVal > 3) // There are only 3 acc registers.
3510 return -1;
3511 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003512 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003513 return -1;
3514}
Jack Carterd0bd6422013-04-18 00:41:53 +00003515
Jack Carter5dc8ac92013-09-25 23:50:44 +00003516int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3517 unsigned IntVal;
3518
3519 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3520 return -1;
3521
3522 if (IntVal > 31)
3523 return -1;
3524
3525 return IntVal;
3526}
3527
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003528int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3529 int CC;
3530
3531 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003532 .Case("msair", 0)
3533 .Case("msacsr", 1)
3534 .Case("msaaccess", 2)
3535 .Case("msasave", 3)
3536 .Case("msamodify", 4)
3537 .Case("msarequest", 5)
3538 .Case("msamap", 6)
3539 .Case("msaunmap", 7)
3540 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003541
3542 return CC;
3543}
3544
Toma Tabacu89a712b2015-04-15 10:48:56 +00003545unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00003546 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00003547 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00003548 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00003549 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00003550 return 0;
3551 }
3552 unsigned AT = getReg(
3553 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00003554 return AT;
3555}
Jack Carter0b744b32012-10-04 02:29:46 +00003556
Jack Carterd0bd6422013-04-18 00:41:53 +00003557unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00003558 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00003559}
3560
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003561unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003562 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00003563 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003564}
3565
Jack Carter873c7242013-01-12 01:03:14 +00003566int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003567 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00003568 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00003569 return -1;
3570
Jack Carter873c7242013-01-12 01:03:14 +00003571 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00003572}
3573
Toma Tabacu13964452014-09-04 13:23:44 +00003574bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003575 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003576 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003577
Jack Carter30a59822012-10-04 04:03:53 +00003578 // Check if the current operand has a custom associated parser, if so, try to
3579 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00003580 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3581 if (ResTy == MatchOperand_Success)
3582 return false;
3583 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3584 // there was a match, but an error occurred, in which case, just return that
3585 // the operand parsing failed.
3586 if (ResTy == MatchOperand_ParseFail)
3587 return true;
3588
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003589 DEBUG(dbgs() << ".. Generic Parser\n");
3590
Jack Carterb4dbc172012-09-05 23:34:03 +00003591 switch (getLexer().getKind()) {
3592 default:
3593 Error(Parser.getTok().getLoc(), "unexpected token in operand");
3594 return true;
3595 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003596 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00003597 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00003598
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003599 // Almost all registers have been parsed by custom parsers. There is only
3600 // one exception to this. $zero (and it's alias $0) will reach this point
3601 // for div, divu, and similar instructions because it is not an operand
3602 // to the instruction definition but an explicit register. Special case
3603 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00003604 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00003605 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003606
Jack Carterd0bd6422013-04-18 00:41:53 +00003607 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00003608 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003609 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00003610 return true;
3611
Jack Carter873c7242013-01-12 01:03:14 +00003612 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00003613 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00003614 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00003615 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003616 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00003617
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003618 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003619 return false;
3620 }
Vladimir Medic4c299852013-11-06 11:27:05 +00003621 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00003622 case AsmToken::LParen:
3623 case AsmToken::Minus:
3624 case AsmToken::Plus:
3625 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003626 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00003627 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003628 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003629 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003630 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00003631 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00003632 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003633 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003634 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003635 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00003636 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00003637 return true;
3638
Jack Carter873c7242013-01-12 01:03:14 +00003639 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3640
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003641 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00003642 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003643 } // case AsmToken::Percent
3644 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00003645 return true;
3646}
3647
Vladimir Medic4c299852013-11-06 11:27:05 +00003648const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00003649 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003650 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00003651 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003652 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00003653 // It's a constant, evaluate reloc value.
3654 int16_t Val;
3655 switch (getVariantKind(RelocStr)) {
3656 case MCSymbolRefExpr::VK_Mips_ABS_LO:
3657 // Get the 1st 16-bits.
3658 Val = MCE->getValue() & 0xffff;
3659 break;
3660 case MCSymbolRefExpr::VK_Mips_ABS_HI:
3661 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
3662 // 16 bits being negative.
3663 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
3664 break;
3665 case MCSymbolRefExpr::VK_Mips_HIGHER:
3666 // Get the 3rd 16-bits.
3667 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
3668 break;
3669 case MCSymbolRefExpr::VK_Mips_HIGHEST:
3670 // Get the 4th 16-bits.
3671 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
3672 break;
3673 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00003674 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00003675 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00003676 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003677 }
3678
Jack Carterb5cf5902013-04-17 00:18:04 +00003679 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003680 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00003681 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00003682 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003683 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003684 return Res;
3685 }
3686
3687 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00003688 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
3689
Sasa Stankovic06c47802014-04-03 10:37:45 +00003690 // Try to create target expression.
3691 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00003692 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003693
Jack Carterd0bd6422013-04-18 00:41:53 +00003694 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
3695 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003696 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003697 return Res;
3698 }
3699
3700 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003701 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003702 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00003703 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00003704 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003705 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003706 return Expr;
3707}
3708
3709bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
3710
3711 switch (Expr->getKind()) {
3712 case MCExpr::Constant:
3713 return true;
3714 case MCExpr::SymbolRef:
3715 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
3716 case MCExpr::Binary:
3717 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
3718 if (!isEvaluated(BE->getLHS()))
3719 return false;
3720 return isEvaluated(BE->getRHS());
3721 }
3722 case MCExpr::Unary:
3723 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003724 case MCExpr::Target:
3725 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003726 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003727 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00003728}
Jack Carterd0bd6422013-04-18 00:41:53 +00003729
Jack Carterb5cf5902013-04-17 00:18:04 +00003730bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003731 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003732 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00003733 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00003734 if (Tok.isNot(AsmToken::Identifier))
3735 return true;
3736
Yaron Keren075759a2015-03-30 15:42:36 +00003737 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00003738
Jack Carterd0bd6422013-04-18 00:41:53 +00003739 Parser.Lex(); // Eat the identifier.
3740 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003741 const MCExpr *IdVal;
3742 SMLoc EndLoc;
3743
3744 if (getLexer().getKind() == AsmToken::LParen) {
3745 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003746 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003747 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003748 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003749 const AsmToken &nextTok = Parser.getTok();
3750 if (nextTok.isNot(AsmToken::Identifier))
3751 return true;
3752 Str += "(%";
3753 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00003754 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00003755 if (getLexer().getKind() != AsmToken::LParen)
3756 return true;
3757 } else
3758 break;
3759 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003760 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00003761 return true;
3762
3763 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00003764 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003765
3766 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00003767 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003768
Jack Carterd0bd6422013-04-18 00:41:53 +00003769 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00003770 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003771}
3772
Jack Carterb4dbc172012-09-05 23:34:03 +00003773bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
3774 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003775 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00003776 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003777 if (ResTy == MatchOperand_Success) {
3778 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00003779 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003780 StartLoc = Operand.getStartLoc();
3781 EndLoc = Operand.getEndLoc();
3782
3783 // AFAIK, we only support numeric registers and named GPR's in CFI
3784 // directives.
3785 // Don't worry about eating tokens before failing. Using an unrecognised
3786 // register is a parse error.
3787 if (Operand.isGPRAsmReg()) {
3788 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003789 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003790 }
3791
3792 return (RegNo == (unsigned)-1);
3793 }
3794
3795 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00003796 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00003797}
3798
Jack Carterb5cf5902013-04-17 00:18:04 +00003799bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003800 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00003801 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003802 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003803 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00003804
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003805 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003806 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003807 ++NumOfLParen;
3808 }
Jack Carter873c7242013-01-12 01:03:14 +00003809
Jack Carterd0bd6422013-04-18 00:41:53 +00003810 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003811 default:
3812 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00003813 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00003814 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00003815 case AsmToken::Integer:
3816 case AsmToken::Minus:
3817 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00003818 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003819 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00003820 else
3821 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00003822 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00003823 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003824 break;
Jack Carter873c7242013-01-12 01:03:14 +00003825 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00003826 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003827 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003828 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003829}
3830
David Blaikie960ea3f2014-06-08 16:18:35 +00003831MipsAsmParser::OperandMatchResultTy
3832MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003833 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003834 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00003835 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00003836 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003837 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003838 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00003839 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00003840 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00003841
Jack Carterb5cf5902013-04-17 00:18:04 +00003842 if (getLexer().getKind() == AsmToken::LParen) {
3843 Parser.Lex();
3844 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003845 }
3846
Jack Carterb5cf5902013-04-17 00:18:04 +00003847 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003848 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00003849 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003850
Jack Carterd0bd6422013-04-18 00:41:53 +00003851 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003852 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003853 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003854 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003855 SMLoc E =
3856 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003857 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003858 return MatchOperand_Success;
3859 }
3860 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003861 SMLoc E =
3862 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00003863
Jack Carterd0bd6422013-04-18 00:41:53 +00003864 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003865 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00003866 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003867 S, E, *this);
3868 Operands.push_back(
3869 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003870 return MatchOperand_Success;
3871 }
3872 Error(Parser.getTok().getLoc(), "'(' expected");
3873 return MatchOperand_ParseFail;
3874 }
3875
Jack Carterd0bd6422013-04-18 00:41:53 +00003876 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003877 }
3878
Toma Tabacu13964452014-09-04 13:23:44 +00003879 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003880 if (Res != MatchOperand_Success)
3881 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003882
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003883 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003884 Error(Parser.getTok().getLoc(), "')' expected");
3885 return MatchOperand_ParseFail;
3886 }
3887
Jack Carter873c7242013-01-12 01:03:14 +00003888 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3889
Jack Carterd0bd6422013-04-18 00:41:53 +00003890 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003891
Craig Topper062a2ba2014-04-25 05:30:21 +00003892 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003893 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003894
Jack Carterd0bd6422013-04-18 00:41:53 +00003895 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00003896 std::unique_ptr<MipsOperand> op(
3897 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00003898 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003899 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003900 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00003901 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003902 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
3903 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003904 if (IdVal->evaluateAsAbsolute(Imm))
3905 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003906 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003907 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00003908 getContext());
3909 }
3910
David Blaikie960ea3f2014-06-08 16:18:35 +00003911 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003912 return MatchOperand_Success;
3913}
3914
David Blaikie960ea3f2014-06-08 16:18:35 +00003915bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003916 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00003917 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00003918 if (Sym) {
3919 SMLoc S = Parser.getTok().getLoc();
3920 const MCExpr *Expr;
3921 if (Sym->isVariable())
3922 Expr = Sym->getVariableValue();
3923 else
3924 return false;
3925 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003926 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00003927 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00003928 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003929 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003930 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00003931 if (ResTy == MatchOperand_Success) {
3932 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00003933 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00003934 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003935 llvm_unreachable("Should never ParseFail");
3936 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00003937 }
3938 } else if (Expr->getKind() == MCExpr::Constant) {
3939 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00003940 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00003941 Operands.push_back(
3942 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00003943 return true;
3944 }
3945 }
3946 return false;
3947}
Jack Carterd0bd6422013-04-18 00:41:53 +00003948
Jack Carter873c7242013-01-12 01:03:14 +00003949MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003950MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00003951 StringRef Identifier,
3952 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003953 int Index = matchCPURegisterName(Identifier);
3954 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003955 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003956 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3957 return MatchOperand_Success;
3958 }
3959
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003960 Index = matchHWRegsRegisterName(Identifier);
3961 if (Index != -1) {
3962 Operands.push_back(MipsOperand::createHWRegsReg(
3963 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3964 return MatchOperand_Success;
3965 }
3966
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003967 Index = matchFPURegisterName(Identifier);
3968 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003969 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003970 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3971 return MatchOperand_Success;
3972 }
3973
3974 Index = matchFCCRegisterName(Identifier);
3975 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003976 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003977 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3978 return MatchOperand_Success;
3979 }
3980
3981 Index = matchACRegisterName(Identifier);
3982 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003983 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003984 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3985 return MatchOperand_Success;
3986 }
3987
3988 Index = matchMSA128RegisterName(Identifier);
3989 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003990 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003991 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3992 return MatchOperand_Success;
3993 }
3994
3995 Index = matchMSA128CtrlRegisterName(Identifier);
3996 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003997 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003998 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3999 return MatchOperand_Success;
4000 }
4001
4002 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00004003}
4004
4005MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004006MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004007 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00004008 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004009
4010 if (Token.is(AsmToken::Identifier)) {
4011 DEBUG(dbgs() << ".. identifier\n");
4012 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00004013 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004014 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00004015 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004016 } else if (Token.is(AsmToken::Integer)) {
4017 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004018 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004019 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
4020 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004021 return MatchOperand_Success;
4022 }
4023
4024 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
4025
4026 return MatchOperand_NoMatch;
4027}
4028
David Blaikie960ea3f2014-06-08 16:18:35 +00004029MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004030MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004031 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004032 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004033
4034 auto Token = Parser.getTok();
4035
4036 SMLoc S = Token.getLoc();
4037
4038 if (Token.isNot(AsmToken::Dollar)) {
4039 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4040 if (Token.is(AsmToken::Identifier)) {
4041 if (searchSymbolAlias(Operands))
4042 return MatchOperand_Success;
4043 }
4044 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4045 return MatchOperand_NoMatch;
4046 }
4047 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004048
Toma Tabacu13964452014-09-04 13:23:44 +00004049 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004050 if (ResTy == MatchOperand_Success) {
4051 Parser.Lex(); // $
4052 Parser.Lex(); // identifier
4053 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004054 return ResTy;
4055}
4056
4057MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004058MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004059 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004060 switch (getLexer().getKind()) {
4061 default:
4062 return MatchOperand_NoMatch;
4063 case AsmToken::LParen:
4064 case AsmToken::Minus:
4065 case AsmToken::Plus:
4066 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004067 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004068 case AsmToken::String:
4069 break;
4070 }
4071
4072 const MCExpr *IdVal;
4073 SMLoc S = Parser.getTok().getLoc();
4074 if (getParser().parseExpression(IdVal))
4075 return MatchOperand_ParseFail;
4076
4077 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4078 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4079 return MatchOperand_Success;
4080}
4081
David Blaikie960ea3f2014-06-08 16:18:35 +00004082MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004083MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004084 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004085 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004086
4087 SMLoc S = getLexer().getLoc();
4088
4089 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00004090 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004091 if (ResTy != MatchOperand_NoMatch)
4092 return ResTy;
4093
Daniel Sanders315386c2014-04-01 10:40:14 +00004094 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00004095 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00004096 if (ResTy != MatchOperand_NoMatch)
4097 return ResTy;
4098
Daniel Sandersffd84362014-04-01 10:41:48 +00004099 const MCExpr *Expr = nullptr;
4100 if (Parser.parseExpression(Expr)) {
4101 // We have no way of knowing if a symbol was consumed so we must ParseFail
4102 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004103 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004104 Operands.push_back(
4105 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004106 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004107}
4108
Vladimir Medic2b953d02013-10-01 09:48:56 +00004109MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004110MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004111 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004112 const MCExpr *IdVal;
4113 // If the first token is '$' we may have register operand.
4114 if (Parser.getTok().is(AsmToken::Dollar))
4115 return MatchOperand_NoMatch;
4116 SMLoc S = Parser.getTok().getLoc();
4117 if (getParser().parseExpression(IdVal))
4118 return MatchOperand_ParseFail;
4119 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004120 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004121 int64_t Val = MCE->getValue();
4122 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4123 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004124 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004125 return MatchOperand_Success;
4126}
4127
Matheus Almeida779c5932013-11-18 12:32:49 +00004128MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004129MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004130 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00004131 switch (getLexer().getKind()) {
4132 default:
4133 return MatchOperand_NoMatch;
4134 case AsmToken::LParen:
4135 case AsmToken::Plus:
4136 case AsmToken::Minus:
4137 case AsmToken::Integer:
4138 break;
4139 }
4140
4141 const MCExpr *Expr;
4142 SMLoc S = Parser.getTok().getLoc();
4143
4144 if (getParser().parseExpression(Expr))
4145 return MatchOperand_ParseFail;
4146
4147 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004148 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00004149 Error(S, "expected immediate value");
4150 return MatchOperand_ParseFail;
4151 }
4152
4153 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
4154 // and because the CPU always adds one to the immediate field, the allowed
4155 // range becomes 1..4. We'll only check the range here and will deal
4156 // with the addition/subtraction when actually decoding/encoding
4157 // the instruction.
4158 if (Val < 1 || Val > 4) {
4159 Error(S, "immediate not in range (1..4)");
4160 return MatchOperand_ParseFail;
4161 }
4162
Jack Carter3b2c96e2014-01-22 23:31:38 +00004163 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004164 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00004165 return MatchOperand_Success;
4166}
4167
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004168MipsAsmParser::OperandMatchResultTy
4169MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4170 MCAsmParser &Parser = getParser();
4171 SmallVector<unsigned, 10> Regs;
4172 unsigned RegNo;
4173 unsigned PrevReg = Mips::NoRegister;
4174 bool RegRange = false;
4175 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4176
4177 if (Parser.getTok().isNot(AsmToken::Dollar))
4178 return MatchOperand_ParseFail;
4179
4180 SMLoc S = Parser.getTok().getLoc();
4181 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4182 SMLoc E = getLexer().getLoc();
4183 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4184 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4185 if (RegRange) {
4186 // Remove last register operand because registers from register range
4187 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004188 if ((isGP64bit() && RegNo == Mips::RA_64) ||
4189 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004190 Regs.push_back(RegNo);
4191 } else {
4192 unsigned TmpReg = PrevReg + 1;
4193 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004194 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
4195 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
4196 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004197 Error(E, "invalid register operand");
4198 return MatchOperand_ParseFail;
4199 }
4200
4201 PrevReg = TmpReg;
4202 Regs.push_back(TmpReg++);
4203 }
4204 }
4205
4206 RegRange = false;
4207 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004208 if ((PrevReg == Mips::NoRegister) &&
4209 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
4210 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004211 Error(E, "$16 or $31 expected");
4212 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004213 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
4214 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
4215 !isGP64bit()) ||
4216 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
4217 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
4218 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004219 Error(E, "invalid register operand");
4220 return MatchOperand_ParseFail;
4221 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004222 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
4223 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
4224 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004225 Error(E, "consecutive register numbers expected");
4226 return MatchOperand_ParseFail;
4227 }
4228
4229 Regs.push_back(RegNo);
4230 }
4231
4232 if (Parser.getTok().is(AsmToken::Minus))
4233 RegRange = true;
4234
4235 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4236 !Parser.getTok().isNot(AsmToken::Comma)) {
4237 Error(E, "',' or '-' expected");
4238 return MatchOperand_ParseFail;
4239 }
4240
4241 Lex(); // Consume comma or minus
4242 if (Parser.getTok().isNot(AsmToken::Dollar))
4243 break;
4244
4245 PrevReg = RegNo;
4246 }
4247
4248 SMLoc E = Parser.getTok().getLoc();
4249 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4250 parseMemOperand(Operands);
4251 return MatchOperand_Success;
4252}
4253
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004254MipsAsmParser::OperandMatchResultTy
4255MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4256 MCAsmParser &Parser = getParser();
4257
4258 SMLoc S = Parser.getTok().getLoc();
4259 if (parseAnyRegister(Operands) != MatchOperand_Success)
4260 return MatchOperand_ParseFail;
4261
4262 SMLoc E = Parser.getTok().getLoc();
4263 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
4264 unsigned Reg = Op.getGPR32Reg();
4265 Operands.pop_back();
4266 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
4267 return MatchOperand_Success;
4268}
4269
Zoran Jovanovic41688672015-02-10 16:36:20 +00004270MipsAsmParser::OperandMatchResultTy
4271MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4272 MCAsmParser &Parser = getParser();
4273 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4274 SmallVector<unsigned, 10> Regs;
4275
4276 if (Parser.getTok().isNot(AsmToken::Dollar))
4277 return MatchOperand_ParseFail;
4278
4279 SMLoc S = Parser.getTok().getLoc();
4280
4281 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4282 return MatchOperand_ParseFail;
4283
4284 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4285 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4286 Regs.push_back(RegNo);
4287
4288 SMLoc E = Parser.getTok().getLoc();
4289 if (Parser.getTok().isNot(AsmToken::Comma)) {
4290 Error(E, "',' expected");
4291 return MatchOperand_ParseFail;
4292 }
4293
4294 // Remove comma.
4295 Parser.Lex();
4296
4297 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4298 return MatchOperand_ParseFail;
4299
4300 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4301 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4302 Regs.push_back(RegNo);
4303
4304 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4305
4306 return MatchOperand_Success;
4307}
4308
Jack Carterdc1e35d2012-09-06 20:00:02 +00004309MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
4310
Vladimir Medic4c299852013-11-06 11:27:05 +00004311 MCSymbolRefExpr::VariantKind VK =
4312 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
4313 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
4314 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
4315 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
4316 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
4317 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
4318 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
4319 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
4320 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
4321 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
4322 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
4323 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
4324 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
4325 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
4326 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
4327 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
4328 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
4329 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00004330 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
4331 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
4332 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
4333 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
4334 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
4335 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00004336 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
4337 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00004338 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004339
Matheus Almeida2852af82014-04-22 10:15:54 +00004340 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00004341
Jack Carterdc1e35d2012-09-06 20:00:02 +00004342 return VK;
4343}
Jack Cartera63b16a2012-09-07 00:23:42 +00004344
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004345/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4346/// either this.
4347/// ::= '(', register, ')'
4348/// handle it before we iterate so we don't get tripped up by the lack of
4349/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004350bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004351 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004352 if (getLexer().is(AsmToken::LParen)) {
4353 Operands.push_back(
4354 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4355 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004356 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004357 SMLoc Loc = getLexer().getLoc();
4358 Parser.eatToEndOfStatement();
4359 return Error(Loc, "unexpected token in argument list");
4360 }
4361 if (Parser.getTok().isNot(AsmToken::RParen)) {
4362 SMLoc Loc = getLexer().getLoc();
4363 Parser.eatToEndOfStatement();
4364 return Error(Loc, "unexpected token, expected ')'");
4365 }
4366 Operands.push_back(
4367 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4368 Parser.Lex();
4369 }
4370 return false;
4371}
4372
4373/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4374/// either one of these.
4375/// ::= '[', register, ']'
4376/// ::= '[', integer, ']'
4377/// handle it before we iterate so we don't get tripped up by the lack of
4378/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004379bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004380 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004381 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004382 if (getLexer().is(AsmToken::LBrac)) {
4383 Operands.push_back(
4384 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4385 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004386 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004387 SMLoc Loc = getLexer().getLoc();
4388 Parser.eatToEndOfStatement();
4389 return Error(Loc, "unexpected token in argument list");
4390 }
4391 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4392 SMLoc Loc = getLexer().getLoc();
4393 Parser.eatToEndOfStatement();
4394 return Error(Loc, "unexpected token, expected ']'");
4395 }
4396 Operands.push_back(
4397 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4398 Parser.Lex();
4399 }
4400 return false;
4401}
4402
David Blaikie960ea3f2014-06-08 16:18:35 +00004403bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4404 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004405 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004406 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004407
4408 // We have reached first instruction, module directive are now forbidden.
4409 getTargetStreamer().forbidModuleDirective();
4410
Vladimir Medic74593e62013-07-17 15:00:42 +00004411 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004412 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004413 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004414 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004415 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004416 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004417 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004418
4419 // Read the remaining operands.
4420 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4421 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004422 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004423 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004424 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004425 return Error(Loc, "unexpected token in argument list");
4426 }
Toma Tabacu13964452014-09-04 13:23:44 +00004427 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004428 return true;
4429 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004430
Jack Carterd0bd6422013-04-18 00:41:53 +00004431 while (getLexer().is(AsmToken::Comma)) {
4432 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004433 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004434 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004435 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004436 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004437 return Error(Loc, "unexpected token in argument list");
4438 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004439 // Parse bracket and parenthesis suffixes before we iterate
4440 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004441 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004442 return true;
4443 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004444 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004445 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004446 }
4447 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004448 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4449 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004450 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004451 return Error(Loc, "unexpected token in argument list");
4452 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004453 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004454 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004455}
4456
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004457bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004458 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004459 SMLoc Loc = getLexer().getLoc();
4460 Parser.eatToEndOfStatement();
4461 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004462}
4463
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004464bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004465 return Error(Loc, ErrorMsg);
4466}
4467
Jack Carter0b744b32012-10-04 02:29:46 +00004468bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004469 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004470 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004471
4472 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004473 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004474
4475 Parser.Lex(); // Eat "noat".
4476
Jack Carterd0bd6422013-04-18 00:41:53 +00004477 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004478 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004479 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004480 return false;
4481 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004482
4483 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004484 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004485 return false;
4486}
Jack Carterd0bd6422013-04-18 00:41:53 +00004487
Jack Carter0b744b32012-10-04 02:29:46 +00004488bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004489 // Line can be: ".set at", which sets $at to $1
4490 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004491 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004492 Parser.Lex(); // Eat "at".
4493
Jack Carter0b744b32012-10-04 02:29:46 +00004494 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004495 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004496 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004497
4498 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004499 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004500 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004501 }
4502
4503 if (getLexer().isNot(AsmToken::Equal)) {
4504 reportParseError("unexpected token, expected equals sign");
4505 return false;
4506 }
4507 Parser.Lex(); // Eat "=".
4508
4509 if (getLexer().isNot(AsmToken::Dollar)) {
4510 if (getLexer().is(AsmToken::EndOfStatement)) {
4511 reportParseError("no register specified");
4512 return false;
4513 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004514 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004515 return false;
4516 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004517 }
4518 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004519
Toma Tabacu16a74492015-02-13 10:30:57 +00004520 // Find out what "reg" is.
4521 unsigned AtRegNo;
4522 const AsmToken &Reg = Parser.getTok();
4523 if (Reg.is(AsmToken::Identifier)) {
4524 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4525 } else if (Reg.is(AsmToken::Integer)) {
4526 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004527 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004528 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004529 return false;
4530 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004531
4532 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004533 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004534 reportParseError("invalid register");
4535 return false;
4536 }
4537 Parser.Lex(); // Eat "reg".
4538
4539 // If this is not the end of the statement, report an error.
4540 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4541 reportParseError("unexpected token, expected end of statement");
4542 return false;
4543 }
4544
4545 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4546
4547 Parser.Lex(); // Consume the EndOfStatement.
4548 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004549}
4550
4551bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004552 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004553 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004554 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004555 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004556 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004557 return false;
4558 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004559 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004560 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004561 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004562 return false;
4563}
4564
4565bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004566 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004567 Parser.Lex();
4568 // If this is not the end of the statement, report an error.
4569 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004570 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004571 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00004572 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004573 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00004574 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004575 Parser.Lex(); // Consume the EndOfStatement.
4576 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004577}
4578
4579bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004580 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004581 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004582 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004583 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004584 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004585 return false;
4586 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004587 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004588 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004589 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004590 return false;
4591}
4592
4593bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004594 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004595 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004596 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004597 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004598 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004599 return false;
4600 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004601 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00004602 reportParseError("`noreorder' must be set before `nomacro'");
4603 return false;
4604 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004605 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004606 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004607 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004608 return false;
4609}
Jack Carterd76b2372013-03-21 21:44:16 +00004610
Daniel Sanders44934432014-08-07 12:03:36 +00004611bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004612 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004613 Parser.Lex();
4614
4615 // If this is not the end of the statement, report an error.
4616 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004617 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004618
4619 setFeatureBits(Mips::FeatureMSA, "msa");
4620 getTargetStreamer().emitDirectiveSetMsa();
4621 return false;
4622}
4623
4624bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004625 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004626 Parser.Lex();
4627
4628 // If this is not the end of the statement, report an error.
4629 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004630 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004631
4632 clearFeatureBits(Mips::FeatureMSA, "msa");
4633 getTargetStreamer().emitDirectiveSetNoMsa();
4634 return false;
4635}
4636
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004637bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004638 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004639 Parser.Lex(); // Eat "nodsp".
4640
4641 // If this is not the end of the statement, report an error.
4642 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4643 reportParseError("unexpected token, expected end of statement");
4644 return false;
4645 }
4646
4647 clearFeatureBits(Mips::FeatureDSP, "dsp");
4648 getTargetStreamer().emitDirectiveSetNoDsp();
4649 return false;
4650}
4651
Toma Tabacucc2502d2014-11-04 17:18:07 +00004652bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004653 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004654 Parser.Lex(); // Eat "mips16".
4655
Jack Carter39536722014-01-22 23:08:42 +00004656 // If this is not the end of the statement, report an error.
4657 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004658 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00004659 return false;
4660 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00004661
4662 setFeatureBits(Mips::FeatureMips16, "mips16");
4663 getTargetStreamer().emitDirectiveSetMips16();
4664 Parser.Lex(); // Consume the EndOfStatement.
4665 return false;
4666}
4667
4668bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004669 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004670 Parser.Lex(); // Eat "nomips16".
4671
4672 // If this is not the end of the statement, report an error.
4673 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4674 reportParseError("unexpected token, expected end of statement");
4675 return false;
4676 }
4677
4678 clearFeatureBits(Mips::FeatureMips16, "mips16");
4679 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00004680 Parser.Lex(); // Consume the EndOfStatement.
4681 return false;
4682}
4683
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004684bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004685 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004686 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004687 // Line can be: .set fp=32
4688 // .set fp=xx
4689 // .set fp=64
4690 Parser.Lex(); // Eat fp token
4691 AsmToken Tok = Parser.getTok();
4692 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004693 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004694 return false;
4695 }
4696 Parser.Lex(); // Eat '=' token.
4697 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004698
4699 if (!parseFpABIValue(FpAbiVal, ".set"))
4700 return false;
4701
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004702 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004703 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004704 return false;
4705 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004706 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004707 Parser.Lex(); // Consume the EndOfStatement.
4708 return false;
4709}
4710
Toma Tabacu32c72aa2015-06-30 09:36:50 +00004711bool MipsAsmParser::parseSetOddSPRegDirective() {
4712 MCAsmParser &Parser = getParser();
4713
4714 Parser.Lex(); // Eat "oddspreg".
4715 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4716 reportParseError("unexpected token, expected end of statement");
4717 return false;
4718 }
4719
4720 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4721 getTargetStreamer().emitDirectiveSetOddSPReg();
4722 return false;
4723}
4724
4725bool MipsAsmParser::parseSetNoOddSPRegDirective() {
4726 MCAsmParser &Parser = getParser();
4727
4728 Parser.Lex(); // Eat "nooddspreg".
4729 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4730 reportParseError("unexpected token, expected end of statement");
4731 return false;
4732 }
4733
4734 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4735 getTargetStreamer().emitDirectiveSetNoOddSPReg();
4736 return false;
4737}
4738
Toma Tabacu9db22db2014-09-09 10:15:38 +00004739bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004740 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004741 SMLoc Loc = getLexer().getLoc();
4742
4743 Parser.Lex();
4744 if (getLexer().isNot(AsmToken::EndOfStatement))
4745 return reportParseError("unexpected token, expected end of statement");
4746
4747 // Always keep an element on the options "stack" to prevent the user
4748 // from changing the initial options. This is how we remember them.
4749 if (AssemblerOptions.size() == 2)
4750 return reportParseError(Loc, ".set pop with no .set push");
4751
Akira Hatanakab11ef082015-11-14 06:35:56 +00004752 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004753 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00004754 setAvailableFeatures(
4755 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
4756 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00004757
4758 getTargetStreamer().emitDirectiveSetPop();
4759 return false;
4760}
4761
4762bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004763 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004764 Parser.Lex();
4765 if (getLexer().isNot(AsmToken::EndOfStatement))
4766 return reportParseError("unexpected token, expected end of statement");
4767
4768 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00004769 AssemblerOptions.push_back(
4770 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00004771
4772 getTargetStreamer().emitDirectiveSetPush();
4773 return false;
4774}
4775
Toma Tabacu29696502015-06-02 09:48:04 +00004776bool MipsAsmParser::parseSetSoftFloatDirective() {
4777 MCAsmParser &Parser = getParser();
4778 Parser.Lex();
4779 if (getLexer().isNot(AsmToken::EndOfStatement))
4780 return reportParseError("unexpected token, expected end of statement");
4781
4782 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4783 getTargetStreamer().emitDirectiveSetSoftFloat();
4784 return false;
4785}
4786
4787bool MipsAsmParser::parseSetHardFloatDirective() {
4788 MCAsmParser &Parser = getParser();
4789 Parser.Lex();
4790 if (getLexer().isNot(AsmToken::EndOfStatement))
4791 return reportParseError("unexpected token, expected end of statement");
4792
4793 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4794 getTargetStreamer().emitDirectiveSetHardFloat();
4795 return false;
4796}
4797
Jack Carterd76b2372013-03-21 21:44:16 +00004798bool MipsAsmParser::parseSetAssignment() {
4799 StringRef Name;
4800 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00004801 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00004802
4803 if (Parser.parseIdentifier(Name))
4804 reportParseError("expected identifier after .set");
4805
4806 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004807 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00004808 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00004809
Jack Carter3b2c96e2014-01-22 23:31:38 +00004810 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00004811 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00004812
Jim Grosbach6f482002015-05-18 18:43:14 +00004813 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00004814 Sym->setVariableValue(Value);
4815
4816 return false;
4817}
Jack Carterd0bd6422013-04-18 00:41:53 +00004818
Toma Tabacu26647792014-09-09 12:52:14 +00004819bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004820 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00004821 Parser.Lex();
4822 if (getLexer().isNot(AsmToken::EndOfStatement))
4823 return reportParseError("unexpected token, expected end of statement");
4824
4825 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00004826 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00004827 setAvailableFeatures(
4828 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
4829 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00004830 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
4831
4832 getTargetStreamer().emitDirectiveSetMips0();
4833 return false;
4834}
4835
Toma Tabacu85618b32014-08-19 14:22:52 +00004836bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004837 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00004838 Parser.Lex();
4839 if (getLexer().isNot(AsmToken::Equal))
4840 return reportParseError("unexpected token, expected equals sign");
4841
4842 Parser.Lex();
4843 StringRef Arch;
4844 if (Parser.parseIdentifier(Arch))
4845 return reportParseError("expected arch identifier");
4846
4847 StringRef ArchFeatureName =
4848 StringSwitch<StringRef>(Arch)
4849 .Case("mips1", "mips1")
4850 .Case("mips2", "mips2")
4851 .Case("mips3", "mips3")
4852 .Case("mips4", "mips4")
4853 .Case("mips5", "mips5")
4854 .Case("mips32", "mips32")
4855 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004856 .Case("mips32r3", "mips32r3")
4857 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004858 .Case("mips32r6", "mips32r6")
4859 .Case("mips64", "mips64")
4860 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004861 .Case("mips64r3", "mips64r3")
4862 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004863 .Case("mips64r6", "mips64r6")
4864 .Case("cnmips", "cnmips")
4865 .Case("r4000", "mips3") // This is an implementation of Mips3.
4866 .Default("");
4867
4868 if (ArchFeatureName.empty())
4869 return reportParseError("unsupported architecture");
4870
4871 selectArch(ArchFeatureName);
4872 getTargetStreamer().emitDirectiveSetArch(Arch);
4873 return false;
4874}
4875
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004876bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004877 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004878 Parser.Lex();
4879 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004880 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004881
Matheus Almeida2852af82014-04-22 10:15:54 +00004882 switch (Feature) {
4883 default:
4884 llvm_unreachable("Unimplemented feature");
4885 case Mips::FeatureDSP:
4886 setFeatureBits(Mips::FeatureDSP, "dsp");
4887 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004888 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004889 case Mips::FeatureMicroMips:
4890 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004891 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004892 case Mips::FeatureMips1:
4893 selectArch("mips1");
4894 getTargetStreamer().emitDirectiveSetMips1();
4895 break;
4896 case Mips::FeatureMips2:
4897 selectArch("mips2");
4898 getTargetStreamer().emitDirectiveSetMips2();
4899 break;
4900 case Mips::FeatureMips3:
4901 selectArch("mips3");
4902 getTargetStreamer().emitDirectiveSetMips3();
4903 break;
4904 case Mips::FeatureMips4:
4905 selectArch("mips4");
4906 getTargetStreamer().emitDirectiveSetMips4();
4907 break;
4908 case Mips::FeatureMips5:
4909 selectArch("mips5");
4910 getTargetStreamer().emitDirectiveSetMips5();
4911 break;
4912 case Mips::FeatureMips32:
4913 selectArch("mips32");
4914 getTargetStreamer().emitDirectiveSetMips32();
4915 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004916 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004917 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004918 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004919 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004920 case Mips::FeatureMips32r3:
4921 selectArch("mips32r3");
4922 getTargetStreamer().emitDirectiveSetMips32R3();
4923 break;
4924 case Mips::FeatureMips32r5:
4925 selectArch("mips32r5");
4926 getTargetStreamer().emitDirectiveSetMips32R5();
4927 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004928 case Mips::FeatureMips32r6:
4929 selectArch("mips32r6");
4930 getTargetStreamer().emitDirectiveSetMips32R6();
4931 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004932 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004933 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00004934 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00004935 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004936 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004937 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004938 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00004939 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004940 case Mips::FeatureMips64r3:
4941 selectArch("mips64r3");
4942 getTargetStreamer().emitDirectiveSetMips64R3();
4943 break;
4944 case Mips::FeatureMips64r5:
4945 selectArch("mips64r5");
4946 getTargetStreamer().emitDirectiveSetMips64R5();
4947 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004948 case Mips::FeatureMips64r6:
4949 selectArch("mips64r6");
4950 getTargetStreamer().emitDirectiveSetMips64R6();
4951 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004952 }
4953 return false;
4954}
4955
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004956bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004957 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004958 if (getLexer().isNot(AsmToken::Comma)) {
4959 SMLoc Loc = getLexer().getLoc();
4960 Parser.eatToEndOfStatement();
4961 return Error(Loc, ErrorStr);
4962 }
4963
Matheus Almeida2852af82014-04-22 10:15:54 +00004964 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004965 return true;
4966}
4967
Daniel Sanderse2982ad2015-09-17 16:08:39 +00004968// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
4969// In this class, it is only used for .cprestore.
4970// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
4971// MipsTargetELFStreamer and MipsAsmParser.
4972bool MipsAsmParser::isPicAndNotNxxAbi() {
4973 return inPicMode() && !(isABI_N32() || isABI_N64());
4974}
4975
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004976bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00004977 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00004978 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004979
Toma Tabacudde4c462014-11-06 10:02:45 +00004980 if (inMips16Mode()) {
4981 reportParseError(".cpload is not supported in Mips16 mode");
4982 return false;
4983 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004984
David Blaikie960ea3f2014-06-08 16:18:35 +00004985 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00004986 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004987 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4988 reportParseError("expected register containing function address");
4989 return false;
4990 }
4991
David Blaikie960ea3f2014-06-08 16:18:35 +00004992 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
4993 if (!RegOpnd.isGPRAsmReg()) {
4994 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004995 return false;
4996 }
4997
Toma Tabacudde4c462014-11-06 10:02:45 +00004998 // If this is not the end of the statement, report an error.
4999 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5000 reportParseError("unexpected token, expected end of statement");
5001 return false;
5002 }
5003
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005004 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005005 return false;
5006}
5007
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005008bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5009 MCAsmParser &Parser = getParser();
5010
5011 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5012 // is used in non-PIC mode.
5013
5014 if (inMips16Mode()) {
5015 reportParseError(".cprestore is not supported in Mips16 mode");
5016 return false;
5017 }
5018
5019 // Get the stack offset value.
5020 const MCExpr *StackOffset;
5021 int64_t StackOffsetVal;
5022 if (Parser.parseExpression(StackOffset)) {
5023 reportParseError("expected stack offset value");
5024 return false;
5025 }
5026
5027 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5028 reportParseError("stack offset is not an absolute expression");
5029 return false;
5030 }
5031
5032 if (StackOffsetVal < 0) {
5033 Warning(Loc, ".cprestore with negative stack offset has no effect");
5034 IsCpRestoreSet = false;
5035 } else {
5036 IsCpRestoreSet = true;
5037 CpRestoreOffset = StackOffsetVal;
5038 }
5039
5040 // If this is not the end of the statement, report an error.
5041 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5042 reportParseError("unexpected token, expected end of statement");
5043 return false;
5044 }
5045
5046 // Store the $gp on the stack.
5047 SmallVector<MCInst, 3> StoreInsts;
5048 createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc,
5049 StoreInsts);
5050
5051 getTargetStreamer().emitDirectiveCpRestore(StoreInsts, CpRestoreOffset);
5052 Parser.Lex(); // Consume the EndOfStatement.
5053 return false;
5054}
5055
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005056bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005057 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005058 unsigned FuncReg;
5059 unsigned Save;
5060 bool SaveIsReg = true;
5061
Matheus Almeida7e815762014-06-18 13:08:59 +00005062 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005063 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005064 if (ResTy == MatchOperand_NoMatch) {
5065 reportParseError("expected register containing function address");
5066 Parser.eatToEndOfStatement();
5067 return false;
5068 }
5069
5070 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5071 if (!FuncRegOpnd.isGPRAsmReg()) {
5072 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
5073 Parser.eatToEndOfStatement();
5074 return false;
5075 }
5076
5077 FuncReg = FuncRegOpnd.getGPR32Reg();
5078 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005079
Toma Tabacu65f10572014-09-16 15:00:52 +00005080 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005081 return true;
5082
Toma Tabacu13964452014-09-04 13:23:44 +00005083 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005084 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005085 const MCExpr *OffsetExpr;
5086 int64_t OffsetVal;
5087 SMLoc ExprLoc = getLexer().getLoc();
5088
5089 if (Parser.parseExpression(OffsetExpr) ||
5090 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5091 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005092 Parser.eatToEndOfStatement();
5093 return false;
5094 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005095
5096 Save = OffsetVal;
5097 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005098 } else {
5099 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5100 if (!SaveOpnd.isGPRAsmReg()) {
5101 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5102 Parser.eatToEndOfStatement();
5103 return false;
5104 }
5105 Save = SaveOpnd.getGPR32Reg();
5106 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005107
Toma Tabacu65f10572014-09-16 15:00:52 +00005108 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005109 return true;
5110
Toma Tabacu8874eac2015-02-18 13:46:53 +00005111 const MCExpr *Expr;
5112 if (Parser.parseExpression(Expr)) {
5113 reportParseError("expected expression");
5114 return false;
5115 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005116
Toma Tabacu8874eac2015-02-18 13:46:53 +00005117 if (Expr->getKind() != MCExpr::SymbolRef) {
5118 reportParseError("expected symbol");
5119 return false;
5120 }
5121 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5122
Daniel Sandersf173dda2015-09-22 10:50:09 +00005123 CpSaveLocation = Save;
5124 CpSaveLocationIsRegister = SaveIsReg;
5125
Toma Tabacu8874eac2015-02-18 13:46:53 +00005126 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5127 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005128 return false;
5129}
5130
Daniel Sandersf173dda2015-09-22 10:50:09 +00005131bool MipsAsmParser::parseDirectiveCPReturn() {
5132 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5133 CpSaveLocationIsRegister);
5134 return false;
5135}
5136
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005137bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005138 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005139 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5140 const AsmToken &Tok = Parser.getTok();
5141
5142 if (Tok.getString() == "2008") {
5143 Parser.Lex();
5144 getTargetStreamer().emitDirectiveNaN2008();
5145 return false;
5146 } else if (Tok.getString() == "legacy") {
5147 Parser.Lex();
5148 getTargetStreamer().emitDirectiveNaNLegacy();
5149 return false;
5150 }
5151 }
5152 // If we don't recognize the option passed to the .nan
5153 // directive (e.g. no option or unknown option), emit an error.
5154 reportParseError("invalid option in .nan directive");
5155 return false;
5156}
5157
Jack Carter0b744b32012-10-04 02:29:46 +00005158bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005159 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005160 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005161 const AsmToken &Tok = Parser.getTok();
5162
5163 if (Tok.getString() == "noat") {
5164 return parseSetNoAtDirective();
5165 } else if (Tok.getString() == "at") {
5166 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005167 } else if (Tok.getString() == "arch") {
5168 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005169 } else if (Tok.getString() == "fp") {
5170 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005171 } else if (Tok.getString() == "oddspreg") {
5172 return parseSetOddSPRegDirective();
5173 } else if (Tok.getString() == "nooddspreg") {
5174 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005175 } else if (Tok.getString() == "pop") {
5176 return parseSetPopDirective();
5177 } else if (Tok.getString() == "push") {
5178 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005179 } else if (Tok.getString() == "reorder") {
5180 return parseSetReorderDirective();
5181 } else if (Tok.getString() == "noreorder") {
5182 return parseSetNoReorderDirective();
5183 } else if (Tok.getString() == "macro") {
5184 return parseSetMacroDirective();
5185 } else if (Tok.getString() == "nomacro") {
5186 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005187 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005188 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005189 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005190 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005191 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005192 getTargetStreamer().emitDirectiveSetNoMicroMips();
5193 Parser.eatToEndOfStatement();
5194 return false;
5195 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005196 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005197 } else if (Tok.getString() == "mips0") {
5198 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005199 } else if (Tok.getString() == "mips1") {
5200 return parseSetFeature(Mips::FeatureMips1);
5201 } else if (Tok.getString() == "mips2") {
5202 return parseSetFeature(Mips::FeatureMips2);
5203 } else if (Tok.getString() == "mips3") {
5204 return parseSetFeature(Mips::FeatureMips3);
5205 } else if (Tok.getString() == "mips4") {
5206 return parseSetFeature(Mips::FeatureMips4);
5207 } else if (Tok.getString() == "mips5") {
5208 return parseSetFeature(Mips::FeatureMips5);
5209 } else if (Tok.getString() == "mips32") {
5210 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005211 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005212 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005213 } else if (Tok.getString() == "mips32r3") {
5214 return parseSetFeature(Mips::FeatureMips32r3);
5215 } else if (Tok.getString() == "mips32r5") {
5216 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005217 } else if (Tok.getString() == "mips32r6") {
5218 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005219 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005220 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005221 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005222 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005223 } else if (Tok.getString() == "mips64r3") {
5224 return parseSetFeature(Mips::FeatureMips64r3);
5225 } else if (Tok.getString() == "mips64r5") {
5226 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005227 } else if (Tok.getString() == "mips64r6") {
5228 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005229 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005230 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005231 } else if (Tok.getString() == "nodsp") {
5232 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005233 } else if (Tok.getString() == "msa") {
5234 return parseSetMsaDirective();
5235 } else if (Tok.getString() == "nomsa") {
5236 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005237 } else if (Tok.getString() == "softfloat") {
5238 return parseSetSoftFloatDirective();
5239 } else if (Tok.getString() == "hardfloat") {
5240 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005241 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005242 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005243 parseSetAssignment();
5244 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005245 }
Jack Carter07c818d2013-01-25 01:31:34 +00005246
Jack Carter0b744b32012-10-04 02:29:46 +00005247 return true;
5248}
5249
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005250/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005251/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005252bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005253 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005254 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5255 for (;;) {
5256 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005257 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005258 return true;
5259
5260 getParser().getStreamer().EmitValue(Value, Size);
5261
5262 if (getLexer().is(AsmToken::EndOfStatement))
5263 break;
5264
Jack Carter07c818d2013-01-25 01:31:34 +00005265 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005266 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005267 Parser.Lex();
5268 }
5269 }
5270
5271 Parser.Lex();
5272 return false;
5273}
5274
Vladimir Medic4c299852013-11-06 11:27:05 +00005275/// parseDirectiveGpWord
5276/// ::= .gpword local_sym
5277bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005278 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005279 const MCExpr *Value;
5280 // EmitGPRel32Value requires an expression, so we are using base class
5281 // method to evaluate the expression.
5282 if (getParser().parseExpression(Value))
5283 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005284 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005285
Vladimir Medice10c1122013-11-13 13:18:04 +00005286 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005287 return Error(getLexer().getLoc(),
5288 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005289 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005290 return false;
5291}
5292
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005293/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005294/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005295bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005296 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005297 const MCExpr *Value;
5298 // EmitGPRel64Value requires an expression, so we are using base class
5299 // method to evaluate the expression.
5300 if (getParser().parseExpression(Value))
5301 return true;
5302 getParser().getStreamer().EmitGPRel64Value(Value);
5303
5304 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005305 return Error(getLexer().getLoc(),
5306 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005307 Parser.Lex(); // Eat EndOfStatement token.
5308 return false;
5309}
5310
Jack Carter0cd3c192014-01-06 23:27:31 +00005311bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005312 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005313 // Get the option token.
5314 AsmToken Tok = Parser.getTok();
5315 // At the moment only identifiers are supported.
5316 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005317 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005318 Parser.eatToEndOfStatement();
5319 return false;
5320 }
5321
5322 StringRef Option = Tok.getIdentifier();
5323
5324 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005325 // MipsAsmParser needs to know if the current PIC mode changes.
5326 IsPicEnabled = false;
5327
Jack Carter0cd3c192014-01-06 23:27:31 +00005328 getTargetStreamer().emitDirectiveOptionPic0();
5329 Parser.Lex();
5330 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5331 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005332 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005333 Parser.eatToEndOfStatement();
5334 }
5335 return false;
5336 }
5337
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005338 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005339 // MipsAsmParser needs to know if the current PIC mode changes.
5340 IsPicEnabled = true;
5341
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005342 getTargetStreamer().emitDirectiveOptionPic2();
5343 Parser.Lex();
5344 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5345 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005346 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005347 Parser.eatToEndOfStatement();
5348 }
5349 return false;
5350 }
5351
Jack Carter0cd3c192014-01-06 23:27:31 +00005352 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005353 Warning(Parser.getTok().getLoc(),
5354 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005355 Parser.eatToEndOfStatement();
5356 return false;
5357}
5358
Toma Tabacu9ca50962015-04-16 09:53:47 +00005359/// parseInsnDirective
5360/// ::= .insn
5361bool MipsAsmParser::parseInsnDirective() {
5362 // If this is not the end of the statement, report an error.
5363 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5364 reportParseError("unexpected token, expected end of statement");
5365 return false;
5366 }
5367
5368 // The actual label marking happens in
5369 // MipsELFStreamer::createPendingLabelRelocs().
5370 getTargetStreamer().emitDirectiveInsn();
5371
5372 getParser().Lex(); // Eat EndOfStatement token.
5373 return false;
5374}
5375
Daniel Sanders7e527422014-07-10 13:38:23 +00005376/// parseDirectiveModule
5377/// ::= .module oddspreg
5378/// ::= .module nooddspreg
5379/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005380/// ::= .module softfloat
5381/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005382bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005383 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005384 MCAsmLexer &Lexer = getLexer();
5385 SMLoc L = Lexer.getLoc();
5386
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005387 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005388 // TODO : get a better message.
5389 reportParseError(".module directive must appear before any code");
5390 return false;
5391 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005392
Toma Tabacuc405c822015-01-23 10:40:19 +00005393 StringRef Option;
5394 if (Parser.parseIdentifier(Option)) {
5395 reportParseError("expected .module option identifier");
5396 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005397 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005398
Toma Tabacuc405c822015-01-23 10:40:19 +00005399 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005400 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005401
Toma Tabacu3c499582015-06-25 10:56:57 +00005402 // Synchronize the abiflags information with the FeatureBits information we
5403 // changed above.
5404 getTargetStreamer().updateABIInfo(*this);
5405
5406 // If printing assembly, use the recently updated abiflags information.
5407 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5408 // emitted at the end).
5409 getTargetStreamer().emitDirectiveModuleOddSPReg();
5410
Toma Tabacuc405c822015-01-23 10:40:19 +00005411 // If this is not the end of the statement, report an error.
5412 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5413 reportParseError("unexpected token, expected end of statement");
5414 return false;
5415 }
5416
5417 return false; // parseDirectiveModule has finished successfully.
5418 } else if (Option == "nooddspreg") {
5419 if (!isABI_O32()) {
5420 Error(L, "'.module nooddspreg' requires the O32 ABI");
5421 return false;
5422 }
5423
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005424 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005425
Toma Tabacu3c499582015-06-25 10:56:57 +00005426 // Synchronize the abiflags information with the FeatureBits information we
5427 // changed above.
5428 getTargetStreamer().updateABIInfo(*this);
5429
5430 // If printing assembly, use the recently updated abiflags information.
5431 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5432 // emitted at the end).
5433 getTargetStreamer().emitDirectiveModuleOddSPReg();
5434
Toma Tabacuc405c822015-01-23 10:40:19 +00005435 // If this is not the end of the statement, report an error.
5436 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5437 reportParseError("unexpected token, expected end of statement");
5438 return false;
5439 }
5440
5441 return false; // parseDirectiveModule has finished successfully.
5442 } else if (Option == "fp") {
5443 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005444 } else if (Option == "softfloat") {
5445 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5446
5447 // Synchronize the ABI Flags information with the FeatureBits information we
5448 // updated above.
5449 getTargetStreamer().updateABIInfo(*this);
5450
5451 // If printing assembly, use the recently updated ABI Flags information.
5452 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5453 // emitted later).
5454 getTargetStreamer().emitDirectiveModuleSoftFloat();
5455
5456 // If this is not the end of the statement, report an error.
5457 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5458 reportParseError("unexpected token, expected end of statement");
5459 return false;
5460 }
5461
5462 return false; // parseDirectiveModule has finished successfully.
5463 } else if (Option == "hardfloat") {
5464 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5465
5466 // Synchronize the ABI Flags information with the FeatureBits information we
5467 // updated above.
5468 getTargetStreamer().updateABIInfo(*this);
5469
5470 // If printing assembly, use the recently updated ABI Flags information.
5471 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5472 // emitted later).
5473 getTargetStreamer().emitDirectiveModuleHardFloat();
5474
5475 // If this is not the end of the statement, report an error.
5476 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5477 reportParseError("unexpected token, expected end of statement");
5478 return false;
5479 }
5480
5481 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005482 } else {
5483 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5484 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005485}
5486
5487/// parseDirectiveModuleFP
5488/// ::= =32
5489/// ::= =xx
5490/// ::= =64
5491bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005492 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005493 MCAsmLexer &Lexer = getLexer();
5494
5495 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005496 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005497 return false;
5498 }
5499 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005500
Daniel Sanders7e527422014-07-10 13:38:23 +00005501 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005502 if (!parseFpABIValue(FpABI, ".module"))
5503 return false;
5504
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005505 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005506 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005507 return false;
5508 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005509
Toma Tabacua64e5402015-06-25 12:44:38 +00005510 // Synchronize the abiflags information with the FeatureBits information we
5511 // changed above.
5512 getTargetStreamer().updateABIInfo(*this);
5513
5514 // If printing assembly, use the recently updated abiflags information.
5515 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5516 // emitted at the end).
5517 getTargetStreamer().emitDirectiveModuleFP();
5518
Daniel Sanders7e527422014-07-10 13:38:23 +00005519 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005520 return false;
5521}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005522
Daniel Sanders7e527422014-07-10 13:38:23 +00005523bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005524 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005525 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005526 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005527 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005528
5529 if (Lexer.is(AsmToken::Identifier)) {
5530 StringRef Value = Parser.getTok().getString();
5531 Parser.Lex();
5532
5533 if (Value != "xx") {
5534 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5535 return false;
5536 }
5537
5538 if (!isABI_O32()) {
5539 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5540 return false;
5541 }
5542
Daniel Sanders7e527422014-07-10 13:38:23 +00005543 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005544 if (ModuleLevelOptions) {
5545 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5546 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5547 } else {
5548 setFeatureBits(Mips::FeatureFPXX, "fpxx");
5549 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5550 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005551 return true;
5552 }
5553
5554 if (Lexer.is(AsmToken::Integer)) {
5555 unsigned Value = Parser.getTok().getIntVal();
5556 Parser.Lex();
5557
5558 if (Value != 32 && Value != 64) {
5559 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5560 return false;
5561 }
5562
5563 if (Value == 32) {
5564 if (!isABI_O32()) {
5565 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
5566 return false;
5567 }
5568
Daniel Sanders7e527422014-07-10 13:38:23 +00005569 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005570 if (ModuleLevelOptions) {
5571 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5572 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5573 } else {
5574 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5575 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5576 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005577 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00005578 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005579 if (ModuleLevelOptions) {
5580 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5581 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5582 } else {
5583 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5584 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
5585 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005586 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005587
Daniel Sanders7e527422014-07-10 13:38:23 +00005588 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005589 }
5590
5591 return false;
5592}
5593
Jack Carter0b744b32012-10-04 02:29:46 +00005594bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005595 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005596 StringRef IDVal = DirectiveID.getString();
5597
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005598 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005599 return parseDirectiveCpLoad(DirectiveID.getLoc());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005600 if (IDVal == ".cprestore")
5601 return parseDirectiveCpRestore(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00005602 if (IDVal == ".dword") {
5603 parseDataDirective(8, DirectiveID.getLoc());
5604 return false;
5605 }
Jack Carterd0bd6422013-04-18 00:41:53 +00005606 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005607 StringRef SymbolName;
5608
5609 if (Parser.parseIdentifier(SymbolName)) {
5610 reportParseError("expected identifier after .ent");
5611 return false;
5612 }
5613
5614 // There's an undocumented extension that allows an integer to
5615 // follow the name of the procedure which AFAICS is ignored by GAS.
5616 // Example: .ent foo,2
5617 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5618 if (getLexer().isNot(AsmToken::Comma)) {
5619 // Even though we accept this undocumented extension for compatibility
5620 // reasons, the additional integer argument does not actually change
5621 // the behaviour of the '.ent' directive, so we would like to discourage
5622 // its use. We do this by not referring to the extended version in
5623 // error messages which are not directly related to its use.
5624 reportParseError("unexpected token, expected end of statement");
5625 return false;
5626 }
5627 Parser.Lex(); // Eat the comma.
5628 const MCExpr *DummyNumber;
5629 int64_t DummyNumberVal;
5630 // If the user was explicitly trying to use the extended version,
5631 // we still give helpful extension-related error messages.
5632 if (Parser.parseExpression(DummyNumber)) {
5633 reportParseError("expected number after comma");
5634 return false;
5635 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00005636 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005637 reportParseError("expected an absolute expression after comma");
5638 return false;
5639 }
5640 }
5641
5642 // If this is not the end of the statement, report an error.
5643 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5644 reportParseError("unexpected token, expected end of statement");
5645 return false;
5646 }
5647
Jim Grosbach6f482002015-05-18 18:43:14 +00005648 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005649
5650 getTargetStreamer().emitDirectiveEnt(*Sym);
5651 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005652 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005653 return false;
5654 }
5655
Jack Carter07c818d2013-01-25 01:31:34 +00005656 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005657 StringRef SymbolName;
5658
5659 if (Parser.parseIdentifier(SymbolName)) {
5660 reportParseError("expected identifier after .end");
5661 return false;
5662 }
5663
5664 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5665 reportParseError("unexpected token, expected end of statement");
5666 return false;
5667 }
5668
5669 if (CurrentFn == nullptr) {
5670 reportParseError(".end used without .ent");
5671 return false;
5672 }
5673
5674 if ((SymbolName != CurrentFn->getName())) {
5675 reportParseError(".end symbol does not match .ent symbol");
5676 return false;
5677 }
5678
5679 getTargetStreamer().emitDirectiveEnd(SymbolName);
5680 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005681 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005682 return false;
5683 }
5684
Jack Carter07c818d2013-01-25 01:31:34 +00005685 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005686 // .frame $stack_reg, frame_size_in_bytes, $return_reg
5687 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005688 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005689 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5690 reportParseError("expected stack register");
5691 return false;
5692 }
5693
5694 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5695 if (!StackRegOpnd.isGPRAsmReg()) {
5696 reportParseError(StackRegOpnd.getStartLoc(),
5697 "expected general purpose register");
5698 return false;
5699 }
5700 unsigned StackReg = StackRegOpnd.getGPR32Reg();
5701
5702 if (Parser.getTok().is(AsmToken::Comma))
5703 Parser.Lex();
5704 else {
5705 reportParseError("unexpected token, expected comma");
5706 return false;
5707 }
5708
5709 // Parse the frame size.
5710 const MCExpr *FrameSize;
5711 int64_t FrameSizeVal;
5712
5713 if (Parser.parseExpression(FrameSize)) {
5714 reportParseError("expected frame size value");
5715 return false;
5716 }
5717
Jim Grosbach13760bd2015-05-30 01:25:56 +00005718 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005719 reportParseError("frame size not an absolute expression");
5720 return false;
5721 }
5722
5723 if (Parser.getTok().is(AsmToken::Comma))
5724 Parser.Lex();
5725 else {
5726 reportParseError("unexpected token, expected comma");
5727 return false;
5728 }
5729
5730 // Parse the return register.
5731 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00005732 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005733 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5734 reportParseError("expected return register");
5735 return false;
5736 }
5737
5738 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5739 if (!ReturnRegOpnd.isGPRAsmReg()) {
5740 reportParseError(ReturnRegOpnd.getStartLoc(),
5741 "expected general purpose register");
5742 return false;
5743 }
5744
5745 // If this is not the end of the statement, report an error.
5746 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5747 reportParseError("unexpected token, expected end of statement");
5748 return false;
5749 }
5750
5751 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
5752 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005753 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005754 return false;
5755 }
5756
Jack Carter07c818d2013-01-25 01:31:34 +00005757 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00005758 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00005759 }
5760
Daniel Sandersd97a6342014-08-13 10:07:34 +00005761 if (IDVal == ".mask" || IDVal == ".fmask") {
5762 // .mask bitmask, frame_offset
5763 // bitmask: One bit for each register used.
5764 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
5765 // first register is expected to be saved.
5766 // Examples:
5767 // .mask 0x80000000, -4
5768 // .fmask 0x80000000, -4
5769 //
Jack Carterbe332172012-09-07 00:48:02 +00005770
Daniel Sandersd97a6342014-08-13 10:07:34 +00005771 // Parse the bitmask
5772 const MCExpr *BitMask;
5773 int64_t BitMaskVal;
5774
5775 if (Parser.parseExpression(BitMask)) {
5776 reportParseError("expected bitmask value");
5777 return false;
5778 }
5779
Jim Grosbach13760bd2015-05-30 01:25:56 +00005780 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005781 reportParseError("bitmask not an absolute expression");
5782 return false;
5783 }
5784
5785 if (Parser.getTok().is(AsmToken::Comma))
5786 Parser.Lex();
5787 else {
5788 reportParseError("unexpected token, expected comma");
5789 return false;
5790 }
5791
5792 // Parse the frame_offset
5793 const MCExpr *FrameOffset;
5794 int64_t FrameOffsetVal;
5795
5796 if (Parser.parseExpression(FrameOffset)) {
5797 reportParseError("expected frame offset value");
5798 return false;
5799 }
5800
Jim Grosbach13760bd2015-05-30 01:25:56 +00005801 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005802 reportParseError("frame offset not an absolute expression");
5803 return false;
5804 }
5805
5806 // If this is not the end of the statement, report an error.
5807 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5808 reportParseError("unexpected token, expected end of statement");
5809 return false;
5810 }
5811
5812 if (IDVal == ".mask")
5813 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
5814 else
5815 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00005816 return false;
5817 }
5818
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005819 if (IDVal == ".nan")
5820 return parseDirectiveNaN();
5821
Jack Carter07c818d2013-01-25 01:31:34 +00005822 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005823 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00005824 return false;
5825 }
5826
Rafael Espindolab59fb732014-03-28 18:50:26 +00005827 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005828 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005829 return false;
5830 }
5831
Jack Carter07c818d2013-01-25 01:31:34 +00005832 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005833 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00005834 return false;
5835 }
5836
Jack Carter0cd3c192014-01-06 23:27:31 +00005837 if (IDVal == ".option")
5838 return parseDirectiveOption();
5839
5840 if (IDVal == ".abicalls") {
5841 getTargetStreamer().emitDirectiveAbiCalls();
5842 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005843 Error(Parser.getTok().getLoc(),
5844 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005845 // Clear line
5846 Parser.eatToEndOfStatement();
5847 }
5848 return false;
5849 }
5850
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005851 if (IDVal == ".cpsetup")
5852 return parseDirectiveCPSetup();
5853
Daniel Sandersf173dda2015-09-22 10:50:09 +00005854 if (IDVal == ".cpreturn")
5855 return parseDirectiveCPReturn();
5856
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005857 if (IDVal == ".module")
5858 return parseDirectiveModule();
5859
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005860 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
5861 return parseInternalDirectiveReallowModule();
5862
Toma Tabacu9ca50962015-04-16 09:53:47 +00005863 if (IDVal == ".insn")
5864 return parseInsnDirective();
5865
Rafael Espindola870c4e92012-01-11 03:56:41 +00005866 return true;
5867}
5868
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005869bool MipsAsmParser::parseInternalDirectiveReallowModule() {
5870 // If this is not the end of the statement, report an error.
5871 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5872 reportParseError("unexpected token, expected end of statement");
5873 return false;
5874 }
5875
5876 getTargetStreamer().reallowModuleDirective();
5877
5878 getParser().Lex(); // Eat EndOfStatement token.
5879 return false;
5880}
5881
Rafael Espindola870c4e92012-01-11 03:56:41 +00005882extern "C" void LLVMInitializeMipsAsmParser() {
5883 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
5884 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
5885 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
5886 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
5887}
Jack Carterb4dbc172012-09-05 23:34:03 +00005888
5889#define GET_REGISTER_MATCHER
5890#define GET_MATCHER_IMPLEMENTATION
5891#include "MipsGenAsmMatcher.inc"