blob: 76cca79741bc8f3f956ef4b274bd79230ed9d9de [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Eric Christophera5762812015-01-26 17:33:46 +000010#include "MCTargetDesc/MipsABIInfo.h"
Petar Jovanovica5da5882014-02-04 18:41:57 +000011#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000012#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000013#include "MipsRegisterInfo.h"
Daniel Sandersa6994442015-08-18 12:33:54 +000014#include "MipsTargetObjectFile.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000015#include "MipsTargetStreamer.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000016#include "llvm/ADT/APInt.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000017#include "llvm/ADT/SmallVector.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000018#include "llvm/ADT/StringSwitch.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000019#include "llvm/MC/MCContext.h"
20#include "llvm/MC/MCExpr.h"
21#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000022#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000023#include "llvm/MC/MCParser/MCAsmLexer.h"
24#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000025#include "llvm/MC/MCStreamer.h"
26#include "llvm/MC/MCSubtargetInfo.h"
27#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000028#include "llvm/MC/MCTargetAsmParser.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000029#include "llvm/Support/Debug.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000030#include "llvm/Support/MathExtras.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000031#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000032#include "llvm/Support/TargetRegistry.h"
Benjamin Kramer799003b2015-03-23 19:32:43 +000033#include "llvm/Support/raw_ostream.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000034#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000035
36using namespace llvm;
37
Chandler Carruthe96dd892014-04-21 22:55:11 +000038#define DEBUG_TYPE "mips-asm-parser"
39
Joey Gouly0e76fa72013-09-12 10:28:05 +000040namespace llvm {
41class MCInstrInfo;
42}
43
Rafael Espindola870c4e92012-01-11 03:56:41 +000044namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000045class MipsAssemblerOptions {
46public:
Toma Tabacu465acfd2015-06-09 13:33:26 +000047 MipsAssemblerOptions(const FeatureBitset &Features_) :
Toma Tabacu9db22db2014-09-09 10:15:38 +000048 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000049
Toma Tabacu9db22db2014-09-09 10:15:38 +000050 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000051 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000052 Reorder = Opts->isReorder();
53 Macro = Opts->isMacro();
54 Features = Opts->getFeatures();
55 }
56
Toma Tabacub19cf202015-04-27 13:12:59 +000057 unsigned getATRegIndex() const { return ATReg; }
58 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000059 if (Reg > 31)
60 return false;
61
62 ATReg = Reg;
63 return true;
64 }
Jack Carter0b744b32012-10-04 02:29:46 +000065
Toma Tabacu9db22db2014-09-09 10:15:38 +000066 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000067 void setReorder() { Reorder = true; }
68 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000069
Toma Tabacu9db22db2014-09-09 10:15:38 +000070 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000071 void setMacro() { Macro = true; }
72 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000073
Toma Tabacu465acfd2015-06-09 13:33:26 +000074 const FeatureBitset &getFeatures() const { return Features; }
75 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000076
Daniel Sandersf0df2212014-08-04 12:20:00 +000077 // Set of features that are either architecture features or referenced
78 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
79 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
80 // The reason we need this mask is explained in the selectArch function.
81 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +000082 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +000083
Jack Carter0b744b32012-10-04 02:29:46 +000084private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000085 unsigned ATReg;
86 bool Reorder;
87 bool Macro;
Toma Tabacu465acfd2015-06-09 13:33:26 +000088 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +000089};
90}
91
Michael Kupersteindb0712f2015-05-26 10:47:10 +000092const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
93 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
94 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
95 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
96 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
97 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
98 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
99 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
100 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
101};
102
Jack Carter0b744b32012-10-04 02:29:46 +0000103namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +0000104class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000105 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000106 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000107 return static_cast<MipsTargetStreamer &>(TS);
108 }
109
Jack Carterb4dbc172012-09-05 23:34:03 +0000110 MCSubtargetInfo &STI;
Eric Christophera5762812015-01-26 17:33:46 +0000111 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000112 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000113 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
114 // nullptr, which indicates that no function is currently
115 // selected. This usually happens after an '.end func'
116 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000117 bool IsLittleEndian;
Daniel Sandersa6994442015-08-18 12:33:54 +0000118 bool IsPicEnabled;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000119 bool IsCpRestoreSet;
120 int CpRestoreOffset;
Daniel Sandersf173dda2015-09-22 10:50:09 +0000121 unsigned CpSaveLocation;
122 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
123 bool CpSaveLocationIsRegister;
Jack Carter0b744b32012-10-04 02:29:46 +0000124
Daniel Sandersef638fe2014-10-03 15:37:37 +0000125 // Print a warning along with its fix-it message at the given range.
126 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
127 SMRange Range, bool ShowColors = true);
128
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000129#define GET_ASSEMBLER_HEADER
130#include "MipsGenAsmMatcher.inc"
131
Matheus Almeida595fcab2014-06-11 15:05:56 +0000132 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
133
Chad Rosier49963552012-10-13 00:26:04 +0000134 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000135 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000136 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000137 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000138
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000139 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000140 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000141
Toma Tabacu13964452014-09-04 13:23:44 +0000142 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000143
Toma Tabacu13964452014-09-04 13:23:44 +0000144 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000145
David Blaikie960ea3f2014-06-08 16:18:35 +0000146 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
147 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000148
Craig Topper56c590a2014-04-29 07:58:02 +0000149 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000150
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000151 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
152 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000153 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000154 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000155 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
156 SMLoc S);
157 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
158 OperandMatchResultTy parseImm(OperandVector &Operands);
159 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
160 OperandMatchResultTy parseInvNum(OperandVector &Operands);
161 OperandMatchResultTy parseLSAImm(OperandVector &Operands);
162 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
163 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
164 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000165
David Blaikie960ea3f2014-06-08 16:18:35 +0000166 bool searchSymbolAlias(OperandVector &Operands);
167
Toma Tabacu13964452014-09-04 13:23:44 +0000168 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000169
Jack Carter30a59822012-10-04 04:03:53 +0000170 bool needsExpansion(MCInst &Inst);
171
Matheus Almeida3813d572014-06-19 14:39:14 +0000172 // Expands assembly pseudo instructions.
173 // Returns false on success, true otherwise.
174 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000175 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000176
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000177 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
178 SmallVectorImpl<MCInst> &Instructions);
179
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000180 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000181 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000182 SmallVectorImpl<MCInst> &Instructions);
183
Toma Tabacuf712ede2015-06-17 14:31:51 +0000184 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
185 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
186 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacu674825c2015-06-16 12:16:24 +0000187
Toma Tabacu00e98672015-05-01 12:19:27 +0000188 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000189 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000190
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000191 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
192 const MCOperand &Offset, bool Is32BitAddress,
193 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000194
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000195 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
196 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000197
Jack Carter9e65aa32013-03-22 00:05:30 +0000198 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000199 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
200 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000201
202 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
203 SmallVectorImpl<MCInst> &Instructions);
204
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000205 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
206 SmallVectorImpl<MCInst> &Instructions);
207
Toma Tabacue1e460d2015-06-11 10:36:10 +0000208 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc,
209 SmallVectorImpl<MCInst> &Instructions);
210
Toma Tabacu1a108322015-06-17 13:20:24 +0000211 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc,
212 SmallVectorImpl<MCInst> &Instructions);
213
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000214 bool expandDiv(MCInst &Inst, SMLoc IDLoc,
215 SmallVectorImpl<MCInst> &Instructions, const bool IsMips64,
216 const bool Signed);
217
Toma Tabacud88d79c2015-06-23 14:39:42 +0000218 bool expandUlhu(MCInst &Inst, SMLoc IDLoc,
219 SmallVectorImpl<MCInst> &Instructions);
220
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000221 bool expandUlw(MCInst &Inst, SMLoc IDLoc,
222 SmallVectorImpl<MCInst> &Instructions);
223
Toma Tabacu234482a2015-03-16 12:03:39 +0000224 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
225 SmallVectorImpl<MCInst> &Instructions);
226
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000227 void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +0000228 bool Is64Bit, SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000229
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000230 void createCpRestoreMemOp(bool IsLoad, int StackOffset, SMLoc IDLoc,
231 SmallVectorImpl<MCInst> &Instructions);
232
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000233 bool reportParseError(Twine ErrorMsg);
234 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000235
Jack Carterb5cf5902013-04-17 00:18:04 +0000236 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000237 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000238
Vladimir Medic4c299852013-11-06 11:27:05 +0000239 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000240
241 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000242 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000243 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000244 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000245 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000246 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000247 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000248 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000249 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000250 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000251 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000252 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000253 bool parseInsnDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000254
255 bool parseSetAtDirective();
256 bool parseSetNoAtDirective();
257 bool parseSetMacroDirective();
258 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000259 bool parseSetMsaDirective();
260 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000261 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000262 bool parseSetReorderDirective();
263 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000264 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000265 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000266 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000267 bool parseSetOddSPRegDirective();
268 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000269 bool parseSetPopDirective();
270 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000271 bool parseSetSoftFloatDirective();
272 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000273
Jack Carterd76b2372013-03-21 21:44:16 +0000274 bool parseSetAssignment();
275
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000276 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000277 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000278 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000279 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000280 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000281 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
282 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000283
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000284 bool parseInternalDirectiveReallowModule();
285
Jack Carterdc1e35d2012-09-06 20:00:02 +0000286 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000287
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000288 bool eatComma(StringRef ErrorStr);
289
Jack Carter1ac53222013-02-20 23:11:17 +0000290 int matchCPURegisterName(StringRef Symbol);
291
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000292 int matchHWRegsRegisterName(StringRef Symbol);
293
Jack Carter873c7242013-01-12 01:03:14 +0000294 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000295
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000296 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000297
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000298 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000299
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000300 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000301
Jack Carter5dc8ac92013-09-25 23:50:44 +0000302 int matchMSA128RegisterName(StringRef Name);
303
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000304 int matchMSA128CtrlRegisterName(StringRef Name);
305
Jack Carterd0bd6422013-04-18 00:41:53 +0000306 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000307
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000308 unsigned getGPR(int RegNo);
309
Toma Tabacu89a712b2015-04-15 10:48:56 +0000310 /// Returns the internal register number for the current AT. Also checks if
311 /// the current AT is unavailable (set to $0) and gives an error if it is.
312 /// This should be used in pseudo-instruction expansions which need AT.
313 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000314
315 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000316 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000317
318 // Helper function that checks if the value of a vector index is within the
319 // boundaries of accepted values for each RegisterKind
320 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
321 bool validateMSAIndex(int Val, int RegKind);
322
Daniel Sandersf0df2212014-08-04 12:20:00 +0000323 // Selects a new architecture by updating the FeatureBits with the necessary
324 // info including implied dependencies.
325 // Internally, it clears all the feature bits related to *any* architecture
326 // and selects the new one using the ToggleFeature functionality of the
327 // MCSubtargetInfo object that handles implied dependencies. The reason we
328 // clear all the arch related bits manually is because ToggleFeature only
329 // clears the features that imply the feature being cleared and not the
330 // features implied by the feature being cleared. This is easier to see
331 // with an example:
332 // --------------------------------------------------
333 // | Feature | Implies |
334 // | -------------------------------------------------|
335 // | FeatureMips1 | None |
336 // | FeatureMips2 | FeatureMips1 |
337 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
338 // | FeatureMips4 | FeatureMips3 |
339 // | ... | |
340 // --------------------------------------------------
341 //
342 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
343 // FeatureMipsGP64 | FeatureMips1)
344 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
345 void selectArch(StringRef ArchFeature) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000346 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000347 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
348 STI.setFeatureBits(FeatureBits);
349 setAvailableFeatures(
350 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000351 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000352 }
353
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000354 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000355 if (!(STI.getFeatureBits()[Feature])) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000356 setAvailableFeatures(
357 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000358 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000359 }
360 }
361
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000362 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000363 if (STI.getFeatureBits()[Feature]) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000364 setAvailableFeatures(
365 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000366 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000367 }
368 }
369
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000370 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
371 setFeatureBits(Feature, FeatureString);
372 AssemblerOptions.front()->setFeatures(STI.getFeatureBits());
373 }
374
375 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
376 clearFeatureBits(Feature, FeatureString);
377 AssemblerOptions.front()->setFeatures(STI.getFeatureBits());
378 }
379
Rafael Espindola870c4e92012-01-11 03:56:41 +0000380public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000381 enum MipsMatchResultTy {
382 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
383#define GET_OPERAND_DIAGNOSTIC_TYPES
384#include "MipsGenAsmMatcher.inc"
385#undef GET_OPERAND_DIAGNOSTIC_TYPES
386
387 };
388
Joey Gouly0e76fa72013-09-12 10:28:05 +0000389 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000390 const MCInstrInfo &MII, const MCTargetOptions &Options)
Colin LeMahieufe2c8b82015-07-27 21:56:53 +0000391 : MCTargetAsmParser(Options), STI(sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000392 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
393 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000394 MCAsmParserExtension::Initialize(parser);
395
Toma Tabacu11e14a92015-04-21 11:50:52 +0000396 parser.addAliasForDirective(".asciiz", ".asciz");
397
Jack Carterb4dbc172012-09-05 23:34:03 +0000398 // Initialize the set of available features.
399 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000400
Toma Tabacu9db22db2014-09-09 10:15:38 +0000401 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000402 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000403 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000404
Toma Tabacu9db22db2014-09-09 10:15:38 +0000405 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000406 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000407 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000408
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000409 getTargetStreamer().updateABIInfo(*this);
410
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000411 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000412 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000413
414 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000415
Daniel Sandersa6994442015-08-18 12:33:54 +0000416 IsPicEnabled =
417 (getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_);
418
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000419 IsCpRestoreSet = false;
420 CpRestoreOffset = -1;
421
Daniel Sanders50f17232015-09-15 16:17:27 +0000422 Triple TheTriple(sti.getTargetTriple());
423 if ((TheTriple.getArch() == Triple::mips) ||
424 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000425 IsLittleEndian = false;
426 else
427 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000428 }
429
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000430 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
431 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
432
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000433 bool isGP64bit() const { return STI.getFeatureBits()[Mips::FeatureGP64Bit]; }
434 bool isFP64bit() const { return STI.getFeatureBits()[Mips::FeatureFP64Bit]; }
Eric Christophera5762812015-01-26 17:33:46 +0000435 const MipsABIInfo &getABI() const { return ABI; }
436 bool isABI_N32() const { return ABI.IsN32(); }
437 bool isABI_N64() const { return ABI.IsN64(); }
438 bool isABI_O32() const { return ABI.IsO32(); }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000439 bool isABI_FPXX() const { return STI.getFeatureBits()[Mips::FeatureFPXX]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000440
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000441 bool useOddSPReg() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000442 return !(STI.getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000443 }
444
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000445 bool inMicroMipsMode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000446 return STI.getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000447 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000448 bool hasMips1() const { return STI.getFeatureBits()[Mips::FeatureMips1]; }
449 bool hasMips2() const { return STI.getFeatureBits()[Mips::FeatureMips2]; }
450 bool hasMips3() const { return STI.getFeatureBits()[Mips::FeatureMips3]; }
451 bool hasMips4() const { return STI.getFeatureBits()[Mips::FeatureMips4]; }
452 bool hasMips5() const { return STI.getFeatureBits()[Mips::FeatureMips5]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000453 bool hasMips32() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000454 return STI.getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000455 }
456 bool hasMips64() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000457 return STI.getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000458 }
459 bool hasMips32r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000460 return STI.getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000461 }
462 bool hasMips64r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000463 return STI.getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000464 }
Daniel Sanders17793142015-02-18 16:24:50 +0000465 bool hasMips32r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000466 return (STI.getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000467 }
468 bool hasMips64r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000469 return (STI.getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000470 }
471 bool hasMips32r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000472 return (STI.getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000473 }
474 bool hasMips64r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000475 return (STI.getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000476 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000477 bool hasMips32r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000478 return STI.getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000479 }
480 bool hasMips64r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000481 return STI.getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000482 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000483
484 bool hasDSP() const { return STI.getFeatureBits()[Mips::FeatureDSP]; }
485 bool hasDSPR2() const { return STI.getFeatureBits()[Mips::FeatureDSPR2]; }
486 bool hasMSA() const { return STI.getFeatureBits()[Mips::FeatureMSA]; }
Kai Nackee0245392015-01-27 19:11:28 +0000487 bool hasCnMips() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000488 return (STI.getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000489 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000490
Daniel Sandersa6994442015-08-18 12:33:54 +0000491 bool inPicMode() {
492 return IsPicEnabled;
493 }
494
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000495 bool inMips16Mode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000496 return STI.getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000497 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000498
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000499 bool useTraps() const {
500 return STI.getFeatureBits()[Mips::FeatureUseTCCInDIV];
501 }
502
Eric Christophere8ae3e32015-05-07 23:10:21 +0000503 bool useSoftFloat() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000504 return STI.getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000505 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000506
Toma Tabacud9d344b2015-04-27 14:05:04 +0000507 /// Warn if RegIndex is the same as the current AT.
508 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000509
510 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000511
512 bool isLittle() const { return IsLittleEndian; }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000513};
514}
515
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000516namespace {
517
518/// MipsOperand - Instances of this class represent a parsed Mips machine
519/// instruction.
520class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000521public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000522 /// Broad categories of register classes
523 /// The exact class is finalized by the render method.
524 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000525 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000526 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000527 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000528 RegKind_FCC = 4, /// FCC
529 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
530 RegKind_MSACtrl = 16, /// MSA control registers
531 RegKind_COP2 = 32, /// COP2
532 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
533 /// context).
534 RegKind_CCR = 128, /// CCR
535 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000536 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000537 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000538 /// Potentially any (e.g. $1)
539 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
540 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000541 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000542 };
543
544private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000545 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000546 k_Immediate, /// An immediate (possibly involving symbol references)
547 k_Memory, /// Base + Offset Memory Address
548 k_PhysRegister, /// A physical register from the Mips namespace
549 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000550 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000551 k_RegList, /// A physical register list
552 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000553 } Kind;
554
David Blaikie960ea3f2014-06-08 16:18:35 +0000555public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000556 MipsOperand(KindTy K, MipsAsmParser &Parser)
557 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
558
David Blaikie960ea3f2014-06-08 16:18:35 +0000559private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000560 /// For diagnostics, and checking the assembler temporary
561 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000562
Eric Christopher8996c5d2013-03-15 00:42:55 +0000563 struct Token {
564 const char *Data;
565 unsigned Length;
566 };
567
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000568 struct PhysRegOp {
569 unsigned Num; /// Register Number
570 };
571
572 struct RegIdxOp {
573 unsigned Index; /// Index into the register class
574 RegKind Kind; /// Bitfield of the kinds it could possibly be
575 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000576 };
577
578 struct ImmOp {
579 const MCExpr *Val;
580 };
581
582 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000583 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000584 const MCExpr *Off;
585 };
586
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000587 struct RegListOp {
588 SmallVector<unsigned, 10> *List;
589 };
590
Jack Carterb4dbc172012-09-05 23:34:03 +0000591 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000592 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000593 struct PhysRegOp PhysReg;
594 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000595 struct ImmOp Imm;
596 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000597 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000598 };
599
600 SMLoc StartLoc, EndLoc;
601
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000602 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000603 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
604 const MCRegisterInfo *RegInfo,
605 SMLoc S, SMLoc E,
606 MipsAsmParser &Parser) {
607 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000608 Op->RegIdx.Index = Index;
609 Op->RegIdx.RegInfo = RegInfo;
610 Op->RegIdx.Kind = RegKind;
611 Op->StartLoc = S;
612 Op->EndLoc = E;
613 return Op;
614 }
615
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000616public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000617 /// Coerce the register to GPR32 and return the real register for the current
618 /// target.
619 unsigned getGPR32Reg() const {
620 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000621 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000622 unsigned ClassID = Mips::GPR32RegClassID;
623 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000624 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000625
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000626 /// Coerce the register to GPR32 and return the real register for the current
627 /// target.
628 unsigned getGPRMM16Reg() const {
629 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
630 unsigned ClassID = Mips::GPR32RegClassID;
631 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
632 }
633
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000634 /// Coerce the register to GPR64 and return the real register for the current
635 /// target.
636 unsigned getGPR64Reg() const {
637 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
638 unsigned ClassID = Mips::GPR64RegClassID;
639 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000640 }
641
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000642private:
643 /// Coerce the register to AFGR64 and return the real register for the current
644 /// target.
645 unsigned getAFGR64Reg() const {
646 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
647 if (RegIdx.Index % 2 != 0)
648 AsmParser.Warning(StartLoc, "Float register should be even.");
649 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
650 .getRegister(RegIdx.Index / 2);
651 }
652
653 /// Coerce the register to FGR64 and return the real register for the current
654 /// target.
655 unsigned getFGR64Reg() const {
656 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
657 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
658 .getRegister(RegIdx.Index);
659 }
660
661 /// Coerce the register to FGR32 and return the real register for the current
662 /// target.
663 unsigned getFGR32Reg() const {
664 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
665 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
666 .getRegister(RegIdx.Index);
667 }
668
669 /// Coerce the register to FGRH32 and return the real register for the current
670 /// target.
671 unsigned getFGRH32Reg() const {
672 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
673 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
674 .getRegister(RegIdx.Index);
675 }
676
677 /// Coerce the register to FCC and return the real register for the current
678 /// target.
679 unsigned getFCCReg() const {
680 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
681 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
682 .getRegister(RegIdx.Index);
683 }
684
685 /// Coerce the register to MSA128 and return the real register for the current
686 /// target.
687 unsigned getMSA128Reg() const {
688 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
689 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
690 // identical
691 unsigned ClassID = Mips::MSA128BRegClassID;
692 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
693 }
694
695 /// Coerce the register to MSACtrl and return the real register for the
696 /// current target.
697 unsigned getMSACtrlReg() const {
698 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
699 unsigned ClassID = Mips::MSACtrlRegClassID;
700 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
701 }
702
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000703 /// Coerce the register to COP0 and return the real register for the
704 /// current target.
705 unsigned getCOP0Reg() const {
706 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
707 unsigned ClassID = Mips::COP0RegClassID;
708 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
709 }
710
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000711 /// Coerce the register to COP2 and return the real register for the
712 /// current target.
713 unsigned getCOP2Reg() const {
714 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
715 unsigned ClassID = Mips::COP2RegClassID;
716 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
717 }
718
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000719 /// Coerce the register to COP3 and return the real register for the
720 /// current target.
721 unsigned getCOP3Reg() const {
722 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
723 unsigned ClassID = Mips::COP3RegClassID;
724 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
725 }
726
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000727 /// Coerce the register to ACC64DSP and return the real register for the
728 /// current target.
729 unsigned getACC64DSPReg() const {
730 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
731 unsigned ClassID = Mips::ACC64DSPRegClassID;
732 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
733 }
734
735 /// Coerce the register to HI32DSP and return the real register for the
736 /// current target.
737 unsigned getHI32DSPReg() const {
738 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
739 unsigned ClassID = Mips::HI32DSPRegClassID;
740 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
741 }
742
743 /// Coerce the register to LO32DSP and return the real register for the
744 /// current target.
745 unsigned getLO32DSPReg() const {
746 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
747 unsigned ClassID = Mips::LO32DSPRegClassID;
748 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
749 }
750
751 /// Coerce the register to CCR and return the real register for the
752 /// current target.
753 unsigned getCCRReg() const {
754 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
755 unsigned ClassID = Mips::CCRRegClassID;
756 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
757 }
758
759 /// Coerce the register to HWRegs and return the real register for the
760 /// current target.
761 unsigned getHWRegsReg() const {
762 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
763 unsigned ClassID = Mips::HWRegsRegClassID;
764 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
765 }
766
767public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000768 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000769 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000770 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000771 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000772 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000773 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000774 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000775 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000776 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000777
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000778 void addRegOperands(MCInst &Inst, unsigned N) const {
779 llvm_unreachable("Use a custom parser instead");
780 }
781
Daniel Sanders21bce302014-04-01 12:35:23 +0000782 /// Render the operand to an MCInst as a GPR32
783 /// Asserts if the wrong number of operands are requested, or the operand
784 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000785 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
786 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000787 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000788 }
789
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000790 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
791 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000792 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000793 }
794
Jozef Kolek1904fa22014-11-24 14:25:53 +0000795 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
796 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000797 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000798 }
799
Zoran Jovanovic41688672015-02-10 16:36:20 +0000800 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
801 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000802 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000803 }
804
Daniel Sanders21bce302014-04-01 12:35:23 +0000805 /// Render the operand to an MCInst as a GPR64
806 /// Asserts if the wrong number of operands are requested, or the operand
807 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000808 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
809 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000810 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000811 }
812
813 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
814 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000815 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000816 }
817
818 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
819 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000820 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000821 }
822
823 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
824 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000825 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000826 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000827 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000828 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
829 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000830 }
831
832 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
833 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000834 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000835 }
836
837 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
838 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000839 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000840 }
841
842 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
843 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000844 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000845 }
846
847 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
848 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000849 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000850 }
851
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000852 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
853 assert(N == 1 && "Invalid number of operands!");
854 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
855 }
856
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000857 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
858 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000859 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000860 }
861
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000862 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
863 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000864 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000865 }
866
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000867 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
868 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000869 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000870 }
871
872 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
873 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000874 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000875 }
876
877 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
878 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000879 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000880 }
881
882 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
883 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000884 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000885 }
886
887 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
888 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000889 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000890 }
891
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000892 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000893 assert(N == 1 && "Invalid number of operands!");
894 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000895 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000896 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000897
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000898 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000899 assert(N == 2 && "Invalid number of operands!");
900
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000901 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
902 ? getMemBase()->getGPR64Reg()
903 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000904
905 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000906 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000907 }
908
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000909 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
910 assert(N == 2 && "Invalid number of operands!");
911
Jim Grosbache9119e42015-05-13 18:37:00 +0000912 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000913
914 const MCExpr *Expr = getMemOff();
915 addExpr(Inst, Expr);
916 }
917
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000918 void addRegListOperands(MCInst &Inst, unsigned N) const {
919 assert(N == 1 && "Invalid number of operands!");
920
921 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000922 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000923 }
924
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000925 void addRegPairOperands(MCInst &Inst, unsigned N) const {
926 assert(N == 2 && "Invalid number of operands!");
927 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +0000928 Inst.addOperand(MCOperand::createReg(RegNo++));
929 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000930 }
931
Zoran Jovanovic41688672015-02-10 16:36:20 +0000932 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
933 assert(N == 2 && "Invalid number of operands!");
934 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000935 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000936 }
937
Craig Topper56c590a2014-04-29 07:58:02 +0000938 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000939 // As a special case until we sort out the definition of div/divu, pretend
940 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
941 if (isGPRAsmReg() && RegIdx.Index == 0)
942 return true;
943
944 return Kind == k_PhysRegister;
945 }
946 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000947 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000948 bool isConstantImm() const {
949 return isImm() && dyn_cast<MCConstantExpr>(getImm());
950 }
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +0000951 template <unsigned Bits> bool isUImm() const {
952 return isImm() && isConstantImm() && isUInt<Bits>(getConstantImm());
953 }
Craig Topper56c590a2014-04-29 07:58:02 +0000954 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000955 // Note: It's not possible to pretend that other operand kinds are tokens.
956 // The matcher emitter checks tokens first.
957 return Kind == k_Token;
958 }
Craig Topper56c590a2014-04-29 07:58:02 +0000959 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000960 bool isConstantMemOff() const {
961 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
962 }
963 template <unsigned Bits> bool isMemWithSimmOffset() const {
Zoran Jovanovica6593ff2015-08-18 12:53:08 +0000964 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
965 && getMemBase()->isGPRAsmReg();
966 }
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +0000967 template <unsigned Bits> bool isMemWithSimmOffsetGPR() const {
968 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) &&
969 getMemBase()->isGPRAsmReg();
970 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000971 bool isMemWithGRPMM16Base() const {
972 return isMem() && getMemBase()->isMM16AsmReg();
973 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000974 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
975 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
976 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
977 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000978 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
979 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
980 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
981 && (getMemBase()->getGPR32Reg() == Mips::SP);
982 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000983 bool isRegList16() const {
984 if (!isRegList())
985 return false;
986
987 int Size = RegList.List->size();
988 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
989 RegList.List->back() != Mips::RA)
990 return false;
991
992 int PrevReg = *RegList.List->begin();
993 for (int i = 1; i < Size - 1; i++) {
994 int Reg = (*(RegList.List))[i];
995 if ( Reg != PrevReg + 1)
996 return false;
997 PrevReg = Reg;
998 }
999
1000 return true;
1001 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001002 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001003 bool isLSAImm() const {
1004 if (!isConstantImm())
1005 return false;
1006 int64_t Val = getConstantImm();
1007 return 1 <= Val && Val <= 4;
1008 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001009 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001010 bool isMovePRegPair() const {
1011 if (Kind != k_RegList || RegList.List->size() != 2)
1012 return false;
1013
1014 unsigned R0 = RegList.List->front();
1015 unsigned R1 = RegList.List->back();
1016
1017 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1018 (R0 == Mips::A1 && R1 == Mips::A3) ||
1019 (R0 == Mips::A2 && R1 == Mips::A3) ||
1020 (R0 == Mips::A0 && R1 == Mips::S5) ||
1021 (R0 == Mips::A0 && R1 == Mips::S6) ||
1022 (R0 == Mips::A0 && R1 == Mips::A1) ||
1023 (R0 == Mips::A0 && R1 == Mips::A2) ||
1024 (R0 == Mips::A0 && R1 == Mips::A3))
1025 return true;
1026
1027 return false;
1028 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001029
1030 StringRef getToken() const {
1031 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001032 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001033 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001034 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001035
Craig Topper56c590a2014-04-29 07:58:02 +00001036 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001037 // As a special case until we sort out the definition of div/divu, pretend
1038 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1039 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1040 RegIdx.Kind & RegKind_GPR)
1041 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001042
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001043 assert(Kind == k_PhysRegister && "Invalid access!");
1044 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001045 }
1046
Jack Carterb4dbc172012-09-05 23:34:03 +00001047 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001048 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001049 return Imm.Val;
1050 }
1051
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001052 int64_t getConstantImm() const {
1053 const MCExpr *Val = getImm();
1054 return static_cast<const MCConstantExpr *>(Val)->getValue();
1055 }
1056
1057 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001058 assert((Kind == k_Memory) && "Invalid access!");
1059 return Mem.Base;
1060 }
1061
1062 const MCExpr *getMemOff() const {
1063 assert((Kind == k_Memory) && "Invalid access!");
1064 return Mem.Off;
1065 }
1066
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001067 int64_t getConstantMemOff() const {
1068 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1069 }
1070
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001071 const SmallVectorImpl<unsigned> &getRegList() const {
1072 assert((Kind == k_RegList) && "Invalid access!");
1073 return *(RegList.List);
1074 }
1075
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001076 unsigned getRegPair() const {
1077 assert((Kind == k_RegPair) && "Invalid access!");
1078 return RegIdx.Index;
1079 }
1080
David Blaikie960ea3f2014-06-08 16:18:35 +00001081 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1082 MipsAsmParser &Parser) {
1083 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001084 Op->Tok.Data = Str.data();
1085 Op->Tok.Length = Str.size();
1086 Op->StartLoc = S;
1087 Op->EndLoc = S;
1088 return Op;
1089 }
1090
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001091 /// Create a numeric register (e.g. $1). The exact register remains
1092 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001093 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001094 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001095 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001096 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001097 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001098 }
1099
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001100 /// Create a register that is definitely a GPR.
1101 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001102 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001103 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001104 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001105 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001106 }
1107
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001108 /// Create a register that is definitely a FGR.
1109 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001110 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001111 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001112 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001113 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1114 }
1115
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001116 /// Create a register that is definitely a HWReg.
1117 /// This is typically only used for named registers such as $hwr_cpunum.
1118 static std::unique_ptr<MipsOperand>
1119 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1120 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1121 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1122 }
1123
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001124 /// Create a register that is definitely an FCC.
1125 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001126 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001127 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001128 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001129 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1130 }
1131
1132 /// Create a register that is definitely an ACC.
1133 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001134 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001135 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001136 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001137 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1138 }
1139
1140 /// Create a register that is definitely an MSA128.
1141 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001142 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001143 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001144 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001145 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1146 }
1147
1148 /// Create a register that is definitely an MSACtrl.
1149 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001150 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001151 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001152 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001153 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1154 }
1155
David Blaikie960ea3f2014-06-08 16:18:35 +00001156 static std::unique_ptr<MipsOperand>
1157 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1158 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001159 Op->Imm.Val = Val;
1160 Op->StartLoc = S;
1161 Op->EndLoc = E;
1162 return Op;
1163 }
1164
David Blaikie960ea3f2014-06-08 16:18:35 +00001165 static std::unique_ptr<MipsOperand>
1166 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1167 SMLoc E, MipsAsmParser &Parser) {
1168 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1169 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001170 Op->Mem.Off = Off;
1171 Op->StartLoc = S;
1172 Op->EndLoc = E;
1173 return Op;
1174 }
1175
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001176 static std::unique_ptr<MipsOperand>
1177 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1178 MipsAsmParser &Parser) {
1179 assert (Regs.size() > 0 && "Empty list not allowed");
1180
1181 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001182 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001183 Op->StartLoc = StartLoc;
1184 Op->EndLoc = EndLoc;
1185 return Op;
1186 }
1187
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001188 static std::unique_ptr<MipsOperand>
1189 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1190 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1191 Op->RegIdx.Index = RegNo;
1192 Op->StartLoc = S;
1193 Op->EndLoc = E;
1194 return Op;
1195 }
1196
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001197 bool isGPRAsmReg() const {
1198 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001199 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001200 bool isMM16AsmReg() const {
1201 if (!(isRegIdx() && RegIdx.Kind))
1202 return false;
1203 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1204 || RegIdx.Index == 16 || RegIdx.Index == 17);
1205 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001206 bool isMM16AsmRegZero() const {
1207 if (!(isRegIdx() && RegIdx.Kind))
1208 return false;
1209 return (RegIdx.Index == 0 ||
1210 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1211 RegIdx.Index == 17);
1212 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001213 bool isMM16AsmRegMoveP() const {
1214 if (!(isRegIdx() && RegIdx.Kind))
1215 return false;
1216 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1217 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1218 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001219 bool isFGRAsmReg() const {
1220 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1221 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001222 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001223 bool isHWRegsAsmReg() const {
1224 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001225 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001226 bool isCCRAsmReg() const {
1227 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001228 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001229 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001230 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1231 return false;
1232 if (!AsmParser.hasEightFccRegisters())
1233 return RegIdx.Index == 0;
1234 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001235 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001236 bool isACCAsmReg() const {
1237 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001238 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001239 bool isCOP0AsmReg() const {
1240 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1241 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001242 bool isCOP2AsmReg() const {
1243 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001244 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001245 bool isCOP3AsmReg() const {
1246 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1247 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001248 bool isMSA128AsmReg() const {
1249 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001250 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001251 bool isMSACtrlAsmReg() const {
1252 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001253 }
1254
Jack Carterb4dbc172012-09-05 23:34:03 +00001255 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001256 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001257 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001258 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001259
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001260 virtual ~MipsOperand() {
1261 switch (Kind) {
1262 case k_Immediate:
1263 break;
1264 case k_Memory:
1265 delete Mem.Base;
1266 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001267 case k_RegList:
1268 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001269 case k_PhysRegister:
1270 case k_RegisterIndex:
1271 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001272 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001273 break;
1274 }
1275 }
1276
Craig Topper56c590a2014-04-29 07:58:02 +00001277 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001278 switch (Kind) {
1279 case k_Immediate:
1280 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001281 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001282 OS << ">";
1283 break;
1284 case k_Memory:
1285 OS << "Mem<";
1286 Mem.Base->print(OS);
1287 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001288 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001289 OS << ">";
1290 break;
1291 case k_PhysRegister:
1292 OS << "PhysReg<" << PhysReg.Num << ">";
1293 break;
1294 case k_RegisterIndex:
1295 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1296 break;
1297 case k_Token:
1298 OS << Tok.Data;
1299 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001300 case k_RegList:
1301 OS << "RegList< ";
1302 for (auto Reg : (*RegList.List))
1303 OS << Reg << " ";
1304 OS << ">";
1305 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001306 case k_RegPair:
1307 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1308 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001309 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001310 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001311}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001312} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001313
Jack Carter9e65aa32013-03-22 00:05:30 +00001314namespace llvm {
1315extern const MCInstrDesc MipsInsts[];
1316}
1317static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1318 return MipsInsts[Opcode];
1319}
1320
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001321static bool hasShortDelaySlot(unsigned Opcode) {
1322 switch (Opcode) {
1323 case Mips::JALS_MM:
1324 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001325 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001326 case Mips::BGEZALS_MM:
1327 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001328 return true;
1329 default:
1330 return false;
1331 }
1332}
1333
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001334static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1335 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1336 return &SRExpr->getSymbol();
1337 }
1338
1339 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1340 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1341 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1342
1343 if (LHSSym)
1344 return LHSSym;
1345
1346 if (RHSSym)
1347 return RHSSym;
1348
1349 return nullptr;
1350 }
1351
1352 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1353 return getSingleMCSymbol(UExpr->getSubExpr());
1354
1355 return nullptr;
1356}
1357
1358static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1359 if (isa<MCSymbolRefExpr>(Expr))
1360 return 1;
1361
1362 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1363 return countMCSymbolRefExpr(BExpr->getLHS()) +
1364 countMCSymbolRefExpr(BExpr->getRHS());
1365
1366 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1367 return countMCSymbolRefExpr(UExpr->getSubExpr());
1368
1369 return 0;
1370}
1371
Jack Carter9e65aa32013-03-22 00:05:30 +00001372bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001373 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001374 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001375 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001376
Jack Carter9e65aa32013-03-22 00:05:30 +00001377 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001378
1379 if (MCID.isBranch() || MCID.isCall()) {
1380 const unsigned Opcode = Inst.getOpcode();
1381 MCOperand Offset;
1382
1383 switch (Opcode) {
1384 default:
1385 break;
Kai Nackee0245392015-01-27 19:11:28 +00001386 case Mips::BBIT0:
1387 case Mips::BBIT032:
1388 case Mips::BBIT1:
1389 case Mips::BBIT132:
1390 assert(hasCnMips() && "instruction only valid for octeon cpus");
1391 // Fall through
1392
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001393 case Mips::BEQ:
1394 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001395 case Mips::BEQ_MM:
1396 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001397 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001398 Offset = Inst.getOperand(2);
1399 if (!Offset.isImm())
1400 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001401 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001402 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001403 if (OffsetToAlignment(Offset.getImm(),
1404 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001405 return Error(IDLoc, "branch to misaligned address");
1406 break;
1407 case Mips::BGEZ:
1408 case Mips::BGTZ:
1409 case Mips::BLEZ:
1410 case Mips::BLTZ:
1411 case Mips::BGEZAL:
1412 case Mips::BLTZAL:
1413 case Mips::BC1F:
1414 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001415 case Mips::BGEZ_MM:
1416 case Mips::BGTZ_MM:
1417 case Mips::BLEZ_MM:
1418 case Mips::BLTZ_MM:
1419 case Mips::BGEZAL_MM:
1420 case Mips::BLTZAL_MM:
1421 case Mips::BC1F_MM:
1422 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001423 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001424 Offset = Inst.getOperand(1);
1425 if (!Offset.isImm())
1426 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001427 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001428 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001429 if (OffsetToAlignment(Offset.getImm(),
1430 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001431 return Error(IDLoc, "branch to misaligned address");
1432 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001433 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001434 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001435 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001436 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001437 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1438 Offset = Inst.getOperand(1);
1439 if (!Offset.isImm())
1440 break; // We'll deal with this situation later on when applying fixups.
1441 if (!isIntN(8, Offset.getImm()))
1442 return Error(IDLoc, "branch target out of range");
1443 if (OffsetToAlignment(Offset.getImm(), 2LL))
1444 return Error(IDLoc, "branch to misaligned address");
1445 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001446 }
1447 }
1448
Daniel Sandersa84989a2014-06-16 13:25:35 +00001449 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1450 // We still accept it but it is a normal nop.
1451 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1452 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1453 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1454 "nop instruction");
1455 }
1456
Kai Nackee0245392015-01-27 19:11:28 +00001457 if (hasCnMips()) {
1458 const unsigned Opcode = Inst.getOpcode();
1459 MCOperand Opnd;
1460 int Imm;
1461
1462 switch (Opcode) {
1463 default:
1464 break;
1465
1466 case Mips::BBIT0:
1467 case Mips::BBIT032:
1468 case Mips::BBIT1:
1469 case Mips::BBIT132:
1470 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1471 // The offset is handled above
1472 Opnd = Inst.getOperand(1);
1473 if (!Opnd.isImm())
1474 return Error(IDLoc, "expected immediate operand kind");
1475 Imm = Opnd.getImm();
1476 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1477 Opcode == Mips::BBIT1 ? 63 : 31))
1478 return Error(IDLoc, "immediate operand value out of range");
1479 if (Imm > 31) {
1480 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1481 : Mips::BBIT132);
1482 Inst.getOperand(1).setImm(Imm - 32);
1483 }
1484 break;
1485
1486 case Mips::CINS:
1487 case Mips::CINS32:
1488 case Mips::EXTS:
1489 case Mips::EXTS32:
1490 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1491 // Check length
1492 Opnd = Inst.getOperand(3);
1493 if (!Opnd.isImm())
1494 return Error(IDLoc, "expected immediate operand kind");
1495 Imm = Opnd.getImm();
1496 if (Imm < 0 || Imm > 31)
1497 return Error(IDLoc, "immediate operand value out of range");
1498 // Check position
1499 Opnd = Inst.getOperand(2);
1500 if (!Opnd.isImm())
1501 return Error(IDLoc, "expected immediate operand kind");
1502 Imm = Opnd.getImm();
1503 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1504 Opcode == Mips::EXTS ? 63 : 31))
1505 return Error(IDLoc, "immediate operand value out of range");
1506 if (Imm > 31) {
1507 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1508 Inst.getOperand(2).setImm(Imm - 32);
1509 }
1510 break;
1511
1512 case Mips::SEQi:
1513 case Mips::SNEi:
1514 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1515 Opnd = Inst.getOperand(2);
1516 if (!Opnd.isImm())
1517 return Error(IDLoc, "expected immediate operand kind");
1518 Imm = Opnd.getImm();
1519 if (!isInt<10>(Imm))
1520 return Error(IDLoc, "immediate operand value out of range");
1521 break;
1522 }
1523 }
1524
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001525 // This expansion is not in a function called by expandInstruction() because
1526 // the pseudo-instruction doesn't have a distinct opcode.
1527 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1528 inPicMode()) {
1529 warnIfNoMacro(IDLoc);
1530
1531 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1532
1533 // We can do this expansion if there's only 1 symbol in the argument
1534 // expression.
1535 if (countMCSymbolRefExpr(JalExpr) > 1)
1536 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1537
1538 // FIXME: This is checking the expression can be handled by the later stages
1539 // of the assembler. We ought to leave it to those later stages but
1540 // we can't do that until we stop evaluateRelocExpr() rewriting the
1541 // expressions into non-equivalent forms.
1542 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1543
1544 // FIXME: Add support for label+offset operands (currently causes an error).
1545 // FIXME: Add support for forward-declared local symbols.
1546 // FIXME: Add expansion for when the LargeGOT option is enabled.
1547 if (JalSym->isInSection() || JalSym->isTemporary()) {
1548 if (isABI_O32()) {
1549 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001550 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001551 // R_(MICRO)MIPS_GOT16 label
1552 // addiu $25, $25, 0
1553 // R_(MICRO)MIPS_LO16 label
1554 // jalr $25
1555 const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
1556 const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
1557
1558 MCInst LwInst;
1559 LwInst.setOpcode(Mips::LW);
1560 LwInst.addOperand(MCOperand::createReg(Mips::T9));
1561 LwInst.addOperand(MCOperand::createReg(Mips::GP));
1562 LwInst.addOperand(MCOperand::createExpr(Got16RelocExpr));
1563 Instructions.push_back(LwInst);
1564
1565 MCInst AddiuInst;
1566 AddiuInst.setOpcode(Mips::ADDiu);
1567 AddiuInst.addOperand(MCOperand::createReg(Mips::T9));
1568 AddiuInst.addOperand(MCOperand::createReg(Mips::T9));
1569 AddiuInst.addOperand(MCOperand::createExpr(Lo16RelocExpr));
1570 Instructions.push_back(AddiuInst);
1571 } else if (isABI_N32() || isABI_N64()) {
1572 // If it's a local symbol and the N32/N64 ABIs are being used,
1573 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001574 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001575 // R_(MICRO)MIPS_GOT_DISP label
1576 // jalr $25
1577 const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
1578
1579 MCInst LoadInst;
1580 LoadInst.setOpcode(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW);
1581 LoadInst.addOperand(MCOperand::createReg(Mips::T9));
1582 LoadInst.addOperand(MCOperand::createReg(Mips::GP));
1583 LoadInst.addOperand(MCOperand::createExpr(GotDispRelocExpr));
1584 Instructions.push_back(LoadInst);
1585 }
1586 } else {
1587 // If it's an external/weak symbol, we expand to:
1588 // lw/ld $25, 0($gp)
1589 // R_(MICRO)MIPS_CALL16 label
1590 // jalr $25
1591 const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
1592
1593 MCInst LoadInst;
1594 LoadInst.setOpcode(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW);
1595 LoadInst.addOperand(MCOperand::createReg(Mips::T9));
1596 LoadInst.addOperand(MCOperand::createReg(Mips::GP));
1597 LoadInst.addOperand(MCOperand::createExpr(Call16RelocExpr));
1598 Instructions.push_back(LoadInst);
1599 }
1600
1601 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001602 if (IsCpRestoreSet && inMicroMipsMode())
1603 JalrInst.setOpcode(Mips::JALRS_MM);
1604 else
1605 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001606 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1607 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1608
1609 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1610 // This relocation is supposed to be an optimization hint for the linker
1611 // and is not necessary for correctness.
1612
1613 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001614 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001615 }
1616
Jack Carter9e65aa32013-03-22 00:05:30 +00001617 if (MCID.mayLoad() || MCID.mayStore()) {
1618 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001619 // reference or immediate we may have to expand instructions.
1620 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001621 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001622 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1623 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001624 MCOperand &Op = Inst.getOperand(i);
1625 if (Op.isImm()) {
1626 int MemOffset = Op.getImm();
1627 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001628 // Offset can't exceed 16bit value.
1629 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001630 return false;
1631 }
1632 } else if (Op.isExpr()) {
1633 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001634 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001635 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001636 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001637 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001638 // Expand symbol.
1639 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001640 return false;
1641 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001642 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001643 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001644 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001645 }
1646 }
1647 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001648 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001649 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001650
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001651 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001652 if (MCID.mayLoad()) {
1653 // Try to create 16-bit GP relative load instruction.
1654 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1655 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1656 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1657 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1658 MCOperand &Op = Inst.getOperand(i);
1659 if (Op.isImm()) {
1660 int MemOffset = Op.getImm();
1661 MCOperand &DstReg = Inst.getOperand(0);
1662 MCOperand &BaseReg = Inst.getOperand(1);
1663 if (isIntN(9, MemOffset) && (MemOffset % 4 == 0) &&
1664 getContext().getRegisterInfo()->getRegClass(
1665 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001666 (BaseReg.getReg() == Mips::GP ||
1667 BaseReg.getReg() == Mips::GP_64)) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001668 MCInst TmpInst;
1669 TmpInst.setLoc(IDLoc);
1670 TmpInst.setOpcode(Mips::LWGP_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00001671 TmpInst.addOperand(MCOperand::createReg(DstReg.getReg()));
1672 TmpInst.addOperand(MCOperand::createReg(Mips::GP));
1673 TmpInst.addOperand(MCOperand::createImm(MemOffset));
Jozef Koleke10a02e2015-01-28 17:27:26 +00001674 Instructions.push_back(TmpInst);
1675 return false;
1676 }
1677 }
1678 }
1679 } // for
1680 } // if load
1681
1682 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1683
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001684 MCOperand Opnd;
1685 int Imm;
1686
1687 switch (Inst.getOpcode()) {
1688 default:
1689 break;
1690 case Mips::ADDIUS5_MM:
1691 Opnd = Inst.getOperand(2);
1692 if (!Opnd.isImm())
1693 return Error(IDLoc, "expected immediate operand kind");
1694 Imm = Opnd.getImm();
1695 if (Imm < -8 || Imm > 7)
1696 return Error(IDLoc, "immediate operand value out of range");
1697 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001698 case Mips::ADDIUSP_MM:
1699 Opnd = Inst.getOperand(0);
1700 if (!Opnd.isImm())
1701 return Error(IDLoc, "expected immediate operand kind");
1702 Imm = Opnd.getImm();
1703 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1704 Imm % 4 != 0)
1705 return Error(IDLoc, "immediate operand value out of range");
1706 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001707 case Mips::SLL16_MM:
1708 case Mips::SRL16_MM:
1709 Opnd = Inst.getOperand(2);
1710 if (!Opnd.isImm())
1711 return Error(IDLoc, "expected immediate operand kind");
1712 Imm = Opnd.getImm();
1713 if (Imm < 1 || Imm > 8)
1714 return Error(IDLoc, "immediate operand value out of range");
1715 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001716 case Mips::LI16_MM:
1717 Opnd = Inst.getOperand(1);
1718 if (!Opnd.isImm())
1719 return Error(IDLoc, "expected immediate operand kind");
1720 Imm = Opnd.getImm();
1721 if (Imm < -1 || Imm > 126)
1722 return Error(IDLoc, "immediate operand value out of range");
1723 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001724 case Mips::ADDIUR2_MM:
1725 Opnd = Inst.getOperand(2);
1726 if (!Opnd.isImm())
1727 return Error(IDLoc, "expected immediate operand kind");
1728 Imm = Opnd.getImm();
1729 if (!(Imm == 1 || Imm == -1 ||
1730 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1731 return Error(IDLoc, "immediate operand value out of range");
1732 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001733 case Mips::ADDIUR1SP_MM:
1734 Opnd = Inst.getOperand(1);
1735 if (!Opnd.isImm())
1736 return Error(IDLoc, "expected immediate operand kind");
1737 Imm = Opnd.getImm();
1738 if (OffsetToAlignment(Imm, 4LL))
1739 return Error(IDLoc, "misaligned immediate operand value");
1740 if (Imm < 0 || Imm > 255)
1741 return Error(IDLoc, "immediate operand value out of range");
1742 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001743 case Mips::ANDI16_MM:
1744 Opnd = Inst.getOperand(2);
1745 if (!Opnd.isImm())
1746 return Error(IDLoc, "expected immediate operand kind");
1747 Imm = Opnd.getImm();
1748 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1749 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1750 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1751 return Error(IDLoc, "immediate operand value out of range");
1752 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001753 case Mips::LBU16_MM:
1754 Opnd = Inst.getOperand(2);
1755 if (!Opnd.isImm())
1756 return Error(IDLoc, "expected immediate operand kind");
1757 Imm = Opnd.getImm();
1758 if (Imm < -1 || Imm > 14)
1759 return Error(IDLoc, "immediate operand value out of range");
1760 break;
Zoran Jovanovic7ba636c2015-09-17 10:14:09 +00001761 case Mips::TEQ_MM:
1762 case Mips::TGE_MM:
1763 case Mips::TGEU_MM:
1764 case Mips::TLT_MM:
1765 case Mips::TLTU_MM:
1766 case Mips::TNE_MM:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001767 case Mips::SB16_MM:
1768 Opnd = Inst.getOperand(2);
1769 if (!Opnd.isImm())
1770 return Error(IDLoc, "expected immediate operand kind");
1771 Imm = Opnd.getImm();
1772 if (Imm < 0 || Imm > 15)
1773 return Error(IDLoc, "immediate operand value out of range");
1774 break;
1775 case Mips::LHU16_MM:
1776 case Mips::SH16_MM:
1777 Opnd = Inst.getOperand(2);
1778 if (!Opnd.isImm())
1779 return Error(IDLoc, "expected immediate operand kind");
1780 Imm = Opnd.getImm();
1781 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1782 return Error(IDLoc, "immediate operand value out of range");
1783 break;
1784 case Mips::LW16_MM:
1785 case Mips::SW16_MM:
1786 Opnd = Inst.getOperand(2);
1787 if (!Opnd.isImm())
1788 return Error(IDLoc, "expected immediate operand kind");
1789 Imm = Opnd.getImm();
1790 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1791 return Error(IDLoc, "immediate operand value out of range");
1792 break;
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +00001793 case Mips::PREFX_MM:
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001794 case Mips::CACHE:
1795 case Mips::PREF:
1796 Opnd = Inst.getOperand(2);
1797 if (!Opnd.isImm())
1798 return Error(IDLoc, "expected immediate operand kind");
1799 Imm = Opnd.getImm();
1800 if (!isUInt<5>(Imm))
1801 return Error(IDLoc, "immediate operand value out of range");
1802 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001803 case Mips::ADDIUPC_MM:
1804 MCOperand Opnd = Inst.getOperand(1);
1805 if (!Opnd.isImm())
1806 return Error(IDLoc, "expected immediate operand kind");
1807 int Imm = Opnd.getImm();
1808 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1809 return Error(IDLoc, "immediate operand value out of range");
1810 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001811 }
1812 }
1813
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001814 if (needsExpansion(Inst)) {
1815 if (expandInstruction(Inst, IDLoc, Instructions))
1816 return true;
1817 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001818 Instructions.push_back(Inst);
1819
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001820 // If this instruction has a delay slot and .set reorder is active,
1821 // emit a NOP after it.
1822 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1823 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1824
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001825 if ((Inst.getOpcode() == Mips::JalOneReg ||
1826 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
1827 isPicAndNotNxxAbi()) {
1828 if (IsCpRestoreSet) {
1829 // We need a NOP between the JALR and the LW:
1830 // If .set reorder has been used, we've already emitted a NOP.
1831 // If .set noreorder has been used, we need to emit a NOP at this point.
1832 if (!AssemblerOptions.back()->isReorder())
1833 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1834
1835 // Load the $gp from the stack.
1836 SmallVector<MCInst, 3> LoadInsts;
1837 createCpRestoreMemOp(true /*IsLoad*/, CpRestoreOffset /*StackOffset*/,
1838 IDLoc, LoadInsts);
1839
1840 for (const MCInst &Inst : LoadInsts)
1841 Instructions.push_back(Inst);
1842
1843 } else
1844 Warning(IDLoc, "no .cprestore used in PIC mode");
1845 }
1846
Jack Carter9e65aa32013-03-22 00:05:30 +00001847 return false;
1848}
1849
Jack Carter30a59822012-10-04 04:03:53 +00001850bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1851
Jack Carterd0bd6422013-04-18 00:41:53 +00001852 switch (Inst.getOpcode()) {
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001853 case Mips::LoadImm32:
1854 case Mips::LoadImm64:
1855 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001856 case Mips::LoadAddrImm64:
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001857 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001858 case Mips::LoadAddrReg64:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001859 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001860 case Mips::B_MMR6_Pseudo:
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001861 case Mips::LWM_MM:
1862 case Mips::SWM_MM:
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001863 case Mips::JalOneReg:
1864 case Mips::JalTwoReg:
Toma Tabacue1e460d2015-06-11 10:36:10 +00001865 case Mips::BneImm:
1866 case Mips::BeqImm:
Toma Tabacu1a108322015-06-17 13:20:24 +00001867 case Mips::BLT:
1868 case Mips::BLE:
1869 case Mips::BGE:
1870 case Mips::BGT:
1871 case Mips::BLTU:
1872 case Mips::BLEU:
1873 case Mips::BGEU:
1874 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00001875 case Mips::BLTL:
1876 case Mips::BLEL:
1877 case Mips::BGEL:
1878 case Mips::BGTL:
1879 case Mips::BLTUL:
1880 case Mips::BLEUL:
1881 case Mips::BGEUL:
1882 case Mips::BGTUL:
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00001883 case Mips::SDivMacro:
1884 case Mips::UDivMacro:
1885 case Mips::DSDivMacro:
1886 case Mips::DUDivMacro:
Toma Tabacud88d79c2015-06-23 14:39:42 +00001887 case Mips::Ulhu:
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00001888 case Mips::Ulw:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00001889 case Mips::NORImm:
Jack Carterd0bd6422013-04-18 00:41:53 +00001890 return true;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00001891 case Mips::ADDi:
1892 case Mips::ADDiu:
1893 case Mips::SLTi:
1894 case Mips::SLTiu:
1895 if ((Inst.getNumOperands() == 3) &&
1896 Inst.getOperand(0).isReg() &&
1897 Inst.getOperand(1).isReg() &&
1898 Inst.getOperand(2).isImm()) {
1899 int64_t ImmValue = Inst.getOperand(2).getImm();
1900 return !isInt<16>(ImmValue);
1901 }
1902 return false;
1903 case Mips::ANDi:
1904 case Mips::ORi:
1905 case Mips::XORi:
1906 if ((Inst.getNumOperands() == 3) &&
1907 Inst.getOperand(0).isReg() &&
1908 Inst.getOperand(1).isReg() &&
1909 Inst.getOperand(2).isImm()) {
1910 int64_t ImmValue = Inst.getOperand(2).getImm();
1911 return !isUInt<16>(ImmValue);
1912 }
1913 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001914 default:
1915 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001916 }
1917}
Jack Carter92995f12012-10-06 00:53:28 +00001918
Matheus Almeida3813d572014-06-19 14:39:14 +00001919bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001920 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001921 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001922 default: llvm_unreachable("unimplemented expansion");
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001923 case Mips::LoadImm32:
Toma Tabacu00e98672015-05-01 12:19:27 +00001924 return expandLoadImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001925 case Mips::LoadImm64:
Toma Tabacu00e98672015-05-01 12:19:27 +00001926 return expandLoadImm(Inst, false, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001927 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001928 case Mips::LoadAddrImm64:
1929 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1930 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1931 "expected immediate operand kind");
1932
1933 return expandLoadAddress(
1934 Inst.getOperand(0).getReg(), Mips::NoRegister, Inst.getOperand(1),
1935 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001936 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001937 case Mips::LoadAddrReg64:
1938 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1939 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1940 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
1941 "expected immediate operand kind");
1942
1943 return expandLoadAddress(
1944 Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(), Inst.getOperand(2),
1945 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001946 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001947 case Mips::B_MMR6_Pseudo:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001948 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001949 case Mips::SWM_MM:
1950 case Mips::LWM_MM:
1951 return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001952 case Mips::JalOneReg:
1953 case Mips::JalTwoReg:
1954 return expandJalWithRegs(Inst, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00001955 case Mips::BneImm:
1956 case Mips::BeqImm:
1957 return expandBranchImm(Inst, IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00001958 case Mips::BLT:
1959 case Mips::BLE:
1960 case Mips::BGE:
1961 case Mips::BGT:
1962 case Mips::BLTU:
1963 case Mips::BLEU:
1964 case Mips::BGEU:
1965 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00001966 case Mips::BLTL:
1967 case Mips::BLEL:
1968 case Mips::BGEL:
1969 case Mips::BGTL:
1970 case Mips::BLTUL:
1971 case Mips::BLEUL:
1972 case Mips::BGEUL:
1973 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00001974 return expandCondBranches(Inst, IDLoc, Instructions);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00001975 case Mips::SDivMacro:
1976 return expandDiv(Inst, IDLoc, Instructions, false, true);
1977 case Mips::DSDivMacro:
1978 return expandDiv(Inst, IDLoc, Instructions, true, true);
1979 case Mips::UDivMacro:
1980 return expandDiv(Inst, IDLoc, Instructions, false, false);
1981 case Mips::DUDivMacro:
1982 return expandDiv(Inst, IDLoc, Instructions, true, false);
Toma Tabacud88d79c2015-06-23 14:39:42 +00001983 case Mips::Ulhu:
1984 return expandUlhu(Inst, IDLoc, Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00001985 case Mips::Ulw:
1986 return expandUlw(Inst, IDLoc, Instructions);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00001987 case Mips::ADDi:
1988 case Mips::ADDiu:
1989 case Mips::ANDi:
1990 case Mips::NORImm:
1991 case Mips::ORi:
1992 case Mips::SLTi:
1993 case Mips::SLTiu:
1994 case Mips::XORi:
1995 return expandAliasImmediate(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001996 }
Jack Carter30a59822012-10-04 04:03:53 +00001997}
Jack Carter92995f12012-10-06 00:53:28 +00001998
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001999namespace {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002000void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc,
Daniel Sanders03f9c012015-07-14 12:24:22 +00002001 SmallVectorImpl<MCInst> &Instructions) {
2002 MCInst tmpInst;
2003 tmpInst.setOpcode(Opcode);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002004 tmpInst.addOperand(MCOperand::createReg(Reg0));
2005 tmpInst.addOperand(Op1);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002006 tmpInst.setLoc(IDLoc);
2007 Instructions.push_back(tmpInst);
2008}
2009
Daniel Sandersf1ae3672015-08-18 09:55:57 +00002010void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc,
Daniel Sanders03f9c012015-07-14 12:24:22 +00002011 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002012 emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002013}
2014
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002015void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc,
2016 SmallVectorImpl<MCInst> &Instructions) {
2017 emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, Instructions);
2018}
2019
2020void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc,
2021 SmallVectorImpl<MCInst> &Instructions) {
2022 MCInst tmpInst;
2023 tmpInst.setOpcode(Opcode);
2024 tmpInst.addOperand(MCOperand::createImm(Imm1));
2025 tmpInst.addOperand(MCOperand::createImm(Imm2));
2026 tmpInst.setLoc(IDLoc);
2027 Instructions.push_back(tmpInst);
2028}
2029
2030void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
2031 SmallVectorImpl<MCInst> &Instructions) {
2032 MCInst tmpInst;
2033 tmpInst.setOpcode(Opcode);
2034 tmpInst.addOperand(MCOperand::createReg(Reg0));
2035 tmpInst.setLoc(IDLoc);
2036 Instructions.push_back(tmpInst);
2037}
2038
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002039void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2,
Daniel Sanders03f9c012015-07-14 12:24:22 +00002040 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
2041 MCInst tmpInst;
2042 tmpInst.setOpcode(Opcode);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002043 tmpInst.addOperand(MCOperand::createReg(Reg0));
2044 tmpInst.addOperand(MCOperand::createReg(Reg1));
2045 tmpInst.addOperand(Op2);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002046 tmpInst.setLoc(IDLoc);
2047 Instructions.push_back(tmpInst);
2048}
2049
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002050void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
Daniel Sanders03f9c012015-07-14 12:24:22 +00002051 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002052 emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc,
Daniel Sanders03f9c012015-07-14 12:24:22 +00002053 Instructions);
2054}
2055
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002056void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
2057 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
2058 emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc,
2059 Instructions);
2060}
Daniel Sanders03f9c012015-07-14 12:24:22 +00002061
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002062void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount,
2063 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
2064 if (ShiftAmount >= 32) {
2065 emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc,
2066 Instructions);
Toma Tabacu7dea2e32015-04-28 14:06:35 +00002067 return;
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002068 }
Toma Tabacu7dea2e32015-04-28 14:06:35 +00002069
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002070 emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00002071}
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002072} // end anonymous namespace.
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00002073
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002074bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
2075 SmallVectorImpl<MCInst> &Instructions) {
2076 // Create a JALR instruction which is going to replace the pseudo-JAL.
2077 MCInst JalrInst;
2078 JalrInst.setLoc(IDLoc);
2079 const MCOperand FirstRegOp = Inst.getOperand(0);
2080 const unsigned Opcode = Inst.getOpcode();
2081
2082 if (Opcode == Mips::JalOneReg) {
2083 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002084 if (IsCpRestoreSet && inMicroMipsMode()) {
2085 JalrInst.setOpcode(Mips::JALRS16_MM);
2086 JalrInst.addOperand(FirstRegOp);
2087 } else if (inMicroMipsMode()) {
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002088 JalrInst.setOpcode(Mips::JALR16_MM);
2089 JalrInst.addOperand(FirstRegOp);
2090 } else {
2091 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002092 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002093 JalrInst.addOperand(FirstRegOp);
2094 }
2095 } else if (Opcode == Mips::JalTwoReg) {
2096 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002097 if (IsCpRestoreSet && inMicroMipsMode())
2098 JalrInst.setOpcode(Mips::JALRS_MM);
2099 else
2100 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002101 JalrInst.addOperand(FirstRegOp);
2102 const MCOperand SecondRegOp = Inst.getOperand(1);
2103 JalrInst.addOperand(SecondRegOp);
2104 }
2105 Instructions.push_back(JalrInst);
2106
2107 // If .set reorder is active, emit a NOP after it.
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002108 if (AssemblerOptions.back()->isReorder())
2109 createNop(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002110
2111 return false;
2112}
2113
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002114/// Can the value be represented by a unsigned N-bit value and a shift left?
2115template<unsigned N>
2116bool isShiftedUIntAtAnyPosition(uint64_t x) {
2117 unsigned BitNum = findFirstSet(x);
2118
2119 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2120}
2121
2122/// Load (or add) an immediate into a register.
2123///
2124/// @param ImmValue The immediate to load.
2125/// @param DstReg The register that will hold the immediate.
2126/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2127/// for a simple initialization.
2128/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2129/// @param IsAddress True if the immediate represents an address. False if it
2130/// is an integer.
2131/// @param IDLoc Location of the immediate in the source file.
2132/// @param Instructions The instructions emitted by this expansion.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002133bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002134 unsigned SrcReg, bool Is32BitImm,
2135 bool IsAddress, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00002136 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00002137 if (!Is32BitImm && !isGP64bit()) {
2138 Error(IDLoc, "instruction requires a 64-bit architecture");
2139 return true;
2140 }
2141
Daniel Sanders03f9c012015-07-14 12:24:22 +00002142 if (Is32BitImm) {
2143 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2144 // Sign extend up to 64-bit so that the predicates match the hardware
2145 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2146 // true.
2147 ImmValue = SignExtend64<32>(ImmValue);
2148 } else {
2149 Error(IDLoc, "instruction requires a 32-bit immediate");
2150 return true;
2151 }
2152 }
2153
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002154 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2155 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2156
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002157 bool UseSrcReg = false;
2158 if (SrcReg != Mips::NoRegister)
2159 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002160
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002161 unsigned TmpReg = DstReg;
2162 if (UseSrcReg && (DstReg == SrcReg)) {
2163 // At this point we need AT to perform the expansions and we exit if it is
2164 // not available.
2165 unsigned ATReg = getATReg(IDLoc);
2166 if (!ATReg)
2167 return true;
2168 TmpReg = ATReg;
2169 }
2170
Daniel Sanders03f9c012015-07-14 12:24:22 +00002171 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002172 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002173 SrcReg = ZeroReg;
2174
2175 // This doesn't quite follow the usual ABI expectations for N32 but matches
2176 // traditional assembler behaviour. N32 would normally use addiu for both
2177 // integers and addresses.
2178 if (IsAddress && !Is32BitImm) {
2179 emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2180 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002181 }
2182
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002183 emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2184 return false;
2185 }
2186
2187 if (isUInt<16>(ImmValue)) {
2188 unsigned TmpReg = DstReg;
2189 if (SrcReg == DstReg) {
2190 TmpReg = getATReg(IDLoc);
2191 if (!TmpReg)
2192 return true;
2193 }
2194
2195 emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002196 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002197 emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2198 return false;
2199 }
2200
2201 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002202 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002203
Toma Tabacu79588102015-04-29 10:19:56 +00002204 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2205 uint16_t Bits15To0 = ImmValue & 0xffff;
2206
Toma Tabacua3d056f2015-05-15 09:42:11 +00002207 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002208 // Traditional behaviour seems to special case this particular value. It's
2209 // not clear why other masks are handled differently.
2210 if (ImmValue == 0xffffffff) {
Daniel Sandersf1ae3672015-08-18 09:55:57 +00002211 emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002212 emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, Instructions);
2213 if (UseSrcReg)
2214 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2215 return false;
2216 }
2217
2218 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002219 // upper 32 bits.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002220 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002221 emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002222 if (Bits15To0)
2223 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
2224 if (UseSrcReg)
2225 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2226 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002227 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002228
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002229 emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions);
2230 if (Bits15To0)
2231 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002232 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002233 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2234 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002235 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002236
2237 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2238 if (Is32BitImm) {
2239 Error(IDLoc, "instruction requires a 32-bit immediate");
2240 return true;
2241 }
2242
2243 // Traditionally, these immediates are shifted as little as possible and as
2244 // such we align the most significant bit to bit 15 of our temporary.
2245 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2246 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2247 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2248 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
2249 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, Instructions);
2250 emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, Instructions);
2251
2252 if (UseSrcReg)
2253 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2254
2255 return false;
2256 }
2257
2258 warnIfNoMacro(IDLoc);
2259
2260 // The remaining case is packed with a sequence of dsll and ori with zeros
2261 // being omitted and any neighbouring dsll's being coalesced.
2262 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2263
2264 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2265 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
2266 IDLoc, Instructions))
2267 return false;
2268
2269 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2270 // skip it and defer the shift to the next chunk.
2271 unsigned ShiftCarriedForwards = 16;
2272 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2273 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2274
2275 if (ImmChunk != 0) {
2276 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2277 Instructions);
2278 emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, Instructions);
2279 ShiftCarriedForwards = 0;
2280 }
2281
2282 ShiftCarriedForwards += 16;
2283 }
2284 ShiftCarriedForwards -= 16;
2285
2286 // Finish any remaining shifts left by trailing zeros.
2287 if (ShiftCarriedForwards)
2288 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2289 Instructions);
2290
2291 if (UseSrcReg)
2292 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2293
Matheus Almeida3813d572014-06-19 14:39:14 +00002294 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002295}
Jack Carter92995f12012-10-06 00:53:28 +00002296
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002297bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
2298 SmallVectorImpl<MCInst> &Instructions) {
2299 const MCOperand &ImmOp = Inst.getOperand(1);
2300 assert(ImmOp.isImm() && "expected immediate operand kind");
2301 const MCOperand &DstRegOp = Inst.getOperand(0);
2302 assert(DstRegOp.isReg() && "expected register operand kind");
2303
2304 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002305 Is32BitImm, false, IDLoc, Instructions))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002306 return true;
2307
2308 return false;
2309}
2310
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002311bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2312 const MCOperand &Offset,
2313 bool Is32BitAddress, SMLoc IDLoc,
2314 SmallVectorImpl<MCInst> &Instructions) {
2315 // la can't produce a usable address when addresses are 64-bit.
2316 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2317 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2318 // We currently can't do this because we depend on the equality
2319 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2320 Error(IDLoc, "la used to load 64-bit address");
2321 // Continue as if we had 'dla' instead.
2322 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002323 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002324
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002325 // dla requires 64-bit addresses.
2326 if (!Is32BitAddress && !ABI.ArePtrs64bit()) {
2327 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002328 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002329 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002330
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002331 if (!Offset.isImm())
2332 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
2333 Is32BitAddress, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002334
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002335 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
2336 IDLoc, Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +00002337}
2338
Toma Tabacuf712ede2015-06-17 14:31:51 +00002339bool MipsAsmParser::loadAndAddSymbolAddress(
2340 const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
2341 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002342 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002343
Daniel Sandersd5a89412015-10-05 13:19:29 +00002344 const MCExpr *Symbol = cast<MCExpr>(SymExpr);
2345 const MipsMCExpr *HiExpr = MipsMCExpr::create(
2346 MCSymbolRefExpr::VK_Mips_ABS_HI, Symbol, getContext());
2347 const MipsMCExpr *LoExpr = MipsMCExpr::create(
2348 MCSymbolRefExpr::VK_Mips_ABS_LO, Symbol, getContext());
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002349
Toma Tabacufb9d1252015-06-22 12:08:39 +00002350 bool UseSrcReg = SrcReg != Mips::NoRegister;
2351
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002352 // This is the 64-bit symbol address expansion.
2353 if (ABI.ArePtrs64bit() && isGP64bit()) {
2354 // We always need AT for the 64-bit expansion.
2355 // If it is not available we exit.
2356 unsigned ATReg = getATReg(IDLoc);
2357 if (!ATReg)
2358 return true;
2359
Daniel Sandersd5a89412015-10-05 13:19:29 +00002360 const MipsMCExpr *HighestExpr = MipsMCExpr::create(
2361 MCSymbolRefExpr::VK_Mips_HIGHEST, Symbol, getContext());
2362 const MipsMCExpr *HigherExpr = MipsMCExpr::create(
2363 MCSymbolRefExpr::VK_Mips_HIGHER, Symbol, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002364
2365 if (UseSrcReg && (DstReg == SrcReg)) {
2366 // If $rs is the same as $rd:
2367 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2368 // daddiu $at, $at, %higher(sym)
2369 // dsll $at, $at, 16
2370 // daddiu $at, $at, %hi(sym)
2371 // dsll $at, $at, 16
2372 // daddiu $at, $at, %lo(sym)
2373 // daddu $rd, $at, $rd
2374 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2375 Instructions);
2376 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr),
2377 IDLoc, Instructions);
2378 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2379 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2380 Instructions);
2381 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2382 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2383 Instructions);
2384 emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions);
2385
2386 return false;
2387 }
2388
2389 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2390 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2391 // lui $at, %hi(sym)
2392 // daddiu $rd, $rd, %higher(sym)
2393 // daddiu $at, $at, %lo(sym)
2394 // dsll32 $rd, $rd, 0
2395 // daddu $rd, $rd, $at
2396 // (daddu $rd, $rd, $rs)
2397 emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2398 Instructions);
2399 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2400 Instructions);
2401 emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr),
2402 IDLoc, Instructions);
2403 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2404 Instructions);
2405 emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions);
2406 emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions);
2407 if (UseSrcReg)
2408 emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions);
2409
2410 return false;
2411 }
2412
2413 // And now, the 32-bit symbol address expansion:
2414 // If $rs is the same as $rd:
2415 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2416 // ori $at, $at, %lo(sym)
2417 // addu $rd, $at, $rd
2418 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2419 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2420 // ori $rd, $rd, %lo(sym)
2421 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002422 unsigned TmpReg = DstReg;
2423 if (UseSrcReg && (DstReg == SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002424 // If $rs is the same as $rd, we need to use AT.
2425 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002426 unsigned ATReg = getATReg(IDLoc);
2427 if (!ATReg)
2428 return true;
2429 TmpReg = ATReg;
2430 }
2431
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002432 emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions);
2433 emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc,
2434 Instructions);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002435
Toma Tabacufb9d1252015-06-22 12:08:39 +00002436 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002437 emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2438 else
2439 assert(DstReg == TmpReg);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002440
Toma Tabacu674825c2015-06-16 12:16:24 +00002441 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002442}
2443
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002444bool MipsAsmParser::expandUncondBranchMMPseudo(
2445 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002446 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2447 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002448
2449 MCOperand Offset = Inst.getOperand(0);
2450 if (Offset.isExpr()) {
2451 Inst.clear();
2452 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002453 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2454 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2455 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002456 } else {
2457 assert(Offset.isImm() && "expected immediate operand kind");
2458 if (isIntN(11, Offset.getImm())) {
2459 // If offset fits into 11 bits then this instruction becomes microMIPS
2460 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002461 if (inMicroMipsMode())
2462 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002463 } else {
2464 if (!isIntN(17, Offset.getImm()))
2465 Error(IDLoc, "branch target out of range");
2466 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2467 Error(IDLoc, "branch to misaligned address");
2468 Inst.clear();
2469 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002470 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2471 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2472 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002473 }
2474 }
2475 Instructions.push_back(Inst);
2476
Zoran Jovanovicada70912015-09-07 11:56:37 +00002477 // If .set reorder is active and branch instruction has a delay slot,
2478 // emit a NOP after it.
2479 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2480 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Toma Tabacu234482a2015-03-16 12:03:39 +00002481 createNop(true, IDLoc, Instructions);
2482
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002483 return false;
2484}
2485
Toma Tabacue1e460d2015-06-11 10:36:10 +00002486bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2487 SmallVectorImpl<MCInst> &Instructions) {
2488 const MCOperand &DstRegOp = Inst.getOperand(0);
2489 assert(DstRegOp.isReg() && "expected register operand kind");
2490
2491 const MCOperand &ImmOp = Inst.getOperand(1);
2492 assert(ImmOp.isImm() && "expected immediate operand kind");
2493
2494 const MCOperand &MemOffsetOp = Inst.getOperand(2);
2495 assert(MemOffsetOp.isImm() && "expected immediate operand kind");
2496
2497 unsigned OpCode = 0;
2498 switch(Inst.getOpcode()) {
2499 case Mips::BneImm:
2500 OpCode = Mips::BNE;
2501 break;
2502 case Mips::BeqImm:
2503 OpCode = Mips::BEQ;
2504 break;
2505 default:
2506 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2507 break;
2508 }
2509
2510 int64_t ImmValue = ImmOp.getImm();
2511 if (ImmValue == 0) {
2512 MCInst BranchInst;
2513 BranchInst.setOpcode(OpCode);
2514 BranchInst.addOperand(DstRegOp);
2515 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2516 BranchInst.addOperand(MemOffsetOp);
2517 Instructions.push_back(BranchInst);
2518 } else {
2519 warnIfNoMacro(IDLoc);
2520
2521 unsigned ATReg = getATReg(IDLoc);
2522 if (!ATReg)
2523 return true;
2524
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002525 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
2526 IDLoc, Instructions))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002527 return true;
2528
2529 MCInst BranchInst;
2530 BranchInst.setOpcode(OpCode);
2531 BranchInst.addOperand(DstRegOp);
2532 BranchInst.addOperand(MCOperand::createReg(ATReg));
2533 BranchInst.addOperand(MemOffsetOp);
2534 Instructions.push_back(BranchInst);
2535 }
2536 return false;
2537}
2538
Jack Carter9e65aa32013-03-22 00:05:30 +00002539void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002540 SmallVectorImpl<MCInst> &Instructions,
2541 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002542 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00002543 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002544 const MCExpr *ExprOffset;
2545 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002546 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002547 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2548 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002549 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002550 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2551 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002552 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002553 if (isImmOpnd) {
2554 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2555 ImmOffset = Inst.getOperand(2).getImm();
2556 LoOffset = ImmOffset & 0x0000ffff;
2557 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002558 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002559 if (LoOffset & 0x8000)
2560 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002561 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002562 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002563 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002564 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002565 // These are some of the types of expansions we perform here:
2566 // 1) lw $8, sym => lui $8, %hi(sym)
2567 // lw $8, %lo(sym)($8)
2568 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2569 // add $8, $8, $9
2570 // lw $8, %lo(offset)($9)
2571 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2572 // add $at, $at, $8
2573 // lw $8, %lo(offset)($at)
2574 // 4) sw $8, sym => lui $at, %hi(sym)
2575 // sw $8, %lo(sym)($at)
2576 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2577 // add $at, $at, $8
2578 // sw $8, %lo(offset)($at)
2579 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2580 // ldc1 $f0, %lo(sym)($at)
2581 //
2582 // For load instructions we can use the destination register as a temporary
2583 // if base and dst are different (examples 1 and 2) and if the base register
2584 // is general purpose otherwise we must use $at (example 6) and error if it's
2585 // not available. For stores we must use $at (examples 4 and 5) because we
2586 // must not clobber the source register setting up the offset.
2587 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2588 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2589 unsigned RegClassIDOp0 =
2590 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2591 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2592 (RegClassIDOp0 == Mips::GPR64RegClassID);
2593 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002594 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002595 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002596 // At this point we need AT to perform the expansions and we exit if it is
2597 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002598 TmpRegNum = getATReg(IDLoc);
2599 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002600 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002601 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002602
Jack Carter9e65aa32013-03-22 00:05:30 +00002603 TempInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00002604 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002605 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002606 TempInst.addOperand(MCOperand::createImm(HiOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002607 else {
Toma Tabacu07c97b32015-06-17 10:43:45 +00002608 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
2609 TempInst.addOperand(MCOperand::createExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002610 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002611 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002612 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002613 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002614 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002615 // Add temp register to base.
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002616 if (BaseRegNum != Mips::ZERO) {
2617 TempInst.setOpcode(Mips::ADDu);
Jim Grosbache9119e42015-05-13 18:37:00 +00002618 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2619 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2620 TempInst.addOperand(MCOperand::createReg(BaseRegNum));
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002621 Instructions.push_back(TempInst);
2622 TempInst.clear();
2623 }
Alp Tokercb402912014-01-24 17:20:08 +00002624 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002625 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002626 TempInst.setOpcode(Inst.getOpcode());
Jim Grosbache9119e42015-05-13 18:37:00 +00002627 TempInst.addOperand(MCOperand::createReg(RegOpNum));
2628 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002629 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002630 TempInst.addOperand(MCOperand::createImm(LoOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002631 else {
Toma Tabacu07c97b32015-06-17 10:43:45 +00002632 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
2633 TempInst.addOperand(MCOperand::createExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002634 }
2635 Instructions.push_back(TempInst);
2636 TempInst.clear();
2637}
2638
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002639bool
2640MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2641 SmallVectorImpl<MCInst> &Instructions) {
2642 unsigned OpNum = Inst.getNumOperands();
2643 unsigned Opcode = Inst.getOpcode();
2644 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2645
2646 assert (Inst.getOperand(OpNum - 1).isImm() &&
2647 Inst.getOperand(OpNum - 2).isReg() &&
2648 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2649
2650 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2651 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2652 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2653 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2654 // It can be implemented as SWM16 or LWM16 instruction.
2655 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2656
2657 Inst.setOpcode(NewOpcode);
2658 Instructions.push_back(Inst);
2659 return false;
2660}
2661
Toma Tabacu1a108322015-06-17 13:20:24 +00002662bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2663 SmallVectorImpl<MCInst> &Instructions) {
2664 unsigned PseudoOpcode = Inst.getOpcode();
2665 unsigned SrcReg = Inst.getOperand(0).getReg();
2666 unsigned TrgReg = Inst.getOperand(1).getReg();
2667 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2668
2669 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002670 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002671
2672 switch (PseudoOpcode) {
2673 case Mips::BLT:
2674 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002675 case Mips::BLTL:
2676 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002677 AcceptsEquality = false;
2678 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002679 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2680 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002681 ZeroSrcOpcode = Mips::BGTZ;
2682 ZeroTrgOpcode = Mips::BLTZ;
2683 break;
2684 case Mips::BLE:
2685 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002686 case Mips::BLEL:
2687 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002688 AcceptsEquality = true;
2689 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002690 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2691 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002692 ZeroSrcOpcode = Mips::BGEZ;
2693 ZeroTrgOpcode = Mips::BLEZ;
2694 break;
2695 case Mips::BGE:
2696 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002697 case Mips::BGEL:
2698 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002699 AcceptsEquality = true;
2700 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002701 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2702 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002703 ZeroSrcOpcode = Mips::BLEZ;
2704 ZeroTrgOpcode = Mips::BGEZ;
2705 break;
2706 case Mips::BGT:
2707 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002708 case Mips::BGTL:
2709 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002710 AcceptsEquality = false;
2711 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002712 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2713 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002714 ZeroSrcOpcode = Mips::BLTZ;
2715 ZeroTrgOpcode = Mips::BGTZ;
2716 break;
2717 default:
2718 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2719 }
2720
2721 MCInst BranchInst;
2722 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2723 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2724 if (IsSrcRegZero && IsTrgRegZero) {
2725 // FIXME: All of these Opcode-specific if's are needed for compatibility
2726 // with GAS' behaviour. However, they may not generate the most efficient
2727 // code in some circumstances.
2728 if (PseudoOpcode == Mips::BLT) {
2729 BranchInst.setOpcode(Mips::BLTZ);
2730 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2731 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2732 Instructions.push_back(BranchInst);
2733 return false;
2734 }
2735 if (PseudoOpcode == Mips::BLE) {
2736 BranchInst.setOpcode(Mips::BLEZ);
2737 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2738 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2739 Instructions.push_back(BranchInst);
2740 Warning(IDLoc, "branch is always taken");
2741 return false;
2742 }
2743 if (PseudoOpcode == Mips::BGE) {
2744 BranchInst.setOpcode(Mips::BGEZ);
2745 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2746 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2747 Instructions.push_back(BranchInst);
2748 Warning(IDLoc, "branch is always taken");
2749 return false;
2750 }
2751 if (PseudoOpcode == Mips::BGT) {
2752 BranchInst.setOpcode(Mips::BGTZ);
2753 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2754 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2755 Instructions.push_back(BranchInst);
2756 return false;
2757 }
2758 if (PseudoOpcode == Mips::BGTU) {
2759 BranchInst.setOpcode(Mips::BNE);
2760 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2761 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2762 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2763 Instructions.push_back(BranchInst);
2764 return false;
2765 }
2766 if (AcceptsEquality) {
2767 // If both registers are $0 and the pseudo-branch accepts equality, it
2768 // will always be taken, so we emit an unconditional branch.
2769 BranchInst.setOpcode(Mips::BEQ);
2770 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2771 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2772 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2773 Instructions.push_back(BranchInst);
2774 Warning(IDLoc, "branch is always taken");
2775 return false;
2776 }
2777 // If both registers are $0 and the pseudo-branch does not accept
2778 // equality, it will never be taken, so we don't have to emit anything.
2779 return false;
2780 }
2781 if (IsSrcRegZero || IsTrgRegZero) {
2782 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2783 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2784 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2785 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2786 // the pseudo-branch will never be taken, so we don't emit anything.
2787 // This only applies to unsigned pseudo-branches.
2788 return false;
2789 }
2790 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2791 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2792 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2793 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2794 // the pseudo-branch will always be taken, so we emit an unconditional
2795 // branch.
2796 // This only applies to unsigned pseudo-branches.
2797 BranchInst.setOpcode(Mips::BEQ);
2798 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2799 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2800 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2801 Instructions.push_back(BranchInst);
2802 Warning(IDLoc, "branch is always taken");
2803 return false;
2804 }
2805 if (IsUnsigned) {
2806 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2807 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2808 // the pseudo-branch will be taken only when the non-zero register is
2809 // different from 0, so we emit a BNEZ.
2810 //
2811 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2812 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2813 // the pseudo-branch will be taken only when the non-zero register is
2814 // equal to 0, so we emit a BEQZ.
2815 //
2816 // Because only BLEU and BGEU branch on equality, we can use the
2817 // AcceptsEquality variable to decide when to emit the BEQZ.
2818 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQ : Mips::BNE);
2819 BranchInst.addOperand(
2820 MCOperand::createReg(IsSrcRegZero ? TrgReg : SrcReg));
2821 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2822 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2823 Instructions.push_back(BranchInst);
2824 return false;
2825 }
2826 // If we have a signed pseudo-branch and one of the registers is $0,
2827 // we can use an appropriate compare-to-zero branch. We select which one
2828 // to use in the switch statement above.
2829 BranchInst.setOpcode(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode);
2830 BranchInst.addOperand(MCOperand::createReg(IsSrcRegZero ? TrgReg : SrcReg));
2831 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2832 Instructions.push_back(BranchInst);
2833 return false;
2834 }
2835
2836 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2837 // expansions. If it is not available, we return.
2838 unsigned ATRegNum = getATReg(IDLoc);
2839 if (!ATRegNum)
2840 return true;
2841
2842 warnIfNoMacro(IDLoc);
2843
2844 // SLT fits well with 2 of our 4 pseudo-branches:
2845 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2846 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2847 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2848 // This is accomplished by using a BNEZ with the result of the SLT.
2849 //
2850 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2851 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2852 // Because only BGE and BLE branch on equality, we can use the
2853 // AcceptsEquality variable to decide when to emit the BEQZ.
2854 // Note that the order of the SLT arguments doesn't change between
2855 // opposites.
2856 //
2857 // The same applies to the unsigned variants, except that SLTu is used
2858 // instead of SLT.
2859 MCInst SetInst;
2860 SetInst.setOpcode(IsUnsigned ? Mips::SLTu : Mips::SLT);
2861 SetInst.addOperand(MCOperand::createReg(ATRegNum));
2862 SetInst.addOperand(MCOperand::createReg(ReverseOrderSLT ? TrgReg : SrcReg));
2863 SetInst.addOperand(MCOperand::createReg(ReverseOrderSLT ? SrcReg : TrgReg));
2864 Instructions.push_back(SetInst);
2865
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002866 if (!IsLikely)
2867 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQ : Mips::BNE);
2868 else
2869 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQL : Mips::BNEL);
Toma Tabacu1a108322015-06-17 13:20:24 +00002870 BranchInst.addOperand(MCOperand::createReg(ATRegNum));
2871 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2872 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2873 Instructions.push_back(BranchInst);
2874 return false;
2875}
2876
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002877bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
2878 SmallVectorImpl<MCInst> &Instructions,
2879 const bool IsMips64, const bool Signed) {
2880 if (hasMips32r6()) {
2881 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2882 return false;
2883 }
2884
2885 warnIfNoMacro(IDLoc);
2886
2887 const MCOperand &RsRegOp = Inst.getOperand(0);
2888 assert(RsRegOp.isReg() && "expected register operand kind");
2889 unsigned RsReg = RsRegOp.getReg();
2890
2891 const MCOperand &RtRegOp = Inst.getOperand(1);
2892 assert(RtRegOp.isReg() && "expected register operand kind");
2893 unsigned RtReg = RtRegOp.getReg();
2894 unsigned DivOp;
2895 unsigned ZeroReg;
2896
2897 if (IsMips64) {
2898 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2899 ZeroReg = Mips::ZERO_64;
2900 } else {
2901 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2902 ZeroReg = Mips::ZERO;
2903 }
2904
2905 bool UseTraps = useTraps();
2906
2907 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2908 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2909 Warning(IDLoc, "dividing zero by zero");
2910 if (IsMips64) {
2911 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2912 if (UseTraps) {
2913 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2914 return false;
2915 }
2916
2917 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2918 return false;
2919 }
2920 } else {
2921 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2922 return false;
2923 }
2924 }
2925
2926 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
2927 Warning(IDLoc, "division by zero");
2928 if (Signed) {
2929 if (UseTraps) {
2930 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2931 return false;
2932 }
2933
2934 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2935 return false;
2936 }
2937 }
2938
2939 // FIXME: The values for these two BranchTarget variables may be different in
2940 // micromips. These magic numbers need to be removed.
2941 unsigned BranchTargetNoTraps;
2942 unsigned BranchTarget;
2943
2944 if (UseTraps) {
2945 BranchTarget = IsMips64 ? 12 : 8;
2946 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2947 } else {
2948 BranchTarget = IsMips64 ? 20 : 16;
2949 BranchTargetNoTraps = 8;
2950 // Branch to the li instruction.
2951 emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc,
2952 Instructions);
2953 }
2954
2955 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2956
2957 if (!UseTraps)
2958 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2959
2960 if (!Signed) {
2961 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
2962 return false;
2963 }
2964
2965 unsigned ATReg = getATReg(IDLoc);
2966 if (!ATReg)
2967 return true;
2968
2969 emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, Instructions);
2970 if (IsMips64) {
2971 // Branch to the mflo instruction.
2972 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
2973 emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, Instructions);
2974 emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, Instructions);
2975 } else {
2976 // Branch to the mflo instruction.
2977 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
2978 emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, Instructions);
2979 }
2980
2981 if (UseTraps)
2982 emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, Instructions);
2983 else {
2984 // Branch to the mflo instruction.
2985 emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, Instructions);
2986 emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, Instructions);
2987 emitII(Mips::BREAK, 0x6, 0, IDLoc, Instructions);
2988 }
2989 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
2990 return false;
2991}
2992
Toma Tabacud88d79c2015-06-23 14:39:42 +00002993bool MipsAsmParser::expandUlhu(MCInst &Inst, SMLoc IDLoc,
2994 SmallVectorImpl<MCInst> &Instructions) {
2995 if (hasMips32r6() || hasMips64r6()) {
2996 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2997 return false;
2998 }
2999
3000 warnIfNoMacro(IDLoc);
3001
3002 const MCOperand &DstRegOp = Inst.getOperand(0);
3003 assert(DstRegOp.isReg() && "expected register operand kind");
3004
3005 const MCOperand &SrcRegOp = Inst.getOperand(1);
3006 assert(SrcRegOp.isReg() && "expected register operand kind");
3007
3008 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3009 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3010
3011 unsigned DstReg = DstRegOp.getReg();
3012 unsigned SrcReg = SrcRegOp.getReg();
3013 int64_t OffsetValue = OffsetImmOp.getImm();
3014
3015 // NOTE: We always need AT for ULHU, as it is always used as the source
3016 // register for one of the LBu's.
3017 unsigned ATReg = getATReg(IDLoc);
3018 if (!ATReg)
3019 return true;
3020
3021 // When the value of offset+1 does not fit in 16 bits, we have to load the
3022 // offset in AT, (D)ADDu the original source register (if there was one), and
3023 // then use AT as the source register for the 2 generated LBu's.
3024 bool LoadedOffsetInAT = false;
3025 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3026 LoadedOffsetInAT = true;
3027
3028 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003029 true, IDLoc, Instructions))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003030 return true;
3031
3032 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3033 // because it will make our output more similar to GAS'. For example,
3034 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3035 // instead of just an "ori $1, $9, 32768".
3036 // NOTE: If there is no source register specified in the ULHU, the parser
3037 // will interpret it as $0.
3038 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3039 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3040 }
3041
3042 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3043 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3044 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3045
3046 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3047 if (isLittle()) {
3048 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3049 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3050 } else {
3051 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3052 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3053 }
3054
3055 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3056
3057 MCInst TmpInst;
3058 TmpInst.setOpcode(Mips::LBu);
3059 TmpInst.addOperand(MCOperand::createReg(FirstLbuDstReg));
3060 TmpInst.addOperand(MCOperand::createReg(LbuSrcReg));
3061 TmpInst.addOperand(MCOperand::createImm(FirstLbuOffset));
3062 Instructions.push_back(TmpInst);
3063
3064 TmpInst.clear();
3065 TmpInst.setOpcode(Mips::LBu);
3066 TmpInst.addOperand(MCOperand::createReg(SecondLbuDstReg));
3067 TmpInst.addOperand(MCOperand::createReg(LbuSrcReg));
3068 TmpInst.addOperand(MCOperand::createImm(SecondLbuOffset));
3069 Instructions.push_back(TmpInst);
3070
3071 TmpInst.clear();
3072 TmpInst.setOpcode(Mips::SLL);
3073 TmpInst.addOperand(MCOperand::createReg(SllReg));
3074 TmpInst.addOperand(MCOperand::createReg(SllReg));
3075 TmpInst.addOperand(MCOperand::createImm(8));
3076 Instructions.push_back(TmpInst);
3077
3078 TmpInst.clear();
3079 TmpInst.setOpcode(Mips::OR);
3080 TmpInst.addOperand(MCOperand::createReg(DstReg));
3081 TmpInst.addOperand(MCOperand::createReg(DstReg));
3082 TmpInst.addOperand(MCOperand::createReg(ATReg));
3083 Instructions.push_back(TmpInst);
3084
3085 return false;
3086}
3087
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003088bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
3089 SmallVectorImpl<MCInst> &Instructions) {
3090 if (hasMips32r6() || hasMips64r6()) {
3091 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3092 return false;
3093 }
3094
3095 const MCOperand &DstRegOp = Inst.getOperand(0);
3096 assert(DstRegOp.isReg() && "expected register operand kind");
3097
3098 const MCOperand &SrcRegOp = Inst.getOperand(1);
3099 assert(SrcRegOp.isReg() && "expected register operand kind");
3100
3101 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3102 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3103
3104 unsigned SrcReg = SrcRegOp.getReg();
3105 int64_t OffsetValue = OffsetImmOp.getImm();
3106 unsigned ATReg = 0;
3107
3108 // When the value of offset+3 does not fit in 16 bits, we have to load the
3109 // offset in AT, (D)ADDu the original source register (if there was one), and
3110 // then use AT as the source register for the generated LWL and LWR.
3111 bool LoadedOffsetInAT = false;
3112 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3113 ATReg = getATReg(IDLoc);
3114 if (!ATReg)
3115 return true;
3116 LoadedOffsetInAT = true;
3117
3118 warnIfNoMacro(IDLoc);
3119
3120 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003121 true, IDLoc, Instructions))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003122 return true;
3123
3124 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3125 // because it will make our output more similar to GAS'. For example,
3126 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3127 // instead of just an "ori $1, $9, 32768".
3128 // NOTE: If there is no source register specified in the ULW, the parser
3129 // will interpret it as $0.
3130 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3131 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3132 }
3133
3134 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3135 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3136 if (isLittle()) {
3137 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3138 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3139 } else {
3140 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3141 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3142 }
3143
3144 MCInst LeftLoadInst;
3145 LeftLoadInst.setOpcode(Mips::LWL);
3146 LeftLoadInst.addOperand(DstRegOp);
3147 LeftLoadInst.addOperand(MCOperand::createReg(FinalSrcReg));
3148 LeftLoadInst.addOperand(MCOperand::createImm(LeftLoadOffset));
3149 Instructions.push_back(LeftLoadInst);
3150
3151 MCInst RightLoadInst;
3152 RightLoadInst.setOpcode(Mips::LWR);
3153 RightLoadInst.addOperand(DstRegOp);
3154 RightLoadInst.addOperand(MCOperand::createReg(FinalSrcReg));
3155 RightLoadInst.addOperand(MCOperand::createImm(RightLoadOffset ));
3156 Instructions.push_back(RightLoadInst);
3157
3158 return false;
3159}
3160
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003161bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
3162 SmallVectorImpl<MCInst> &Instructions) {
3163
3164 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3165 assert (Inst.getOperand(0).isReg() &&
3166 Inst.getOperand(1).isReg() &&
3167 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3168
3169 unsigned ATReg = Mips::NoRegister;
3170 unsigned FinalDstReg = Mips::NoRegister;
3171 unsigned DstReg = Inst.getOperand(0).getReg();
3172 unsigned SrcReg = Inst.getOperand(1).getReg();
3173 int64_t ImmValue = Inst.getOperand(2).getImm();
3174
3175 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3176
3177 unsigned FinalOpcode = Inst.getOpcode();
3178
3179 if (DstReg == SrcReg) {
3180 ATReg = getATReg(Inst.getLoc());
3181 if (!ATReg)
3182 return true;
3183 FinalDstReg = DstReg;
3184 DstReg = ATReg;
3185 }
3186
3187 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Instructions)) {
3188 switch (FinalOpcode) {
3189 default:
3190 llvm_unreachable("unimplemented expansion");
3191 case (Mips::ADDi):
3192 FinalOpcode = Mips::ADD;
3193 break;
3194 case (Mips::ADDiu):
3195 FinalOpcode = Mips::ADDu;
3196 break;
3197 case (Mips::ANDi):
3198 FinalOpcode = Mips::AND;
3199 break;
3200 case (Mips::NORImm):
3201 FinalOpcode = Mips::NOR;
3202 break;
3203 case (Mips::ORi):
3204 FinalOpcode = Mips::OR;
3205 break;
3206 case (Mips::SLTi):
3207 FinalOpcode = Mips::SLT;
3208 break;
3209 case (Mips::SLTiu):
3210 FinalOpcode = Mips::SLTu;
3211 break;
3212 case (Mips::XORi):
3213 FinalOpcode = Mips::XOR;
3214 break;
3215 }
3216
3217 MCInst tmpInst;
3218
3219 tmpInst.clear();
3220 tmpInst.setLoc(Inst.getLoc());
3221 tmpInst.setOpcode(FinalOpcode);
3222 if (FinalDstReg == Mips::NoRegister) {
3223 tmpInst.addOperand(MCOperand::createReg(DstReg));
3224 tmpInst.addOperand(MCOperand::createReg(DstReg));
3225 tmpInst.addOperand(MCOperand::createReg(SrcReg));
3226 } else {
3227 tmpInst.addOperand(MCOperand::createReg(FinalDstReg));
3228 tmpInst.addOperand(MCOperand::createReg(FinalDstReg));
3229 tmpInst.addOperand(MCOperand::createReg(DstReg));
3230 }
3231 Instructions.push_back(tmpInst);
3232 return false;
3233 }
3234 return true;
3235}
3236
Toma Tabacu234482a2015-03-16 12:03:39 +00003237void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
3238 SmallVectorImpl<MCInst> &Instructions) {
3239 MCInst NopInst;
3240 if (hasShortDelaySlot) {
3241 NopInst.setOpcode(Mips::MOVE16_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003242 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
3243 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
Toma Tabacu234482a2015-03-16 12:03:39 +00003244 } else {
3245 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00003246 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
3247 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
3248 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu234482a2015-03-16 12:03:39 +00003249 }
3250 Instructions.push_back(NopInst);
3251}
3252
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003253void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +00003254 unsigned TrgReg, bool Is64Bit,
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003255 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders03f9c012015-07-14 12:24:22 +00003256 emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
3257 Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003258}
3259
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003260void MipsAsmParser::createCpRestoreMemOp(
3261 bool IsLoad, int StackOffset, SMLoc IDLoc,
3262 SmallVectorImpl<MCInst> &Instructions) {
3263 MCInst MemInst;
3264 MemInst.setOpcode(IsLoad ? Mips::LW : Mips::SW);
3265 MemInst.addOperand(MCOperand::createReg(Mips::GP));
3266 MemInst.addOperand(MCOperand::createReg(Mips::SP));
3267 MemInst.addOperand(MCOperand::createImm(StackOffset));
3268
3269 // If the offset can not fit into 16 bits, we need to expand.
3270 if (!isInt<16>(StackOffset))
3271 expandMemInst(MemInst, IDLoc, Instructions, IsLoad, true /*HasImmOpnd*/);
3272 else
3273 Instructions.push_back(MemInst);
3274}
3275
Matheus Almeida595fcab2014-06-11 15:05:56 +00003276unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3277 // As described by the Mips32r2 spec, the registers Rd and Rs for
3278 // jalr.hb must be different.
3279 unsigned Opcode = Inst.getOpcode();
3280
3281 if (Opcode == Mips::JALR_HB &&
3282 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3283 return Match_RequiresDifferentSrcAndDst;
3284
3285 return Match_Success;
3286}
3287
David Blaikie960ea3f2014-06-08 16:18:35 +00003288bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3289 OperandVector &Operands,
3290 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003291 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003292 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003293
Jack Carterb4dbc172012-09-05 23:34:03 +00003294 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00003295 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00003296 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003297 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003298
3299 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003300 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003301 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00003302 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00003303 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00003304 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00003305 return false;
3306 }
3307 case Match_MissingFeature:
3308 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3309 return true;
3310 case Match_InvalidOperand: {
3311 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003312 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003313 if (ErrorInfo >= Operands.size())
3314 return Error(IDLoc, "too few operands for instruction");
3315
David Blaikie960ea3f2014-06-08 16:18:35 +00003316 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003317 if (ErrorLoc == SMLoc())
3318 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003319 }
3320
3321 return Error(ErrorLoc, "invalid operand for instruction");
3322 }
3323 case Match_MnemonicFail:
3324 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003325 case Match_RequiresDifferentSrcAndDst:
3326 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00003327 }
Craig Topper589ceee2015-01-03 08:16:34 +00003328
3329 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003330}
3331
Toma Tabacud9d344b2015-04-27 14:05:04 +00003332void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3333 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3334 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3335 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003336}
3337
Toma Tabacu81496c12015-05-20 08:54:45 +00003338void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3339 if (!AssemblerOptions.back()->isMacro())
3340 Warning(Loc, "macro instruction expanded into multiple instructions");
3341}
3342
Daniel Sandersef638fe2014-10-03 15:37:37 +00003343void
3344MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3345 SMRange Range, bool ShowColors) {
3346 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003347 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003348 ShowColors);
3349}
3350
Jack Carter1ac53222013-02-20 23:11:17 +00003351int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003352 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003353
Vladimir Medic4c299852013-11-06 11:27:05 +00003354 CC = StringSwitch<unsigned>(Name)
3355 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003356 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003357 .Case("a0", 4)
3358 .Case("a1", 5)
3359 .Case("a2", 6)
3360 .Case("a3", 7)
3361 .Case("v0", 2)
3362 .Case("v1", 3)
3363 .Case("s0", 16)
3364 .Case("s1", 17)
3365 .Case("s2", 18)
3366 .Case("s3", 19)
3367 .Case("s4", 20)
3368 .Case("s5", 21)
3369 .Case("s6", 22)
3370 .Case("s7", 23)
3371 .Case("k0", 26)
3372 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003373 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003374 .Case("sp", 29)
3375 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003376 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003377 .Case("ra", 31)
3378 .Case("t0", 8)
3379 .Case("t1", 9)
3380 .Case("t2", 10)
3381 .Case("t3", 11)
3382 .Case("t4", 12)
3383 .Case("t5", 13)
3384 .Case("t6", 14)
3385 .Case("t7", 15)
3386 .Case("t8", 24)
3387 .Case("t9", 25)
3388 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003389
Toma Tabacufda445c2014-09-15 15:33:01 +00003390 if (!(isABI_N32() || isABI_N64()))
3391 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003392
Daniel Sandersef638fe2014-10-03 15:37:37 +00003393 if (12 <= CC && CC <= 15) {
3394 // Name is one of t4-t7
3395 AsmToken RegTok = getLexer().peekTok();
3396 SMRange RegRange = RegTok.getLocRange();
3397
3398 StringRef FixedName = StringSwitch<StringRef>(Name)
3399 .Case("t4", "t0")
3400 .Case("t5", "t1")
3401 .Case("t6", "t2")
3402 .Case("t7", "t3")
3403 .Default("");
3404 assert(FixedName != "" && "Register name is not one of t4-t7.");
3405
3406 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3407 "Did you mean $" + FixedName + "?", RegRange);
3408 }
3409
Toma Tabacufda445c2014-09-15 15:33:01 +00003410 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3411 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3412 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3413 if (8 <= CC && CC <= 11)
3414 CC += 4;
3415
3416 if (CC == -1)
3417 CC = StringSwitch<unsigned>(Name)
3418 .Case("a4", 8)
3419 .Case("a5", 9)
3420 .Case("a6", 10)
3421 .Case("a7", 11)
3422 .Case("kt0", 26)
3423 .Case("kt1", 27)
3424 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003425
3426 return CC;
3427}
Jack Carterd0bd6422013-04-18 00:41:53 +00003428
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003429int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3430 int CC;
3431
3432 CC = StringSwitch<unsigned>(Name)
3433 .Case("hwr_cpunum", 0)
3434 .Case("hwr_synci_step", 1)
3435 .Case("hwr_cc", 2)
3436 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003437 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003438 .Default(-1);
3439
3440 return CC;
3441}
3442
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003443int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003444
Jack Cartera63b16a2012-09-07 00:23:42 +00003445 if (Name[0] == 'f') {
3446 StringRef NumString = Name.substr(1);
3447 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003448 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003449 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003450 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003451 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003452 return IntVal;
3453 }
3454 return -1;
3455}
Jack Cartera63b16a2012-09-07 00:23:42 +00003456
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003457int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3458
3459 if (Name.startswith("fcc")) {
3460 StringRef NumString = Name.substr(3);
3461 unsigned IntVal;
3462 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003463 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003464 if (IntVal > 7) // There are only 8 fcc registers.
3465 return -1;
3466 return IntVal;
3467 }
3468 return -1;
3469}
3470
3471int MipsAsmParser::matchACRegisterName(StringRef Name) {
3472
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003473 if (Name.startswith("ac")) {
3474 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003475 unsigned IntVal;
3476 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003477 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003478 if (IntVal > 3) // There are only 3 acc registers.
3479 return -1;
3480 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003481 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003482 return -1;
3483}
Jack Carterd0bd6422013-04-18 00:41:53 +00003484
Jack Carter5dc8ac92013-09-25 23:50:44 +00003485int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3486 unsigned IntVal;
3487
3488 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3489 return -1;
3490
3491 if (IntVal > 31)
3492 return -1;
3493
3494 return IntVal;
3495}
3496
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003497int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3498 int CC;
3499
3500 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003501 .Case("msair", 0)
3502 .Case("msacsr", 1)
3503 .Case("msaaccess", 2)
3504 .Case("msasave", 3)
3505 .Case("msamodify", 4)
3506 .Case("msarequest", 5)
3507 .Case("msamap", 6)
3508 .Case("msaunmap", 7)
3509 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003510
3511 return CC;
3512}
3513
Toma Tabacu89a712b2015-04-15 10:48:56 +00003514unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00003515 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00003516 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00003517 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00003518 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00003519 return 0;
3520 }
3521 unsigned AT = getReg(
3522 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00003523 return AT;
3524}
Jack Carter0b744b32012-10-04 02:29:46 +00003525
Jack Carterd0bd6422013-04-18 00:41:53 +00003526unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00003527 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00003528}
3529
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003530unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003531 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00003532 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003533}
3534
Jack Carter873c7242013-01-12 01:03:14 +00003535int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003536 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00003537 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00003538 return -1;
3539
Jack Carter873c7242013-01-12 01:03:14 +00003540 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00003541}
3542
Toma Tabacu13964452014-09-04 13:23:44 +00003543bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003544 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003545 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003546
Jack Carter30a59822012-10-04 04:03:53 +00003547 // Check if the current operand has a custom associated parser, if so, try to
3548 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00003549 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3550 if (ResTy == MatchOperand_Success)
3551 return false;
3552 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3553 // there was a match, but an error occurred, in which case, just return that
3554 // the operand parsing failed.
3555 if (ResTy == MatchOperand_ParseFail)
3556 return true;
3557
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003558 DEBUG(dbgs() << ".. Generic Parser\n");
3559
Jack Carterb4dbc172012-09-05 23:34:03 +00003560 switch (getLexer().getKind()) {
3561 default:
3562 Error(Parser.getTok().getLoc(), "unexpected token in operand");
3563 return true;
3564 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003565 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00003566 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00003567
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003568 // Almost all registers have been parsed by custom parsers. There is only
3569 // one exception to this. $zero (and it's alias $0) will reach this point
3570 // for div, divu, and similar instructions because it is not an operand
3571 // to the instruction definition but an explicit register. Special case
3572 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00003573 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00003574 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003575
Jack Carterd0bd6422013-04-18 00:41:53 +00003576 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00003577 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003578 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00003579 return true;
3580
Jack Carter873c7242013-01-12 01:03:14 +00003581 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00003582 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00003583 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00003584 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003585 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00003586
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003587 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003588 return false;
3589 }
Vladimir Medic4c299852013-11-06 11:27:05 +00003590 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00003591 case AsmToken::LParen:
3592 case AsmToken::Minus:
3593 case AsmToken::Plus:
3594 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003595 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00003596 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003597 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003598 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003599 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00003600 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00003601 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003602 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003603 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003604 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00003605 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00003606 return true;
3607
Jack Carter873c7242013-01-12 01:03:14 +00003608 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3609
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003610 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00003611 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003612 } // case AsmToken::Percent
3613 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00003614 return true;
3615}
3616
Vladimir Medic4c299852013-11-06 11:27:05 +00003617const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00003618 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003619 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00003620 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003621 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00003622 // It's a constant, evaluate reloc value.
3623 int16_t Val;
3624 switch (getVariantKind(RelocStr)) {
3625 case MCSymbolRefExpr::VK_Mips_ABS_LO:
3626 // Get the 1st 16-bits.
3627 Val = MCE->getValue() & 0xffff;
3628 break;
3629 case MCSymbolRefExpr::VK_Mips_ABS_HI:
3630 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
3631 // 16 bits being negative.
3632 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
3633 break;
3634 case MCSymbolRefExpr::VK_Mips_HIGHER:
3635 // Get the 3rd 16-bits.
3636 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
3637 break;
3638 case MCSymbolRefExpr::VK_Mips_HIGHEST:
3639 // Get the 4th 16-bits.
3640 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
3641 break;
3642 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00003643 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00003644 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00003645 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003646 }
3647
Jack Carterb5cf5902013-04-17 00:18:04 +00003648 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003649 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00003650 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00003651 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003652 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003653 return Res;
3654 }
3655
3656 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00003657 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
3658
Sasa Stankovic06c47802014-04-03 10:37:45 +00003659 // Try to create target expression.
3660 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00003661 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003662
Jack Carterd0bd6422013-04-18 00:41:53 +00003663 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
3664 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003665 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003666 return Res;
3667 }
3668
3669 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003670 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003671 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00003672 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00003673 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003674 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003675 return Expr;
3676}
3677
3678bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
3679
3680 switch (Expr->getKind()) {
3681 case MCExpr::Constant:
3682 return true;
3683 case MCExpr::SymbolRef:
3684 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
3685 case MCExpr::Binary:
3686 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
3687 if (!isEvaluated(BE->getLHS()))
3688 return false;
3689 return isEvaluated(BE->getRHS());
3690 }
3691 case MCExpr::Unary:
3692 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003693 case MCExpr::Target:
3694 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003695 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003696 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00003697}
Jack Carterd0bd6422013-04-18 00:41:53 +00003698
Jack Carterb5cf5902013-04-17 00:18:04 +00003699bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003700 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003701 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00003702 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00003703 if (Tok.isNot(AsmToken::Identifier))
3704 return true;
3705
Yaron Keren075759a2015-03-30 15:42:36 +00003706 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00003707
Jack Carterd0bd6422013-04-18 00:41:53 +00003708 Parser.Lex(); // Eat the identifier.
3709 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003710 const MCExpr *IdVal;
3711 SMLoc EndLoc;
3712
3713 if (getLexer().getKind() == AsmToken::LParen) {
3714 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003715 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003716 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003717 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003718 const AsmToken &nextTok = Parser.getTok();
3719 if (nextTok.isNot(AsmToken::Identifier))
3720 return true;
3721 Str += "(%";
3722 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00003723 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00003724 if (getLexer().getKind() != AsmToken::LParen)
3725 return true;
3726 } else
3727 break;
3728 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003729 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00003730 return true;
3731
3732 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00003733 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003734
3735 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00003736 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003737
Jack Carterd0bd6422013-04-18 00:41:53 +00003738 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00003739 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003740}
3741
Jack Carterb4dbc172012-09-05 23:34:03 +00003742bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
3743 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003744 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00003745 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003746 if (ResTy == MatchOperand_Success) {
3747 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00003748 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003749 StartLoc = Operand.getStartLoc();
3750 EndLoc = Operand.getEndLoc();
3751
3752 // AFAIK, we only support numeric registers and named GPR's in CFI
3753 // directives.
3754 // Don't worry about eating tokens before failing. Using an unrecognised
3755 // register is a parse error.
3756 if (Operand.isGPRAsmReg()) {
3757 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003758 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003759 }
3760
3761 return (RegNo == (unsigned)-1);
3762 }
3763
3764 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00003765 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00003766}
3767
Jack Carterb5cf5902013-04-17 00:18:04 +00003768bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003769 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00003770 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003771 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003772 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00003773
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003774 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003775 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003776 ++NumOfLParen;
3777 }
Jack Carter873c7242013-01-12 01:03:14 +00003778
Jack Carterd0bd6422013-04-18 00:41:53 +00003779 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003780 default:
3781 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00003782 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00003783 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00003784 case AsmToken::Integer:
3785 case AsmToken::Minus:
3786 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00003787 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003788 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00003789 else
3790 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00003791 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00003792 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003793 break;
Jack Carter873c7242013-01-12 01:03:14 +00003794 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00003795 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003796 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003797 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003798}
3799
David Blaikie960ea3f2014-06-08 16:18:35 +00003800MipsAsmParser::OperandMatchResultTy
3801MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003802 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003803 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00003804 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00003805 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003806 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003807 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00003808 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00003809 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00003810
Jack Carterb5cf5902013-04-17 00:18:04 +00003811 if (getLexer().getKind() == AsmToken::LParen) {
3812 Parser.Lex();
3813 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003814 }
3815
Jack Carterb5cf5902013-04-17 00:18:04 +00003816 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003817 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00003818 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003819
Jack Carterd0bd6422013-04-18 00:41:53 +00003820 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003821 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003822 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003823 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003824 SMLoc E =
3825 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003826 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003827 return MatchOperand_Success;
3828 }
3829 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003830 SMLoc E =
3831 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00003832
Jack Carterd0bd6422013-04-18 00:41:53 +00003833 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003834 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00003835 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003836 S, E, *this);
3837 Operands.push_back(
3838 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003839 return MatchOperand_Success;
3840 }
3841 Error(Parser.getTok().getLoc(), "'(' expected");
3842 return MatchOperand_ParseFail;
3843 }
3844
Jack Carterd0bd6422013-04-18 00:41:53 +00003845 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003846 }
3847
Toma Tabacu13964452014-09-04 13:23:44 +00003848 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003849 if (Res != MatchOperand_Success)
3850 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003851
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003852 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003853 Error(Parser.getTok().getLoc(), "')' expected");
3854 return MatchOperand_ParseFail;
3855 }
3856
Jack Carter873c7242013-01-12 01:03:14 +00003857 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3858
Jack Carterd0bd6422013-04-18 00:41:53 +00003859 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003860
Craig Topper062a2ba2014-04-25 05:30:21 +00003861 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003862 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003863
Jack Carterd0bd6422013-04-18 00:41:53 +00003864 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00003865 std::unique_ptr<MipsOperand> op(
3866 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00003867 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003868 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003869 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00003870 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003871 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
3872 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003873 if (IdVal->evaluateAsAbsolute(Imm))
3874 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003875 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003876 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00003877 getContext());
3878 }
3879
David Blaikie960ea3f2014-06-08 16:18:35 +00003880 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003881 return MatchOperand_Success;
3882}
3883
David Blaikie960ea3f2014-06-08 16:18:35 +00003884bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003885 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00003886 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00003887 if (Sym) {
3888 SMLoc S = Parser.getTok().getLoc();
3889 const MCExpr *Expr;
3890 if (Sym->isVariable())
3891 Expr = Sym->getVariableValue();
3892 else
3893 return false;
3894 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003895 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00003896 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00003897 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003898 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003899 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00003900 if (ResTy == MatchOperand_Success) {
3901 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00003902 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00003903 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003904 llvm_unreachable("Should never ParseFail");
3905 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00003906 }
3907 } else if (Expr->getKind() == MCExpr::Constant) {
3908 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00003909 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00003910 Operands.push_back(
3911 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00003912 return true;
3913 }
3914 }
3915 return false;
3916}
Jack Carterd0bd6422013-04-18 00:41:53 +00003917
Jack Carter873c7242013-01-12 01:03:14 +00003918MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003919MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00003920 StringRef Identifier,
3921 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003922 int Index = matchCPURegisterName(Identifier);
3923 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003924 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003925 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3926 return MatchOperand_Success;
3927 }
3928
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003929 Index = matchHWRegsRegisterName(Identifier);
3930 if (Index != -1) {
3931 Operands.push_back(MipsOperand::createHWRegsReg(
3932 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3933 return MatchOperand_Success;
3934 }
3935
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003936 Index = matchFPURegisterName(Identifier);
3937 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003938 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003939 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3940 return MatchOperand_Success;
3941 }
3942
3943 Index = matchFCCRegisterName(Identifier);
3944 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003945 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003946 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3947 return MatchOperand_Success;
3948 }
3949
3950 Index = matchACRegisterName(Identifier);
3951 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003952 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003953 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3954 return MatchOperand_Success;
3955 }
3956
3957 Index = matchMSA128RegisterName(Identifier);
3958 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003959 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003960 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3961 return MatchOperand_Success;
3962 }
3963
3964 Index = matchMSA128CtrlRegisterName(Identifier);
3965 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003966 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003967 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3968 return MatchOperand_Success;
3969 }
3970
3971 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00003972}
3973
3974MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003975MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003976 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00003977 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003978
3979 if (Token.is(AsmToken::Identifier)) {
3980 DEBUG(dbgs() << ".. identifier\n");
3981 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00003982 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003983 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00003984 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003985 } else if (Token.is(AsmToken::Integer)) {
3986 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003987 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003988 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
3989 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003990 return MatchOperand_Success;
3991 }
3992
3993 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
3994
3995 return MatchOperand_NoMatch;
3996}
3997
David Blaikie960ea3f2014-06-08 16:18:35 +00003998MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003999MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004000 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004001 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004002
4003 auto Token = Parser.getTok();
4004
4005 SMLoc S = Token.getLoc();
4006
4007 if (Token.isNot(AsmToken::Dollar)) {
4008 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4009 if (Token.is(AsmToken::Identifier)) {
4010 if (searchSymbolAlias(Operands))
4011 return MatchOperand_Success;
4012 }
4013 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4014 return MatchOperand_NoMatch;
4015 }
4016 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004017
Toma Tabacu13964452014-09-04 13:23:44 +00004018 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004019 if (ResTy == MatchOperand_Success) {
4020 Parser.Lex(); // $
4021 Parser.Lex(); // identifier
4022 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004023 return ResTy;
4024}
4025
4026MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004027MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004028 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004029 switch (getLexer().getKind()) {
4030 default:
4031 return MatchOperand_NoMatch;
4032 case AsmToken::LParen:
4033 case AsmToken::Minus:
4034 case AsmToken::Plus:
4035 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004036 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004037 case AsmToken::String:
4038 break;
4039 }
4040
4041 const MCExpr *IdVal;
4042 SMLoc S = Parser.getTok().getLoc();
4043 if (getParser().parseExpression(IdVal))
4044 return MatchOperand_ParseFail;
4045
4046 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4047 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4048 return MatchOperand_Success;
4049}
4050
David Blaikie960ea3f2014-06-08 16:18:35 +00004051MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004052MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004053 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004054 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004055
4056 SMLoc S = getLexer().getLoc();
4057
4058 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00004059 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004060 if (ResTy != MatchOperand_NoMatch)
4061 return ResTy;
4062
Daniel Sanders315386c2014-04-01 10:40:14 +00004063 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00004064 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00004065 if (ResTy != MatchOperand_NoMatch)
4066 return ResTy;
4067
Daniel Sandersffd84362014-04-01 10:41:48 +00004068 const MCExpr *Expr = nullptr;
4069 if (Parser.parseExpression(Expr)) {
4070 // We have no way of knowing if a symbol was consumed so we must ParseFail
4071 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004072 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004073 Operands.push_back(
4074 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004075 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004076}
4077
Vladimir Medic2b953d02013-10-01 09:48:56 +00004078MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004079MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004080 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004081 const MCExpr *IdVal;
4082 // If the first token is '$' we may have register operand.
4083 if (Parser.getTok().is(AsmToken::Dollar))
4084 return MatchOperand_NoMatch;
4085 SMLoc S = Parser.getTok().getLoc();
4086 if (getParser().parseExpression(IdVal))
4087 return MatchOperand_ParseFail;
4088 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004089 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004090 int64_t Val = MCE->getValue();
4091 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4092 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004093 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004094 return MatchOperand_Success;
4095}
4096
Matheus Almeida779c5932013-11-18 12:32:49 +00004097MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004098MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004099 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00004100 switch (getLexer().getKind()) {
4101 default:
4102 return MatchOperand_NoMatch;
4103 case AsmToken::LParen:
4104 case AsmToken::Plus:
4105 case AsmToken::Minus:
4106 case AsmToken::Integer:
4107 break;
4108 }
4109
4110 const MCExpr *Expr;
4111 SMLoc S = Parser.getTok().getLoc();
4112
4113 if (getParser().parseExpression(Expr))
4114 return MatchOperand_ParseFail;
4115
4116 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004117 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00004118 Error(S, "expected immediate value");
4119 return MatchOperand_ParseFail;
4120 }
4121
4122 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
4123 // and because the CPU always adds one to the immediate field, the allowed
4124 // range becomes 1..4. We'll only check the range here and will deal
4125 // with the addition/subtraction when actually decoding/encoding
4126 // the instruction.
4127 if (Val < 1 || Val > 4) {
4128 Error(S, "immediate not in range (1..4)");
4129 return MatchOperand_ParseFail;
4130 }
4131
Jack Carter3b2c96e2014-01-22 23:31:38 +00004132 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004133 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00004134 return MatchOperand_Success;
4135}
4136
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004137MipsAsmParser::OperandMatchResultTy
4138MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4139 MCAsmParser &Parser = getParser();
4140 SmallVector<unsigned, 10> Regs;
4141 unsigned RegNo;
4142 unsigned PrevReg = Mips::NoRegister;
4143 bool RegRange = false;
4144 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4145
4146 if (Parser.getTok().isNot(AsmToken::Dollar))
4147 return MatchOperand_ParseFail;
4148
4149 SMLoc S = Parser.getTok().getLoc();
4150 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4151 SMLoc E = getLexer().getLoc();
4152 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4153 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4154 if (RegRange) {
4155 // Remove last register operand because registers from register range
4156 // should be inserted first.
4157 if (RegNo == Mips::RA) {
4158 Regs.push_back(RegNo);
4159 } else {
4160 unsigned TmpReg = PrevReg + 1;
4161 while (TmpReg <= RegNo) {
4162 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
4163 Error(E, "invalid register operand");
4164 return MatchOperand_ParseFail;
4165 }
4166
4167 PrevReg = TmpReg;
4168 Regs.push_back(TmpReg++);
4169 }
4170 }
4171
4172 RegRange = false;
4173 } else {
4174 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
4175 (RegNo != Mips::RA)) {
4176 Error(E, "$16 or $31 expected");
4177 return MatchOperand_ParseFail;
4178 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
4179 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
4180 Error(E, "invalid register operand");
4181 return MatchOperand_ParseFail;
4182 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
4183 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
4184 Error(E, "consecutive register numbers expected");
4185 return MatchOperand_ParseFail;
4186 }
4187
4188 Regs.push_back(RegNo);
4189 }
4190
4191 if (Parser.getTok().is(AsmToken::Minus))
4192 RegRange = true;
4193
4194 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4195 !Parser.getTok().isNot(AsmToken::Comma)) {
4196 Error(E, "',' or '-' expected");
4197 return MatchOperand_ParseFail;
4198 }
4199
4200 Lex(); // Consume comma or minus
4201 if (Parser.getTok().isNot(AsmToken::Dollar))
4202 break;
4203
4204 PrevReg = RegNo;
4205 }
4206
4207 SMLoc E = Parser.getTok().getLoc();
4208 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4209 parseMemOperand(Operands);
4210 return MatchOperand_Success;
4211}
4212
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004213MipsAsmParser::OperandMatchResultTy
4214MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4215 MCAsmParser &Parser = getParser();
4216
4217 SMLoc S = Parser.getTok().getLoc();
4218 if (parseAnyRegister(Operands) != MatchOperand_Success)
4219 return MatchOperand_ParseFail;
4220
4221 SMLoc E = Parser.getTok().getLoc();
4222 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
4223 unsigned Reg = Op.getGPR32Reg();
4224 Operands.pop_back();
4225 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
4226 return MatchOperand_Success;
4227}
4228
Zoran Jovanovic41688672015-02-10 16:36:20 +00004229MipsAsmParser::OperandMatchResultTy
4230MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4231 MCAsmParser &Parser = getParser();
4232 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4233 SmallVector<unsigned, 10> Regs;
4234
4235 if (Parser.getTok().isNot(AsmToken::Dollar))
4236 return MatchOperand_ParseFail;
4237
4238 SMLoc S = Parser.getTok().getLoc();
4239
4240 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4241 return MatchOperand_ParseFail;
4242
4243 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4244 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4245 Regs.push_back(RegNo);
4246
4247 SMLoc E = Parser.getTok().getLoc();
4248 if (Parser.getTok().isNot(AsmToken::Comma)) {
4249 Error(E, "',' expected");
4250 return MatchOperand_ParseFail;
4251 }
4252
4253 // Remove comma.
4254 Parser.Lex();
4255
4256 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4257 return MatchOperand_ParseFail;
4258
4259 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4260 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4261 Regs.push_back(RegNo);
4262
4263 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4264
4265 return MatchOperand_Success;
4266}
4267
Jack Carterdc1e35d2012-09-06 20:00:02 +00004268MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
4269
Vladimir Medic4c299852013-11-06 11:27:05 +00004270 MCSymbolRefExpr::VariantKind VK =
4271 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
4272 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
4273 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
4274 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
4275 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
4276 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
4277 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
4278 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
4279 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
4280 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
4281 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
4282 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
4283 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
4284 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
4285 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
4286 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
4287 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
4288 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00004289 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
4290 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
4291 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
4292 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
4293 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
4294 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00004295 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
4296 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00004297 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004298
Matheus Almeida2852af82014-04-22 10:15:54 +00004299 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00004300
Jack Carterdc1e35d2012-09-06 20:00:02 +00004301 return VK;
4302}
Jack Cartera63b16a2012-09-07 00:23:42 +00004303
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004304/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4305/// either this.
4306/// ::= '(', register, ')'
4307/// handle it before we iterate so we don't get tripped up by the lack of
4308/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004309bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004310 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004311 if (getLexer().is(AsmToken::LParen)) {
4312 Operands.push_back(
4313 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4314 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004315 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004316 SMLoc Loc = getLexer().getLoc();
4317 Parser.eatToEndOfStatement();
4318 return Error(Loc, "unexpected token in argument list");
4319 }
4320 if (Parser.getTok().isNot(AsmToken::RParen)) {
4321 SMLoc Loc = getLexer().getLoc();
4322 Parser.eatToEndOfStatement();
4323 return Error(Loc, "unexpected token, expected ')'");
4324 }
4325 Operands.push_back(
4326 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4327 Parser.Lex();
4328 }
4329 return false;
4330}
4331
4332/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4333/// either one of these.
4334/// ::= '[', register, ']'
4335/// ::= '[', integer, ']'
4336/// handle it before we iterate so we don't get tripped up by the lack of
4337/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004338bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004339 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004340 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004341 if (getLexer().is(AsmToken::LBrac)) {
4342 Operands.push_back(
4343 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4344 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004345 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004346 SMLoc Loc = getLexer().getLoc();
4347 Parser.eatToEndOfStatement();
4348 return Error(Loc, "unexpected token in argument list");
4349 }
4350 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4351 SMLoc Loc = getLexer().getLoc();
4352 Parser.eatToEndOfStatement();
4353 return Error(Loc, "unexpected token, expected ']'");
4354 }
4355 Operands.push_back(
4356 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4357 Parser.Lex();
4358 }
4359 return false;
4360}
4361
David Blaikie960ea3f2014-06-08 16:18:35 +00004362bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4363 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004364 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004365 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004366
4367 // We have reached first instruction, module directive are now forbidden.
4368 getTargetStreamer().forbidModuleDirective();
4369
Vladimir Medic74593e62013-07-17 15:00:42 +00004370 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004371 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004372 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004373 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004374 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004375 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004376 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004377
4378 // Read the remaining operands.
4379 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4380 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004381 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004382 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004383 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004384 return Error(Loc, "unexpected token in argument list");
4385 }
Toma Tabacu13964452014-09-04 13:23:44 +00004386 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004387 return true;
4388 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004389
Jack Carterd0bd6422013-04-18 00:41:53 +00004390 while (getLexer().is(AsmToken::Comma)) {
4391 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004392 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004393 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004394 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004395 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004396 return Error(Loc, "unexpected token in argument list");
4397 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004398 // Parse bracket and parenthesis suffixes before we iterate
4399 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004400 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004401 return true;
4402 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004403 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004404 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004405 }
4406 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004407 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4408 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004409 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004410 return Error(Loc, "unexpected token in argument list");
4411 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004412 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004413 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004414}
4415
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004416bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004417 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004418 SMLoc Loc = getLexer().getLoc();
4419 Parser.eatToEndOfStatement();
4420 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004421}
4422
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004423bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004424 return Error(Loc, ErrorMsg);
4425}
4426
Jack Carter0b744b32012-10-04 02:29:46 +00004427bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004428 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004429 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004430
4431 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004432 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004433
4434 Parser.Lex(); // Eat "noat".
4435
Jack Carterd0bd6422013-04-18 00:41:53 +00004436 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004437 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004438 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004439 return false;
4440 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004441
4442 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004443 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004444 return false;
4445}
Jack Carterd0bd6422013-04-18 00:41:53 +00004446
Jack Carter0b744b32012-10-04 02:29:46 +00004447bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004448 // Line can be: ".set at", which sets $at to $1
4449 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004450 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004451 Parser.Lex(); // Eat "at".
4452
Jack Carter0b744b32012-10-04 02:29:46 +00004453 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004454 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004455 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004456
4457 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004458 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004459 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004460 }
4461
4462 if (getLexer().isNot(AsmToken::Equal)) {
4463 reportParseError("unexpected token, expected equals sign");
4464 return false;
4465 }
4466 Parser.Lex(); // Eat "=".
4467
4468 if (getLexer().isNot(AsmToken::Dollar)) {
4469 if (getLexer().is(AsmToken::EndOfStatement)) {
4470 reportParseError("no register specified");
4471 return false;
4472 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004473 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004474 return false;
4475 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004476 }
4477 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004478
Toma Tabacu16a74492015-02-13 10:30:57 +00004479 // Find out what "reg" is.
4480 unsigned AtRegNo;
4481 const AsmToken &Reg = Parser.getTok();
4482 if (Reg.is(AsmToken::Identifier)) {
4483 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4484 } else if (Reg.is(AsmToken::Integer)) {
4485 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004486 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004487 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004488 return false;
4489 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004490
4491 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004492 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004493 reportParseError("invalid register");
4494 return false;
4495 }
4496 Parser.Lex(); // Eat "reg".
4497
4498 // If this is not the end of the statement, report an error.
4499 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4500 reportParseError("unexpected token, expected end of statement");
4501 return false;
4502 }
4503
4504 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4505
4506 Parser.Lex(); // Consume the EndOfStatement.
4507 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004508}
4509
4510bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004511 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004512 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004513 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004514 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004515 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004516 return false;
4517 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004518 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004519 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004520 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004521 return false;
4522}
4523
4524bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004525 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004526 Parser.Lex();
4527 // If this is not the end of the statement, report an error.
4528 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004529 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004530 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00004531 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004532 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00004533 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004534 Parser.Lex(); // Consume the EndOfStatement.
4535 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004536}
4537
4538bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004539 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004540 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004541 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004542 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004543 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004544 return false;
4545 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004546 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004547 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004548 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004549 return false;
4550}
4551
4552bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004553 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004554 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004555 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004556 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004557 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004558 return false;
4559 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004560 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00004561 reportParseError("`noreorder' must be set before `nomacro'");
4562 return false;
4563 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004564 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004565 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004566 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004567 return false;
4568}
Jack Carterd76b2372013-03-21 21:44:16 +00004569
Daniel Sanders44934432014-08-07 12:03:36 +00004570bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004571 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004572 Parser.Lex();
4573
4574 // If this is not the end of the statement, report an error.
4575 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004576 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004577
4578 setFeatureBits(Mips::FeatureMSA, "msa");
4579 getTargetStreamer().emitDirectiveSetMsa();
4580 return false;
4581}
4582
4583bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004584 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004585 Parser.Lex();
4586
4587 // If this is not the end of the statement, report an error.
4588 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004589 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004590
4591 clearFeatureBits(Mips::FeatureMSA, "msa");
4592 getTargetStreamer().emitDirectiveSetNoMsa();
4593 return false;
4594}
4595
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004596bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004597 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004598 Parser.Lex(); // Eat "nodsp".
4599
4600 // If this is not the end of the statement, report an error.
4601 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4602 reportParseError("unexpected token, expected end of statement");
4603 return false;
4604 }
4605
4606 clearFeatureBits(Mips::FeatureDSP, "dsp");
4607 getTargetStreamer().emitDirectiveSetNoDsp();
4608 return false;
4609}
4610
Toma Tabacucc2502d2014-11-04 17:18:07 +00004611bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004612 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004613 Parser.Lex(); // Eat "mips16".
4614
Jack Carter39536722014-01-22 23:08:42 +00004615 // 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 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00004618 return false;
4619 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00004620
4621 setFeatureBits(Mips::FeatureMips16, "mips16");
4622 getTargetStreamer().emitDirectiveSetMips16();
4623 Parser.Lex(); // Consume the EndOfStatement.
4624 return false;
4625}
4626
4627bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004628 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004629 Parser.Lex(); // Eat "nomips16".
4630
4631 // If this is not the end of the statement, report an error.
4632 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4633 reportParseError("unexpected token, expected end of statement");
4634 return false;
4635 }
4636
4637 clearFeatureBits(Mips::FeatureMips16, "mips16");
4638 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00004639 Parser.Lex(); // Consume the EndOfStatement.
4640 return false;
4641}
4642
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004643bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004644 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004645 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004646 // Line can be: .set fp=32
4647 // .set fp=xx
4648 // .set fp=64
4649 Parser.Lex(); // Eat fp token
4650 AsmToken Tok = Parser.getTok();
4651 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004652 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004653 return false;
4654 }
4655 Parser.Lex(); // Eat '=' token.
4656 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004657
4658 if (!parseFpABIValue(FpAbiVal, ".set"))
4659 return false;
4660
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004661 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004662 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004663 return false;
4664 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004665 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004666 Parser.Lex(); // Consume the EndOfStatement.
4667 return false;
4668}
4669
Toma Tabacu32c72aa2015-06-30 09:36:50 +00004670bool MipsAsmParser::parseSetOddSPRegDirective() {
4671 MCAsmParser &Parser = getParser();
4672
4673 Parser.Lex(); // Eat "oddspreg".
4674 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4675 reportParseError("unexpected token, expected end of statement");
4676 return false;
4677 }
4678
4679 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4680 getTargetStreamer().emitDirectiveSetOddSPReg();
4681 return false;
4682}
4683
4684bool MipsAsmParser::parseSetNoOddSPRegDirective() {
4685 MCAsmParser &Parser = getParser();
4686
4687 Parser.Lex(); // Eat "nooddspreg".
4688 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4689 reportParseError("unexpected token, expected end of statement");
4690 return false;
4691 }
4692
4693 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4694 getTargetStreamer().emitDirectiveSetNoOddSPReg();
4695 return false;
4696}
4697
Toma Tabacu9db22db2014-09-09 10:15:38 +00004698bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004699 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004700 SMLoc Loc = getLexer().getLoc();
4701
4702 Parser.Lex();
4703 if (getLexer().isNot(AsmToken::EndOfStatement))
4704 return reportParseError("unexpected token, expected end of statement");
4705
4706 // Always keep an element on the options "stack" to prevent the user
4707 // from changing the initial options. This is how we remember them.
4708 if (AssemblerOptions.size() == 2)
4709 return reportParseError(Loc, ".set pop with no .set push");
4710
4711 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00004712 setAvailableFeatures(
4713 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
4714 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00004715
4716 getTargetStreamer().emitDirectiveSetPop();
4717 return false;
4718}
4719
4720bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004721 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004722 Parser.Lex();
4723 if (getLexer().isNot(AsmToken::EndOfStatement))
4724 return reportParseError("unexpected token, expected end of statement");
4725
4726 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00004727 AssemblerOptions.push_back(
4728 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00004729
4730 getTargetStreamer().emitDirectiveSetPush();
4731 return false;
4732}
4733
Toma Tabacu29696502015-06-02 09:48:04 +00004734bool MipsAsmParser::parseSetSoftFloatDirective() {
4735 MCAsmParser &Parser = getParser();
4736 Parser.Lex();
4737 if (getLexer().isNot(AsmToken::EndOfStatement))
4738 return reportParseError("unexpected token, expected end of statement");
4739
4740 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4741 getTargetStreamer().emitDirectiveSetSoftFloat();
4742 return false;
4743}
4744
4745bool MipsAsmParser::parseSetHardFloatDirective() {
4746 MCAsmParser &Parser = getParser();
4747 Parser.Lex();
4748 if (getLexer().isNot(AsmToken::EndOfStatement))
4749 return reportParseError("unexpected token, expected end of statement");
4750
4751 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4752 getTargetStreamer().emitDirectiveSetHardFloat();
4753 return false;
4754}
4755
Jack Carterd76b2372013-03-21 21:44:16 +00004756bool MipsAsmParser::parseSetAssignment() {
4757 StringRef Name;
4758 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00004759 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00004760
4761 if (Parser.parseIdentifier(Name))
4762 reportParseError("expected identifier after .set");
4763
4764 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004765 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00004766 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00004767
Jack Carter3b2c96e2014-01-22 23:31:38 +00004768 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00004769 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00004770
Jim Grosbach6f482002015-05-18 18:43:14 +00004771 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00004772 Sym->setVariableValue(Value);
4773
4774 return false;
4775}
Jack Carterd0bd6422013-04-18 00:41:53 +00004776
Toma Tabacu26647792014-09-09 12:52:14 +00004777bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004778 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00004779 Parser.Lex();
4780 if (getLexer().isNot(AsmToken::EndOfStatement))
4781 return reportParseError("unexpected token, expected end of statement");
4782
4783 // Reset assembler options to their initial values.
Toma Tabacu465acfd2015-06-09 13:33:26 +00004784 setAvailableFeatures(
4785 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
4786 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00004787 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
4788
4789 getTargetStreamer().emitDirectiveSetMips0();
4790 return false;
4791}
4792
Toma Tabacu85618b32014-08-19 14:22:52 +00004793bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004794 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00004795 Parser.Lex();
4796 if (getLexer().isNot(AsmToken::Equal))
4797 return reportParseError("unexpected token, expected equals sign");
4798
4799 Parser.Lex();
4800 StringRef Arch;
4801 if (Parser.parseIdentifier(Arch))
4802 return reportParseError("expected arch identifier");
4803
4804 StringRef ArchFeatureName =
4805 StringSwitch<StringRef>(Arch)
4806 .Case("mips1", "mips1")
4807 .Case("mips2", "mips2")
4808 .Case("mips3", "mips3")
4809 .Case("mips4", "mips4")
4810 .Case("mips5", "mips5")
4811 .Case("mips32", "mips32")
4812 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004813 .Case("mips32r3", "mips32r3")
4814 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004815 .Case("mips32r6", "mips32r6")
4816 .Case("mips64", "mips64")
4817 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004818 .Case("mips64r3", "mips64r3")
4819 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004820 .Case("mips64r6", "mips64r6")
4821 .Case("cnmips", "cnmips")
4822 .Case("r4000", "mips3") // This is an implementation of Mips3.
4823 .Default("");
4824
4825 if (ArchFeatureName.empty())
4826 return reportParseError("unsupported architecture");
4827
4828 selectArch(ArchFeatureName);
4829 getTargetStreamer().emitDirectiveSetArch(Arch);
4830 return false;
4831}
4832
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004833bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004834 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004835 Parser.Lex();
4836 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004837 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004838
Matheus Almeida2852af82014-04-22 10:15:54 +00004839 switch (Feature) {
4840 default:
4841 llvm_unreachable("Unimplemented feature");
4842 case Mips::FeatureDSP:
4843 setFeatureBits(Mips::FeatureDSP, "dsp");
4844 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004845 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004846 case Mips::FeatureMicroMips:
4847 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004848 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004849 case Mips::FeatureMips1:
4850 selectArch("mips1");
4851 getTargetStreamer().emitDirectiveSetMips1();
4852 break;
4853 case Mips::FeatureMips2:
4854 selectArch("mips2");
4855 getTargetStreamer().emitDirectiveSetMips2();
4856 break;
4857 case Mips::FeatureMips3:
4858 selectArch("mips3");
4859 getTargetStreamer().emitDirectiveSetMips3();
4860 break;
4861 case Mips::FeatureMips4:
4862 selectArch("mips4");
4863 getTargetStreamer().emitDirectiveSetMips4();
4864 break;
4865 case Mips::FeatureMips5:
4866 selectArch("mips5");
4867 getTargetStreamer().emitDirectiveSetMips5();
4868 break;
4869 case Mips::FeatureMips32:
4870 selectArch("mips32");
4871 getTargetStreamer().emitDirectiveSetMips32();
4872 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004873 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004874 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004875 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004876 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004877 case Mips::FeatureMips32r3:
4878 selectArch("mips32r3");
4879 getTargetStreamer().emitDirectiveSetMips32R3();
4880 break;
4881 case Mips::FeatureMips32r5:
4882 selectArch("mips32r5");
4883 getTargetStreamer().emitDirectiveSetMips32R5();
4884 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004885 case Mips::FeatureMips32r6:
4886 selectArch("mips32r6");
4887 getTargetStreamer().emitDirectiveSetMips32R6();
4888 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004889 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004890 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00004891 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00004892 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004893 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004894 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004895 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00004896 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004897 case Mips::FeatureMips64r3:
4898 selectArch("mips64r3");
4899 getTargetStreamer().emitDirectiveSetMips64R3();
4900 break;
4901 case Mips::FeatureMips64r5:
4902 selectArch("mips64r5");
4903 getTargetStreamer().emitDirectiveSetMips64R5();
4904 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004905 case Mips::FeatureMips64r6:
4906 selectArch("mips64r6");
4907 getTargetStreamer().emitDirectiveSetMips64R6();
4908 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004909 }
4910 return false;
4911}
4912
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004913bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004914 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004915 if (getLexer().isNot(AsmToken::Comma)) {
4916 SMLoc Loc = getLexer().getLoc();
4917 Parser.eatToEndOfStatement();
4918 return Error(Loc, ErrorStr);
4919 }
4920
Matheus Almeida2852af82014-04-22 10:15:54 +00004921 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004922 return true;
4923}
4924
Daniel Sanderse2982ad2015-09-17 16:08:39 +00004925// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
4926// In this class, it is only used for .cprestore.
4927// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
4928// MipsTargetELFStreamer and MipsAsmParser.
4929bool MipsAsmParser::isPicAndNotNxxAbi() {
4930 return inPicMode() && !(isABI_N32() || isABI_N64());
4931}
4932
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004933bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00004934 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00004935 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004936
Toma Tabacudde4c462014-11-06 10:02:45 +00004937 if (inMips16Mode()) {
4938 reportParseError(".cpload is not supported in Mips16 mode");
4939 return false;
4940 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004941
David Blaikie960ea3f2014-06-08 16:18:35 +00004942 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00004943 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004944 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4945 reportParseError("expected register containing function address");
4946 return false;
4947 }
4948
David Blaikie960ea3f2014-06-08 16:18:35 +00004949 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
4950 if (!RegOpnd.isGPRAsmReg()) {
4951 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004952 return false;
4953 }
4954
Toma Tabacudde4c462014-11-06 10:02:45 +00004955 // If this is not the end of the statement, report an error.
4956 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4957 reportParseError("unexpected token, expected end of statement");
4958 return false;
4959 }
4960
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004961 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004962 return false;
4963}
4964
Daniel Sanderse2982ad2015-09-17 16:08:39 +00004965bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
4966 MCAsmParser &Parser = getParser();
4967
4968 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
4969 // is used in non-PIC mode.
4970
4971 if (inMips16Mode()) {
4972 reportParseError(".cprestore is not supported in Mips16 mode");
4973 return false;
4974 }
4975
4976 // Get the stack offset value.
4977 const MCExpr *StackOffset;
4978 int64_t StackOffsetVal;
4979 if (Parser.parseExpression(StackOffset)) {
4980 reportParseError("expected stack offset value");
4981 return false;
4982 }
4983
4984 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
4985 reportParseError("stack offset is not an absolute expression");
4986 return false;
4987 }
4988
4989 if (StackOffsetVal < 0) {
4990 Warning(Loc, ".cprestore with negative stack offset has no effect");
4991 IsCpRestoreSet = false;
4992 } else {
4993 IsCpRestoreSet = true;
4994 CpRestoreOffset = StackOffsetVal;
4995 }
4996
4997 // If this is not the end of the statement, report an error.
4998 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4999 reportParseError("unexpected token, expected end of statement");
5000 return false;
5001 }
5002
5003 // Store the $gp on the stack.
5004 SmallVector<MCInst, 3> StoreInsts;
5005 createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc,
5006 StoreInsts);
5007
5008 getTargetStreamer().emitDirectiveCpRestore(StoreInsts, CpRestoreOffset);
5009 Parser.Lex(); // Consume the EndOfStatement.
5010 return false;
5011}
5012
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005013bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005014 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005015 unsigned FuncReg;
5016 unsigned Save;
5017 bool SaveIsReg = true;
5018
Matheus Almeida7e815762014-06-18 13:08:59 +00005019 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005020 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005021 if (ResTy == MatchOperand_NoMatch) {
5022 reportParseError("expected register containing function address");
5023 Parser.eatToEndOfStatement();
5024 return false;
5025 }
5026
5027 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5028 if (!FuncRegOpnd.isGPRAsmReg()) {
5029 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
5030 Parser.eatToEndOfStatement();
5031 return false;
5032 }
5033
5034 FuncReg = FuncRegOpnd.getGPR32Reg();
5035 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005036
Toma Tabacu65f10572014-09-16 15:00:52 +00005037 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005038 return true;
5039
Toma Tabacu13964452014-09-04 13:23:44 +00005040 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005041 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005042 const MCExpr *OffsetExpr;
5043 int64_t OffsetVal;
5044 SMLoc ExprLoc = getLexer().getLoc();
5045
5046 if (Parser.parseExpression(OffsetExpr) ||
5047 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5048 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005049 Parser.eatToEndOfStatement();
5050 return false;
5051 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005052
5053 Save = OffsetVal;
5054 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005055 } else {
5056 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5057 if (!SaveOpnd.isGPRAsmReg()) {
5058 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5059 Parser.eatToEndOfStatement();
5060 return false;
5061 }
5062 Save = SaveOpnd.getGPR32Reg();
5063 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005064
Toma Tabacu65f10572014-09-16 15:00:52 +00005065 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005066 return true;
5067
Toma Tabacu8874eac2015-02-18 13:46:53 +00005068 const MCExpr *Expr;
5069 if (Parser.parseExpression(Expr)) {
5070 reportParseError("expected expression");
5071 return false;
5072 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005073
Toma Tabacu8874eac2015-02-18 13:46:53 +00005074 if (Expr->getKind() != MCExpr::SymbolRef) {
5075 reportParseError("expected symbol");
5076 return false;
5077 }
5078 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5079
Daniel Sandersf173dda2015-09-22 10:50:09 +00005080 CpSaveLocation = Save;
5081 CpSaveLocationIsRegister = SaveIsReg;
5082
Toma Tabacu8874eac2015-02-18 13:46:53 +00005083 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5084 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005085 return false;
5086}
5087
Daniel Sandersf173dda2015-09-22 10:50:09 +00005088bool MipsAsmParser::parseDirectiveCPReturn() {
5089 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5090 CpSaveLocationIsRegister);
5091 return false;
5092}
5093
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005094bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005095 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005096 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5097 const AsmToken &Tok = Parser.getTok();
5098
5099 if (Tok.getString() == "2008") {
5100 Parser.Lex();
5101 getTargetStreamer().emitDirectiveNaN2008();
5102 return false;
5103 } else if (Tok.getString() == "legacy") {
5104 Parser.Lex();
5105 getTargetStreamer().emitDirectiveNaNLegacy();
5106 return false;
5107 }
5108 }
5109 // If we don't recognize the option passed to the .nan
5110 // directive (e.g. no option or unknown option), emit an error.
5111 reportParseError("invalid option in .nan directive");
5112 return false;
5113}
5114
Jack Carter0b744b32012-10-04 02:29:46 +00005115bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005116 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005117 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005118 const AsmToken &Tok = Parser.getTok();
5119
5120 if (Tok.getString() == "noat") {
5121 return parseSetNoAtDirective();
5122 } else if (Tok.getString() == "at") {
5123 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005124 } else if (Tok.getString() == "arch") {
5125 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005126 } else if (Tok.getString() == "fp") {
5127 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005128 } else if (Tok.getString() == "oddspreg") {
5129 return parseSetOddSPRegDirective();
5130 } else if (Tok.getString() == "nooddspreg") {
5131 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005132 } else if (Tok.getString() == "pop") {
5133 return parseSetPopDirective();
5134 } else if (Tok.getString() == "push") {
5135 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005136 } else if (Tok.getString() == "reorder") {
5137 return parseSetReorderDirective();
5138 } else if (Tok.getString() == "noreorder") {
5139 return parseSetNoReorderDirective();
5140 } else if (Tok.getString() == "macro") {
5141 return parseSetMacroDirective();
5142 } else if (Tok.getString() == "nomacro") {
5143 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005144 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005145 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005146 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005147 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005148 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005149 getTargetStreamer().emitDirectiveSetNoMicroMips();
5150 Parser.eatToEndOfStatement();
5151 return false;
5152 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005153 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005154 } else if (Tok.getString() == "mips0") {
5155 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005156 } else if (Tok.getString() == "mips1") {
5157 return parseSetFeature(Mips::FeatureMips1);
5158 } else if (Tok.getString() == "mips2") {
5159 return parseSetFeature(Mips::FeatureMips2);
5160 } else if (Tok.getString() == "mips3") {
5161 return parseSetFeature(Mips::FeatureMips3);
5162 } else if (Tok.getString() == "mips4") {
5163 return parseSetFeature(Mips::FeatureMips4);
5164 } else if (Tok.getString() == "mips5") {
5165 return parseSetFeature(Mips::FeatureMips5);
5166 } else if (Tok.getString() == "mips32") {
5167 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005168 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005169 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005170 } else if (Tok.getString() == "mips32r3") {
5171 return parseSetFeature(Mips::FeatureMips32r3);
5172 } else if (Tok.getString() == "mips32r5") {
5173 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005174 } else if (Tok.getString() == "mips32r6") {
5175 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005176 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005177 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005178 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005179 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005180 } else if (Tok.getString() == "mips64r3") {
5181 return parseSetFeature(Mips::FeatureMips64r3);
5182 } else if (Tok.getString() == "mips64r5") {
5183 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005184 } else if (Tok.getString() == "mips64r6") {
5185 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005186 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005187 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005188 } else if (Tok.getString() == "nodsp") {
5189 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005190 } else if (Tok.getString() == "msa") {
5191 return parseSetMsaDirective();
5192 } else if (Tok.getString() == "nomsa") {
5193 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005194 } else if (Tok.getString() == "softfloat") {
5195 return parseSetSoftFloatDirective();
5196 } else if (Tok.getString() == "hardfloat") {
5197 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005198 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005199 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005200 parseSetAssignment();
5201 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005202 }
Jack Carter07c818d2013-01-25 01:31:34 +00005203
Jack Carter0b744b32012-10-04 02:29:46 +00005204 return true;
5205}
5206
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005207/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005208/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005209bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005210 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005211 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5212 for (;;) {
5213 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005214 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005215 return true;
5216
5217 getParser().getStreamer().EmitValue(Value, Size);
5218
5219 if (getLexer().is(AsmToken::EndOfStatement))
5220 break;
5221
Jack Carter07c818d2013-01-25 01:31:34 +00005222 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005223 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005224 Parser.Lex();
5225 }
5226 }
5227
5228 Parser.Lex();
5229 return false;
5230}
5231
Vladimir Medic4c299852013-11-06 11:27:05 +00005232/// parseDirectiveGpWord
5233/// ::= .gpword local_sym
5234bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005235 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005236 const MCExpr *Value;
5237 // EmitGPRel32Value requires an expression, so we are using base class
5238 // method to evaluate the expression.
5239 if (getParser().parseExpression(Value))
5240 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005241 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005242
Vladimir Medice10c1122013-11-13 13:18:04 +00005243 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005244 return Error(getLexer().getLoc(),
5245 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005246 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005247 return false;
5248}
5249
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005250/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005251/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005252bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005253 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005254 const MCExpr *Value;
5255 // EmitGPRel64Value requires an expression, so we are using base class
5256 // method to evaluate the expression.
5257 if (getParser().parseExpression(Value))
5258 return true;
5259 getParser().getStreamer().EmitGPRel64Value(Value);
5260
5261 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005262 return Error(getLexer().getLoc(),
5263 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005264 Parser.Lex(); // Eat EndOfStatement token.
5265 return false;
5266}
5267
Jack Carter0cd3c192014-01-06 23:27:31 +00005268bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005269 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005270 // Get the option token.
5271 AsmToken Tok = Parser.getTok();
5272 // At the moment only identifiers are supported.
5273 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005274 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005275 Parser.eatToEndOfStatement();
5276 return false;
5277 }
5278
5279 StringRef Option = Tok.getIdentifier();
5280
5281 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005282 // MipsAsmParser needs to know if the current PIC mode changes.
5283 IsPicEnabled = false;
5284
Jack Carter0cd3c192014-01-06 23:27:31 +00005285 getTargetStreamer().emitDirectiveOptionPic0();
5286 Parser.Lex();
5287 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5288 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005289 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005290 Parser.eatToEndOfStatement();
5291 }
5292 return false;
5293 }
5294
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005295 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005296 // MipsAsmParser needs to know if the current PIC mode changes.
5297 IsPicEnabled = true;
5298
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005299 getTargetStreamer().emitDirectiveOptionPic2();
5300 Parser.Lex();
5301 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5302 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005303 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005304 Parser.eatToEndOfStatement();
5305 }
5306 return false;
5307 }
5308
Jack Carter0cd3c192014-01-06 23:27:31 +00005309 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005310 Warning(Parser.getTok().getLoc(),
5311 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005312 Parser.eatToEndOfStatement();
5313 return false;
5314}
5315
Toma Tabacu9ca50962015-04-16 09:53:47 +00005316/// parseInsnDirective
5317/// ::= .insn
5318bool MipsAsmParser::parseInsnDirective() {
5319 // If this is not the end of the statement, report an error.
5320 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5321 reportParseError("unexpected token, expected end of statement");
5322 return false;
5323 }
5324
5325 // The actual label marking happens in
5326 // MipsELFStreamer::createPendingLabelRelocs().
5327 getTargetStreamer().emitDirectiveInsn();
5328
5329 getParser().Lex(); // Eat EndOfStatement token.
5330 return false;
5331}
5332
Daniel Sanders7e527422014-07-10 13:38:23 +00005333/// parseDirectiveModule
5334/// ::= .module oddspreg
5335/// ::= .module nooddspreg
5336/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005337/// ::= .module softfloat
5338/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005339bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005340 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005341 MCAsmLexer &Lexer = getLexer();
5342 SMLoc L = Lexer.getLoc();
5343
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005344 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005345 // TODO : get a better message.
5346 reportParseError(".module directive must appear before any code");
5347 return false;
5348 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005349
Toma Tabacuc405c822015-01-23 10:40:19 +00005350 StringRef Option;
5351 if (Parser.parseIdentifier(Option)) {
5352 reportParseError("expected .module option identifier");
5353 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005354 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005355
Toma Tabacuc405c822015-01-23 10:40:19 +00005356 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005357 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005358
Toma Tabacu3c499582015-06-25 10:56:57 +00005359 // Synchronize the abiflags information with the FeatureBits information we
5360 // changed above.
5361 getTargetStreamer().updateABIInfo(*this);
5362
5363 // If printing assembly, use the recently updated abiflags information.
5364 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5365 // emitted at the end).
5366 getTargetStreamer().emitDirectiveModuleOddSPReg();
5367
Toma Tabacuc405c822015-01-23 10:40:19 +00005368 // If this is not the end of the statement, report an error.
5369 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5370 reportParseError("unexpected token, expected end of statement");
5371 return false;
5372 }
5373
5374 return false; // parseDirectiveModule has finished successfully.
5375 } else if (Option == "nooddspreg") {
5376 if (!isABI_O32()) {
5377 Error(L, "'.module nooddspreg' requires the O32 ABI");
5378 return false;
5379 }
5380
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005381 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005382
Toma Tabacu3c499582015-06-25 10:56:57 +00005383 // Synchronize the abiflags information with the FeatureBits information we
5384 // changed above.
5385 getTargetStreamer().updateABIInfo(*this);
5386
5387 // If printing assembly, use the recently updated abiflags information.
5388 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5389 // emitted at the end).
5390 getTargetStreamer().emitDirectiveModuleOddSPReg();
5391
Toma Tabacuc405c822015-01-23 10:40:19 +00005392 // If this is not the end of the statement, report an error.
5393 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5394 reportParseError("unexpected token, expected end of statement");
5395 return false;
5396 }
5397
5398 return false; // parseDirectiveModule has finished successfully.
5399 } else if (Option == "fp") {
5400 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005401 } else if (Option == "softfloat") {
5402 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5403
5404 // Synchronize the ABI Flags information with the FeatureBits information we
5405 // updated above.
5406 getTargetStreamer().updateABIInfo(*this);
5407
5408 // If printing assembly, use the recently updated ABI Flags information.
5409 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5410 // emitted later).
5411 getTargetStreamer().emitDirectiveModuleSoftFloat();
5412
5413 // If this is not the end of the statement, report an error.
5414 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5415 reportParseError("unexpected token, expected end of statement");
5416 return false;
5417 }
5418
5419 return false; // parseDirectiveModule has finished successfully.
5420 } else if (Option == "hardfloat") {
5421 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5422
5423 // Synchronize the ABI Flags information with the FeatureBits information we
5424 // updated above.
5425 getTargetStreamer().updateABIInfo(*this);
5426
5427 // If printing assembly, use the recently updated ABI Flags information.
5428 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5429 // emitted later).
5430 getTargetStreamer().emitDirectiveModuleHardFloat();
5431
5432 // If this is not the end of the statement, report an error.
5433 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5434 reportParseError("unexpected token, expected end of statement");
5435 return false;
5436 }
5437
5438 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005439 } else {
5440 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5441 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005442}
5443
5444/// parseDirectiveModuleFP
5445/// ::= =32
5446/// ::= =xx
5447/// ::= =64
5448bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005449 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005450 MCAsmLexer &Lexer = getLexer();
5451
5452 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005453 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005454 return false;
5455 }
5456 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005457
Daniel Sanders7e527422014-07-10 13:38:23 +00005458 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005459 if (!parseFpABIValue(FpABI, ".module"))
5460 return false;
5461
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005462 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005463 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005464 return false;
5465 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005466
Toma Tabacua64e5402015-06-25 12:44:38 +00005467 // Synchronize the abiflags information with the FeatureBits information we
5468 // changed above.
5469 getTargetStreamer().updateABIInfo(*this);
5470
5471 // If printing assembly, use the recently updated abiflags information.
5472 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5473 // emitted at the end).
5474 getTargetStreamer().emitDirectiveModuleFP();
5475
Daniel Sanders7e527422014-07-10 13:38:23 +00005476 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005477 return false;
5478}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005479
Daniel Sanders7e527422014-07-10 13:38:23 +00005480bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005481 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005482 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005483 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005484 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005485
5486 if (Lexer.is(AsmToken::Identifier)) {
5487 StringRef Value = Parser.getTok().getString();
5488 Parser.Lex();
5489
5490 if (Value != "xx") {
5491 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5492 return false;
5493 }
5494
5495 if (!isABI_O32()) {
5496 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5497 return false;
5498 }
5499
Daniel Sanders7e527422014-07-10 13:38:23 +00005500 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005501 if (ModuleLevelOptions) {
5502 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5503 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5504 } else {
5505 setFeatureBits(Mips::FeatureFPXX, "fpxx");
5506 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5507 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005508 return true;
5509 }
5510
5511 if (Lexer.is(AsmToken::Integer)) {
5512 unsigned Value = Parser.getTok().getIntVal();
5513 Parser.Lex();
5514
5515 if (Value != 32 && Value != 64) {
5516 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5517 return false;
5518 }
5519
5520 if (Value == 32) {
5521 if (!isABI_O32()) {
5522 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
5523 return false;
5524 }
5525
Daniel Sanders7e527422014-07-10 13:38:23 +00005526 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005527 if (ModuleLevelOptions) {
5528 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5529 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5530 } else {
5531 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5532 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5533 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005534 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00005535 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005536 if (ModuleLevelOptions) {
5537 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5538 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5539 } else {
5540 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5541 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
5542 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005543 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005544
Daniel Sanders7e527422014-07-10 13:38:23 +00005545 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005546 }
5547
5548 return false;
5549}
5550
Jack Carter0b744b32012-10-04 02:29:46 +00005551bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005552 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005553 StringRef IDVal = DirectiveID.getString();
5554
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005555 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005556 return parseDirectiveCpLoad(DirectiveID.getLoc());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005557 if (IDVal == ".cprestore")
5558 return parseDirectiveCpRestore(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00005559 if (IDVal == ".dword") {
5560 parseDataDirective(8, DirectiveID.getLoc());
5561 return false;
5562 }
Jack Carterd0bd6422013-04-18 00:41:53 +00005563 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005564 StringRef SymbolName;
5565
5566 if (Parser.parseIdentifier(SymbolName)) {
5567 reportParseError("expected identifier after .ent");
5568 return false;
5569 }
5570
5571 // There's an undocumented extension that allows an integer to
5572 // follow the name of the procedure which AFAICS is ignored by GAS.
5573 // Example: .ent foo,2
5574 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5575 if (getLexer().isNot(AsmToken::Comma)) {
5576 // Even though we accept this undocumented extension for compatibility
5577 // reasons, the additional integer argument does not actually change
5578 // the behaviour of the '.ent' directive, so we would like to discourage
5579 // its use. We do this by not referring to the extended version in
5580 // error messages which are not directly related to its use.
5581 reportParseError("unexpected token, expected end of statement");
5582 return false;
5583 }
5584 Parser.Lex(); // Eat the comma.
5585 const MCExpr *DummyNumber;
5586 int64_t DummyNumberVal;
5587 // If the user was explicitly trying to use the extended version,
5588 // we still give helpful extension-related error messages.
5589 if (Parser.parseExpression(DummyNumber)) {
5590 reportParseError("expected number after comma");
5591 return false;
5592 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00005593 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005594 reportParseError("expected an absolute expression after comma");
5595 return false;
5596 }
5597 }
5598
5599 // If this is not the end of the statement, report an error.
5600 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5601 reportParseError("unexpected token, expected end of statement");
5602 return false;
5603 }
5604
Jim Grosbach6f482002015-05-18 18:43:14 +00005605 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005606
5607 getTargetStreamer().emitDirectiveEnt(*Sym);
5608 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005609 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005610 return false;
5611 }
5612
Jack Carter07c818d2013-01-25 01:31:34 +00005613 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005614 StringRef SymbolName;
5615
5616 if (Parser.parseIdentifier(SymbolName)) {
5617 reportParseError("expected identifier after .end");
5618 return false;
5619 }
5620
5621 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5622 reportParseError("unexpected token, expected end of statement");
5623 return false;
5624 }
5625
5626 if (CurrentFn == nullptr) {
5627 reportParseError(".end used without .ent");
5628 return false;
5629 }
5630
5631 if ((SymbolName != CurrentFn->getName())) {
5632 reportParseError(".end symbol does not match .ent symbol");
5633 return false;
5634 }
5635
5636 getTargetStreamer().emitDirectiveEnd(SymbolName);
5637 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005638 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005639 return false;
5640 }
5641
Jack Carter07c818d2013-01-25 01:31:34 +00005642 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005643 // .frame $stack_reg, frame_size_in_bytes, $return_reg
5644 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005645 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005646 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5647 reportParseError("expected stack register");
5648 return false;
5649 }
5650
5651 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5652 if (!StackRegOpnd.isGPRAsmReg()) {
5653 reportParseError(StackRegOpnd.getStartLoc(),
5654 "expected general purpose register");
5655 return false;
5656 }
5657 unsigned StackReg = StackRegOpnd.getGPR32Reg();
5658
5659 if (Parser.getTok().is(AsmToken::Comma))
5660 Parser.Lex();
5661 else {
5662 reportParseError("unexpected token, expected comma");
5663 return false;
5664 }
5665
5666 // Parse the frame size.
5667 const MCExpr *FrameSize;
5668 int64_t FrameSizeVal;
5669
5670 if (Parser.parseExpression(FrameSize)) {
5671 reportParseError("expected frame size value");
5672 return false;
5673 }
5674
Jim Grosbach13760bd2015-05-30 01:25:56 +00005675 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005676 reportParseError("frame size not an absolute expression");
5677 return false;
5678 }
5679
5680 if (Parser.getTok().is(AsmToken::Comma))
5681 Parser.Lex();
5682 else {
5683 reportParseError("unexpected token, expected comma");
5684 return false;
5685 }
5686
5687 // Parse the return register.
5688 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00005689 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005690 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5691 reportParseError("expected return register");
5692 return false;
5693 }
5694
5695 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5696 if (!ReturnRegOpnd.isGPRAsmReg()) {
5697 reportParseError(ReturnRegOpnd.getStartLoc(),
5698 "expected general purpose register");
5699 return false;
5700 }
5701
5702 // If this is not the end of the statement, report an error.
5703 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5704 reportParseError("unexpected token, expected end of statement");
5705 return false;
5706 }
5707
5708 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
5709 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005710 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005711 return false;
5712 }
5713
Jack Carter07c818d2013-01-25 01:31:34 +00005714 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00005715 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00005716 }
5717
Daniel Sandersd97a6342014-08-13 10:07:34 +00005718 if (IDVal == ".mask" || IDVal == ".fmask") {
5719 // .mask bitmask, frame_offset
5720 // bitmask: One bit for each register used.
5721 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
5722 // first register is expected to be saved.
5723 // Examples:
5724 // .mask 0x80000000, -4
5725 // .fmask 0x80000000, -4
5726 //
Jack Carterbe332172012-09-07 00:48:02 +00005727
Daniel Sandersd97a6342014-08-13 10:07:34 +00005728 // Parse the bitmask
5729 const MCExpr *BitMask;
5730 int64_t BitMaskVal;
5731
5732 if (Parser.parseExpression(BitMask)) {
5733 reportParseError("expected bitmask value");
5734 return false;
5735 }
5736
Jim Grosbach13760bd2015-05-30 01:25:56 +00005737 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005738 reportParseError("bitmask not an absolute expression");
5739 return false;
5740 }
5741
5742 if (Parser.getTok().is(AsmToken::Comma))
5743 Parser.Lex();
5744 else {
5745 reportParseError("unexpected token, expected comma");
5746 return false;
5747 }
5748
5749 // Parse the frame_offset
5750 const MCExpr *FrameOffset;
5751 int64_t FrameOffsetVal;
5752
5753 if (Parser.parseExpression(FrameOffset)) {
5754 reportParseError("expected frame offset value");
5755 return false;
5756 }
5757
Jim Grosbach13760bd2015-05-30 01:25:56 +00005758 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005759 reportParseError("frame offset not an absolute expression");
5760 return false;
5761 }
5762
5763 // If this is not the end of the statement, report an error.
5764 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5765 reportParseError("unexpected token, expected end of statement");
5766 return false;
5767 }
5768
5769 if (IDVal == ".mask")
5770 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
5771 else
5772 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00005773 return false;
5774 }
5775
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005776 if (IDVal == ".nan")
5777 return parseDirectiveNaN();
5778
Jack Carter07c818d2013-01-25 01:31:34 +00005779 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005780 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00005781 return false;
5782 }
5783
Rafael Espindolab59fb732014-03-28 18:50:26 +00005784 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005785 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005786 return false;
5787 }
5788
Jack Carter07c818d2013-01-25 01:31:34 +00005789 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005790 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00005791 return false;
5792 }
5793
Jack Carter0cd3c192014-01-06 23:27:31 +00005794 if (IDVal == ".option")
5795 return parseDirectiveOption();
5796
5797 if (IDVal == ".abicalls") {
5798 getTargetStreamer().emitDirectiveAbiCalls();
5799 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005800 Error(Parser.getTok().getLoc(),
5801 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005802 // Clear line
5803 Parser.eatToEndOfStatement();
5804 }
5805 return false;
5806 }
5807
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005808 if (IDVal == ".cpsetup")
5809 return parseDirectiveCPSetup();
5810
Daniel Sandersf173dda2015-09-22 10:50:09 +00005811 if (IDVal == ".cpreturn")
5812 return parseDirectiveCPReturn();
5813
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005814 if (IDVal == ".module")
5815 return parseDirectiveModule();
5816
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005817 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
5818 return parseInternalDirectiveReallowModule();
5819
Toma Tabacu9ca50962015-04-16 09:53:47 +00005820 if (IDVal == ".insn")
5821 return parseInsnDirective();
5822
Rafael Espindola870c4e92012-01-11 03:56:41 +00005823 return true;
5824}
5825
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005826bool MipsAsmParser::parseInternalDirectiveReallowModule() {
5827 // If this is not the end of the statement, report an error.
5828 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5829 reportParseError("unexpected token, expected end of statement");
5830 return false;
5831 }
5832
5833 getTargetStreamer().reallowModuleDirective();
5834
5835 getParser().Lex(); // Eat EndOfStatement token.
5836 return false;
5837}
5838
Rafael Espindola870c4e92012-01-11 03:56:41 +00005839extern "C" void LLVMInitializeMipsAsmParser() {
5840 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
5841 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
5842 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
5843 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
5844}
Jack Carterb4dbc172012-09-05 23:34:03 +00005845
5846#define GET_REGISTER_MATCHER
5847#define GET_MATCHER_IMPLEMENTATION
5848#include "MipsGenAsmMatcher.inc"