blob: 34c4b47e7b4f2e558adae3001c8638269828a6e9 [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
Daniel Sanders6394ee52015-10-15 14:52:58 +0000218 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
219 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000220
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000221 bool expandUlw(MCInst &Inst, SMLoc IDLoc,
222 SmallVectorImpl<MCInst> &Instructions);
223
Toma Tabacu234482a2015-03-16 12:03:39 +0000224 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
225 SmallVectorImpl<MCInst> &Instructions);
226
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000227 void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +0000228 bool Is64Bit, SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000229
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000230 void createCpRestoreMemOp(bool IsLoad, int StackOffset, SMLoc IDLoc,
231 SmallVectorImpl<MCInst> &Instructions);
232
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000233 bool reportParseError(Twine ErrorMsg);
234 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000235
Jack Carterb5cf5902013-04-17 00:18:04 +0000236 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000237 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000238
Vladimir Medic4c299852013-11-06 11:27:05 +0000239 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000240
241 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000242 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000243 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000244 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000245 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000246 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000247 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000248 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000249 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000250 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000251 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000252 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000253 bool parseInsnDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000254
255 bool parseSetAtDirective();
256 bool parseSetNoAtDirective();
257 bool parseSetMacroDirective();
258 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000259 bool parseSetMsaDirective();
260 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000261 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000262 bool parseSetReorderDirective();
263 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000264 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000265 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000266 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000267 bool parseSetOddSPRegDirective();
268 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000269 bool parseSetPopDirective();
270 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000271 bool parseSetSoftFloatDirective();
272 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000273
Jack Carterd76b2372013-03-21 21:44:16 +0000274 bool parseSetAssignment();
275
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000276 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000277 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000278 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000279 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000280 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000281 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
282 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000283
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000284 bool parseInternalDirectiveReallowModule();
285
Jack Carterdc1e35d2012-09-06 20:00:02 +0000286 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000287
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000288 bool eatComma(StringRef ErrorStr);
289
Jack Carter1ac53222013-02-20 23:11:17 +0000290 int matchCPURegisterName(StringRef Symbol);
291
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000292 int matchHWRegsRegisterName(StringRef Symbol);
293
Jack Carter873c7242013-01-12 01:03:14 +0000294 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000295
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000296 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000297
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000298 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000299
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000300 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000301
Jack Carter5dc8ac92013-09-25 23:50:44 +0000302 int matchMSA128RegisterName(StringRef Name);
303
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000304 int matchMSA128CtrlRegisterName(StringRef Name);
305
Jack Carterd0bd6422013-04-18 00:41:53 +0000306 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000307
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000308 unsigned getGPR(int RegNo);
309
Toma Tabacu89a712b2015-04-15 10:48:56 +0000310 /// Returns the internal register number for the current AT. Also checks if
311 /// the current AT is unavailable (set to $0) and gives an error if it is.
312 /// This should be used in pseudo-instruction expansions which need AT.
313 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000314
315 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000316 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000317
318 // Helper function that checks if the value of a vector index is within the
319 // boundaries of accepted values for each RegisterKind
320 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
321 bool validateMSAIndex(int Val, int RegKind);
322
Daniel Sandersf0df2212014-08-04 12:20:00 +0000323 // Selects a new architecture by updating the FeatureBits with the necessary
324 // info including implied dependencies.
325 // Internally, it clears all the feature bits related to *any* architecture
326 // and selects the new one using the ToggleFeature functionality of the
327 // MCSubtargetInfo object that handles implied dependencies. The reason we
328 // clear all the arch related bits manually is because ToggleFeature only
329 // clears the features that imply the feature being cleared and not the
330 // features implied by the feature being cleared. This is easier to see
331 // with an example:
332 // --------------------------------------------------
333 // | Feature | Implies |
334 // | -------------------------------------------------|
335 // | FeatureMips1 | None |
336 // | FeatureMips2 | FeatureMips1 |
337 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
338 // | FeatureMips4 | FeatureMips3 |
339 // | ... | |
340 // --------------------------------------------------
341 //
342 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
343 // FeatureMipsGP64 | FeatureMips1)
344 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
345 void selectArch(StringRef ArchFeature) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000346 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000347 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
348 STI.setFeatureBits(FeatureBits);
349 setAvailableFeatures(
350 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000351 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000352 }
353
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000354 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000355 if (!(STI.getFeatureBits()[Feature])) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000356 setAvailableFeatures(
357 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000358 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000359 }
360 }
361
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000362 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000363 if (STI.getFeatureBits()[Feature]) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000364 setAvailableFeatures(
365 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000366 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000367 }
368 }
369
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000370 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
371 setFeatureBits(Feature, FeatureString);
372 AssemblerOptions.front()->setFeatures(STI.getFeatureBits());
373 }
374
375 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
376 clearFeatureBits(Feature, FeatureString);
377 AssemblerOptions.front()->setFeatures(STI.getFeatureBits());
378 }
379
Rafael Espindola870c4e92012-01-11 03:56:41 +0000380public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000381 enum MipsMatchResultTy {
382 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
383#define GET_OPERAND_DIAGNOSTIC_TYPES
384#include "MipsGenAsmMatcher.inc"
385#undef GET_OPERAND_DIAGNOSTIC_TYPES
386
387 };
388
Joey Gouly0e76fa72013-09-12 10:28:05 +0000389 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000390 const MCInstrInfo &MII, const MCTargetOptions &Options)
Colin LeMahieufe2c8b82015-07-27 21:56:53 +0000391 : MCTargetAsmParser(Options), STI(sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000392 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
393 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000394 MCAsmParserExtension::Initialize(parser);
395
Toma Tabacu11e14a92015-04-21 11:50:52 +0000396 parser.addAliasForDirective(".asciiz", ".asciz");
397
Jack Carterb4dbc172012-09-05 23:34:03 +0000398 // Initialize the set of available features.
399 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000400
Toma Tabacu9db22db2014-09-09 10:15:38 +0000401 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000402 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000403 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000404
Toma Tabacu9db22db2014-09-09 10:15:38 +0000405 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000406 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000407 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000408
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000409 getTargetStreamer().updateABIInfo(*this);
410
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000411 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000412 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000413
414 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000415
Daniel Sandersa6994442015-08-18 12:33:54 +0000416 IsPicEnabled =
417 (getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_);
418
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000419 IsCpRestoreSet = false;
420 CpRestoreOffset = -1;
421
Daniel Sanders50f17232015-09-15 16:17:27 +0000422 Triple TheTriple(sti.getTargetTriple());
423 if ((TheTriple.getArch() == Triple::mips) ||
424 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000425 IsLittleEndian = false;
426 else
427 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000428 }
429
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000430 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
431 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
432
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000433 bool isGP64bit() const { return STI.getFeatureBits()[Mips::FeatureGP64Bit]; }
434 bool isFP64bit() const { return STI.getFeatureBits()[Mips::FeatureFP64Bit]; }
Eric Christophera5762812015-01-26 17:33:46 +0000435 const MipsABIInfo &getABI() const { return ABI; }
436 bool isABI_N32() const { return ABI.IsN32(); }
437 bool isABI_N64() const { return ABI.IsN64(); }
438 bool isABI_O32() const { return ABI.IsO32(); }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000439 bool isABI_FPXX() const { return STI.getFeatureBits()[Mips::FeatureFPXX]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000440
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000441 bool useOddSPReg() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000442 return !(STI.getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000443 }
444
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000445 bool inMicroMipsMode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000446 return STI.getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000447 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000448 bool hasMips1() const { return STI.getFeatureBits()[Mips::FeatureMips1]; }
449 bool hasMips2() const { return STI.getFeatureBits()[Mips::FeatureMips2]; }
450 bool hasMips3() const { return STI.getFeatureBits()[Mips::FeatureMips3]; }
451 bool hasMips4() const { return STI.getFeatureBits()[Mips::FeatureMips4]; }
452 bool hasMips5() const { return STI.getFeatureBits()[Mips::FeatureMips5]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000453 bool hasMips32() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000454 return STI.getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000455 }
456 bool hasMips64() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000457 return STI.getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000458 }
459 bool hasMips32r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000460 return STI.getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000461 }
462 bool hasMips64r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000463 return STI.getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000464 }
Daniel Sanders17793142015-02-18 16:24:50 +0000465 bool hasMips32r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000466 return (STI.getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000467 }
468 bool hasMips64r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000469 return (STI.getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000470 }
471 bool hasMips32r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000472 return (STI.getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000473 }
474 bool hasMips64r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000475 return (STI.getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000476 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000477 bool hasMips32r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000478 return STI.getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000479 }
480 bool hasMips64r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000481 return STI.getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000482 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000483
484 bool hasDSP() const { return STI.getFeatureBits()[Mips::FeatureDSP]; }
485 bool hasDSPR2() const { return STI.getFeatureBits()[Mips::FeatureDSPR2]; }
Zoran Jovanovic2e386d32015-10-12 16:07:25 +0000486 bool hasDSPR3() const { return STI.getFeatureBits()[Mips::FeatureDSPR3]; }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000487 bool hasMSA() const { return STI.getFeatureBits()[Mips::FeatureMSA]; }
Kai Nackee0245392015-01-27 19:11:28 +0000488 bool hasCnMips() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000489 return (STI.getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000490 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000491
Daniel Sandersa6994442015-08-18 12:33:54 +0000492 bool inPicMode() {
493 return IsPicEnabled;
494 }
495
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000496 bool inMips16Mode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000497 return STI.getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000498 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000499
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000500 bool useTraps() const {
501 return STI.getFeatureBits()[Mips::FeatureUseTCCInDIV];
502 }
503
Eric Christophere8ae3e32015-05-07 23:10:21 +0000504 bool useSoftFloat() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000505 return STI.getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000506 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000507
Toma Tabacud9d344b2015-04-27 14:05:04 +0000508 /// Warn if RegIndex is the same as the current AT.
509 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000510
511 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000512
513 bool isLittle() const { return IsLittleEndian; }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000514};
515}
516
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000517namespace {
518
519/// MipsOperand - Instances of this class represent a parsed Mips machine
520/// instruction.
521class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000522public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000523 /// Broad categories of register classes
524 /// The exact class is finalized by the render method.
525 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000526 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000527 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000528 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000529 RegKind_FCC = 4, /// FCC
530 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
531 RegKind_MSACtrl = 16, /// MSA control registers
532 RegKind_COP2 = 32, /// COP2
533 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
534 /// context).
535 RegKind_CCR = 128, /// CCR
536 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000537 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000538 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000539 /// Potentially any (e.g. $1)
540 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
541 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000542 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000543 };
544
545private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000546 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000547 k_Immediate, /// An immediate (possibly involving symbol references)
548 k_Memory, /// Base + Offset Memory Address
549 k_PhysRegister, /// A physical register from the Mips namespace
550 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000551 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000552 k_RegList, /// A physical register list
553 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000554 } Kind;
555
David Blaikie960ea3f2014-06-08 16:18:35 +0000556public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000557 MipsOperand(KindTy K, MipsAsmParser &Parser)
558 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
559
David Blaikie960ea3f2014-06-08 16:18:35 +0000560private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000561 /// For diagnostics, and checking the assembler temporary
562 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000563
Eric Christopher8996c5d2013-03-15 00:42:55 +0000564 struct Token {
565 const char *Data;
566 unsigned Length;
567 };
568
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000569 struct PhysRegOp {
570 unsigned Num; /// Register Number
571 };
572
573 struct RegIdxOp {
574 unsigned Index; /// Index into the register class
575 RegKind Kind; /// Bitfield of the kinds it could possibly be
576 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000577 };
578
579 struct ImmOp {
580 const MCExpr *Val;
581 };
582
583 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000584 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000585 const MCExpr *Off;
586 };
587
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000588 struct RegListOp {
589 SmallVector<unsigned, 10> *List;
590 };
591
Jack Carterb4dbc172012-09-05 23:34:03 +0000592 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000593 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000594 struct PhysRegOp PhysReg;
595 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000596 struct ImmOp Imm;
597 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000598 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000599 };
600
601 SMLoc StartLoc, EndLoc;
602
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000603 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000604 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
605 const MCRegisterInfo *RegInfo,
606 SMLoc S, SMLoc E,
607 MipsAsmParser &Parser) {
608 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000609 Op->RegIdx.Index = Index;
610 Op->RegIdx.RegInfo = RegInfo;
611 Op->RegIdx.Kind = RegKind;
612 Op->StartLoc = S;
613 Op->EndLoc = E;
614 return Op;
615 }
616
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000617public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000618 /// Coerce the register to GPR32 and return the real register for the current
619 /// target.
620 unsigned getGPR32Reg() const {
621 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000622 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000623 unsigned ClassID = Mips::GPR32RegClassID;
624 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000625 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000626
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000627 /// Coerce the register to GPR32 and return the real register for the current
628 /// target.
629 unsigned getGPRMM16Reg() const {
630 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
631 unsigned ClassID = Mips::GPR32RegClassID;
632 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
633 }
634
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000635 /// Coerce the register to GPR64 and return the real register for the current
636 /// target.
637 unsigned getGPR64Reg() const {
638 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
639 unsigned ClassID = Mips::GPR64RegClassID;
640 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000641 }
642
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000643private:
644 /// Coerce the register to AFGR64 and return the real register for the current
645 /// target.
646 unsigned getAFGR64Reg() const {
647 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
648 if (RegIdx.Index % 2 != 0)
649 AsmParser.Warning(StartLoc, "Float register should be even.");
650 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
651 .getRegister(RegIdx.Index / 2);
652 }
653
654 /// Coerce the register to FGR64 and return the real register for the current
655 /// target.
656 unsigned getFGR64Reg() const {
657 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
658 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
659 .getRegister(RegIdx.Index);
660 }
661
662 /// Coerce the register to FGR32 and return the real register for the current
663 /// target.
664 unsigned getFGR32Reg() const {
665 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
666 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
667 .getRegister(RegIdx.Index);
668 }
669
670 /// Coerce the register to FGRH32 and return the real register for the current
671 /// target.
672 unsigned getFGRH32Reg() const {
673 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
674 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
675 .getRegister(RegIdx.Index);
676 }
677
678 /// Coerce the register to FCC and return the real register for the current
679 /// target.
680 unsigned getFCCReg() const {
681 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
682 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
683 .getRegister(RegIdx.Index);
684 }
685
686 /// Coerce the register to MSA128 and return the real register for the current
687 /// target.
688 unsigned getMSA128Reg() const {
689 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
690 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
691 // identical
692 unsigned ClassID = Mips::MSA128BRegClassID;
693 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
694 }
695
696 /// Coerce the register to MSACtrl and return the real register for the
697 /// current target.
698 unsigned getMSACtrlReg() const {
699 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
700 unsigned ClassID = Mips::MSACtrlRegClassID;
701 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
702 }
703
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000704 /// Coerce the register to COP0 and return the real register for the
705 /// current target.
706 unsigned getCOP0Reg() const {
707 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
708 unsigned ClassID = Mips::COP0RegClassID;
709 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
710 }
711
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000712 /// Coerce the register to COP2 and return the real register for the
713 /// current target.
714 unsigned getCOP2Reg() const {
715 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
716 unsigned ClassID = Mips::COP2RegClassID;
717 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
718 }
719
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000720 /// Coerce the register to COP3 and return the real register for the
721 /// current target.
722 unsigned getCOP3Reg() const {
723 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
724 unsigned ClassID = Mips::COP3RegClassID;
725 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
726 }
727
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000728 /// Coerce the register to ACC64DSP and return the real register for the
729 /// current target.
730 unsigned getACC64DSPReg() const {
731 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
732 unsigned ClassID = Mips::ACC64DSPRegClassID;
733 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
734 }
735
736 /// Coerce the register to HI32DSP and return the real register for the
737 /// current target.
738 unsigned getHI32DSPReg() const {
739 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
740 unsigned ClassID = Mips::HI32DSPRegClassID;
741 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
742 }
743
744 /// Coerce the register to LO32DSP and return the real register for the
745 /// current target.
746 unsigned getLO32DSPReg() const {
747 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
748 unsigned ClassID = Mips::LO32DSPRegClassID;
749 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
750 }
751
752 /// Coerce the register to CCR and return the real register for the
753 /// current target.
754 unsigned getCCRReg() const {
755 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
756 unsigned ClassID = Mips::CCRRegClassID;
757 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
758 }
759
760 /// Coerce the register to HWRegs and return the real register for the
761 /// current target.
762 unsigned getHWRegsReg() const {
763 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
764 unsigned ClassID = Mips::HWRegsRegClassID;
765 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
766 }
767
768public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000769 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000770 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000771 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000772 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000773 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000774 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000775 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000776 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000777 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000778
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000779 void addRegOperands(MCInst &Inst, unsigned N) const {
780 llvm_unreachable("Use a custom parser instead");
781 }
782
Daniel Sanders21bce302014-04-01 12:35:23 +0000783 /// Render the operand to an MCInst as a GPR32
784 /// Asserts if the wrong number of operands are requested, or the operand
785 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000786 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
787 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000788 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000789 }
790
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000791 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
792 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000793 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000794 }
795
Jozef Kolek1904fa22014-11-24 14:25:53 +0000796 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
797 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000798 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000799 }
800
Zoran Jovanovic41688672015-02-10 16:36:20 +0000801 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
802 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000803 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000804 }
805
Daniel Sanders21bce302014-04-01 12:35:23 +0000806 /// Render the operand to an MCInst as a GPR64
807 /// Asserts if the wrong number of operands are requested, or the operand
808 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000809 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
810 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000811 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000812 }
813
814 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
815 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000816 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000817 }
818
819 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
820 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000821 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000822 }
823
824 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
825 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000826 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000827 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000828 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000829 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
830 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000831 }
832
833 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
834 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000835 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000836 }
837
838 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
839 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000840 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000841 }
842
843 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
844 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000845 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000846 }
847
848 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
849 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000850 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000851 }
852
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000853 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
854 assert(N == 1 && "Invalid number of operands!");
855 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
856 }
857
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000858 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
859 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000860 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000861 }
862
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000863 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
864 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000865 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000866 }
867
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000868 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
869 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000870 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000871 }
872
873 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
874 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000875 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000876 }
877
878 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
879 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000880 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000881 }
882
883 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
884 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000885 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000886 }
887
888 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
889 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000890 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000891 }
892
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000893 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000894 assert(N == 1 && "Invalid number of operands!");
895 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000896 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000897 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000898
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000899 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000900 assert(N == 2 && "Invalid number of operands!");
901
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000902 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
903 ? getMemBase()->getGPR64Reg()
904 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000905
906 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000907 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000908 }
909
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000910 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
911 assert(N == 2 && "Invalid number of operands!");
912
Jim Grosbache9119e42015-05-13 18:37:00 +0000913 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000914
915 const MCExpr *Expr = getMemOff();
916 addExpr(Inst, Expr);
917 }
918
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000919 void addRegListOperands(MCInst &Inst, unsigned N) const {
920 assert(N == 1 && "Invalid number of operands!");
921
922 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000923 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000924 }
925
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000926 void addRegPairOperands(MCInst &Inst, unsigned N) const {
927 assert(N == 2 && "Invalid number of operands!");
928 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +0000929 Inst.addOperand(MCOperand::createReg(RegNo++));
930 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000931 }
932
Zoran Jovanovic41688672015-02-10 16:36:20 +0000933 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
934 assert(N == 2 && "Invalid number of operands!");
935 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000936 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000937 }
938
Craig Topper56c590a2014-04-29 07:58:02 +0000939 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000940 // As a special case until we sort out the definition of div/divu, pretend
941 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
942 if (isGPRAsmReg() && RegIdx.Index == 0)
943 return true;
944
945 return Kind == k_PhysRegister;
946 }
947 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000948 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000949 bool isConstantImm() const {
950 return isImm() && dyn_cast<MCConstantExpr>(getImm());
951 }
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +0000952 template <unsigned Bits> bool isUImm() const {
953 return isImm() && isConstantImm() && isUInt<Bits>(getConstantImm());
954 }
Craig Topper56c590a2014-04-29 07:58:02 +0000955 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000956 // Note: It's not possible to pretend that other operand kinds are tokens.
957 // The matcher emitter checks tokens first.
958 return Kind == k_Token;
959 }
Craig Topper56c590a2014-04-29 07:58:02 +0000960 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000961 bool isConstantMemOff() const {
962 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
963 }
964 template <unsigned Bits> bool isMemWithSimmOffset() const {
Zoran Jovanovica6593ff2015-08-18 12:53:08 +0000965 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
966 && getMemBase()->isGPRAsmReg();
967 }
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +0000968 template <unsigned Bits> bool isMemWithSimmOffsetGPR() const {
969 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) &&
970 getMemBase()->isGPRAsmReg();
971 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000972 bool isMemWithGRPMM16Base() const {
973 return isMem() && getMemBase()->isMM16AsmReg();
974 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000975 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
976 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
977 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
978 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000979 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
980 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
981 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
982 && (getMemBase()->getGPR32Reg() == Mips::SP);
983 }
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +0000984 bool isUImm5Lsl2() const {
985 return (isImm() && isConstantImm() && isShiftedUInt<5, 2>(getConstantImm()));
986 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000987 bool isRegList16() const {
988 if (!isRegList())
989 return false;
990
991 int Size = RegList.List->size();
992 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
993 RegList.List->back() != Mips::RA)
994 return false;
995
996 int PrevReg = *RegList.List->begin();
997 for (int i = 1; i < Size - 1; i++) {
998 int Reg = (*(RegList.List))[i];
999 if ( Reg != PrevReg + 1)
1000 return false;
1001 PrevReg = Reg;
1002 }
1003
1004 return true;
1005 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001006 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001007 bool isLSAImm() const {
1008 if (!isConstantImm())
1009 return false;
1010 int64_t Val = getConstantImm();
1011 return 1 <= Val && Val <= 4;
1012 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001013 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001014 bool isMovePRegPair() const {
1015 if (Kind != k_RegList || RegList.List->size() != 2)
1016 return false;
1017
1018 unsigned R0 = RegList.List->front();
1019 unsigned R1 = RegList.List->back();
1020
1021 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1022 (R0 == Mips::A1 && R1 == Mips::A3) ||
1023 (R0 == Mips::A2 && R1 == Mips::A3) ||
1024 (R0 == Mips::A0 && R1 == Mips::S5) ||
1025 (R0 == Mips::A0 && R1 == Mips::S6) ||
1026 (R0 == Mips::A0 && R1 == Mips::A1) ||
1027 (R0 == Mips::A0 && R1 == Mips::A2) ||
1028 (R0 == Mips::A0 && R1 == Mips::A3))
1029 return true;
1030
1031 return false;
1032 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001033
1034 StringRef getToken() const {
1035 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001036 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001037 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001038 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001039
Craig Topper56c590a2014-04-29 07:58:02 +00001040 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001041 // As a special case until we sort out the definition of div/divu, pretend
1042 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1043 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1044 RegIdx.Kind & RegKind_GPR)
1045 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001046
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001047 assert(Kind == k_PhysRegister && "Invalid access!");
1048 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001049 }
1050
Jack Carterb4dbc172012-09-05 23:34:03 +00001051 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001052 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001053 return Imm.Val;
1054 }
1055
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001056 int64_t getConstantImm() const {
1057 const MCExpr *Val = getImm();
1058 return static_cast<const MCConstantExpr *>(Val)->getValue();
1059 }
1060
1061 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001062 assert((Kind == k_Memory) && "Invalid access!");
1063 return Mem.Base;
1064 }
1065
1066 const MCExpr *getMemOff() const {
1067 assert((Kind == k_Memory) && "Invalid access!");
1068 return Mem.Off;
1069 }
1070
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001071 int64_t getConstantMemOff() const {
1072 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1073 }
1074
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001075 const SmallVectorImpl<unsigned> &getRegList() const {
1076 assert((Kind == k_RegList) && "Invalid access!");
1077 return *(RegList.List);
1078 }
1079
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001080 unsigned getRegPair() const {
1081 assert((Kind == k_RegPair) && "Invalid access!");
1082 return RegIdx.Index;
1083 }
1084
David Blaikie960ea3f2014-06-08 16:18:35 +00001085 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1086 MipsAsmParser &Parser) {
1087 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001088 Op->Tok.Data = Str.data();
1089 Op->Tok.Length = Str.size();
1090 Op->StartLoc = S;
1091 Op->EndLoc = S;
1092 return Op;
1093 }
1094
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001095 /// Create a numeric register (e.g. $1). The exact register remains
1096 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001097 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001098 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001099 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001100 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001101 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001102 }
1103
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001104 /// Create a register that is definitely a GPR.
1105 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001106 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001107 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001108 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001109 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001110 }
1111
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001112 /// Create a register that is definitely a FGR.
1113 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001114 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001115 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001116 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001117 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1118 }
1119
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001120 /// Create a register that is definitely a HWReg.
1121 /// This is typically only used for named registers such as $hwr_cpunum.
1122 static std::unique_ptr<MipsOperand>
1123 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1124 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1125 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1126 }
1127
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001128 /// Create a register that is definitely an FCC.
1129 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001130 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001131 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001132 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001133 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1134 }
1135
1136 /// Create a register that is definitely an ACC.
1137 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001138 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001139 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001140 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001141 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1142 }
1143
1144 /// Create a register that is definitely an MSA128.
1145 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001146 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001147 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001148 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001149 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1150 }
1151
1152 /// Create a register that is definitely an MSACtrl.
1153 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001154 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001155 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001156 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001157 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1158 }
1159
David Blaikie960ea3f2014-06-08 16:18:35 +00001160 static std::unique_ptr<MipsOperand>
1161 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1162 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001163 Op->Imm.Val = Val;
1164 Op->StartLoc = S;
1165 Op->EndLoc = E;
1166 return Op;
1167 }
1168
David Blaikie960ea3f2014-06-08 16:18:35 +00001169 static std::unique_ptr<MipsOperand>
1170 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1171 SMLoc E, MipsAsmParser &Parser) {
1172 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1173 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001174 Op->Mem.Off = Off;
1175 Op->StartLoc = S;
1176 Op->EndLoc = E;
1177 return Op;
1178 }
1179
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001180 static std::unique_ptr<MipsOperand>
1181 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1182 MipsAsmParser &Parser) {
1183 assert (Regs.size() > 0 && "Empty list not allowed");
1184
1185 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001186 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001187 Op->StartLoc = StartLoc;
1188 Op->EndLoc = EndLoc;
1189 return Op;
1190 }
1191
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001192 static std::unique_ptr<MipsOperand>
1193 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1194 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1195 Op->RegIdx.Index = RegNo;
1196 Op->StartLoc = S;
1197 Op->EndLoc = E;
1198 return Op;
1199 }
1200
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001201 bool isGPRAsmReg() const {
1202 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001203 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001204 bool isMM16AsmReg() const {
1205 if (!(isRegIdx() && RegIdx.Kind))
1206 return false;
1207 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1208 || RegIdx.Index == 16 || RegIdx.Index == 17);
1209 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001210 bool isMM16AsmRegZero() const {
1211 if (!(isRegIdx() && RegIdx.Kind))
1212 return false;
1213 return (RegIdx.Index == 0 ||
1214 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1215 RegIdx.Index == 17);
1216 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001217 bool isMM16AsmRegMoveP() const {
1218 if (!(isRegIdx() && RegIdx.Kind))
1219 return false;
1220 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1221 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1222 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001223 bool isFGRAsmReg() const {
1224 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1225 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001226 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001227 bool isHWRegsAsmReg() const {
1228 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001229 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001230 bool isCCRAsmReg() const {
1231 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001232 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001233 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001234 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1235 return false;
1236 if (!AsmParser.hasEightFccRegisters())
1237 return RegIdx.Index == 0;
1238 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001239 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001240 bool isACCAsmReg() const {
1241 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001242 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001243 bool isCOP0AsmReg() const {
1244 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1245 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001246 bool isCOP2AsmReg() const {
1247 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001248 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001249 bool isCOP3AsmReg() const {
1250 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1251 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001252 bool isMSA128AsmReg() const {
1253 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001254 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001255 bool isMSACtrlAsmReg() const {
1256 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001257 }
1258
Jack Carterb4dbc172012-09-05 23:34:03 +00001259 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001260 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001261 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001262 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001263
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001264 virtual ~MipsOperand() {
1265 switch (Kind) {
1266 case k_Immediate:
1267 break;
1268 case k_Memory:
1269 delete Mem.Base;
1270 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001271 case k_RegList:
1272 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001273 case k_PhysRegister:
1274 case k_RegisterIndex:
1275 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001276 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001277 break;
1278 }
1279 }
1280
Craig Topper56c590a2014-04-29 07:58:02 +00001281 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001282 switch (Kind) {
1283 case k_Immediate:
1284 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001285 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001286 OS << ">";
1287 break;
1288 case k_Memory:
1289 OS << "Mem<";
1290 Mem.Base->print(OS);
1291 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001292 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001293 OS << ">";
1294 break;
1295 case k_PhysRegister:
1296 OS << "PhysReg<" << PhysReg.Num << ">";
1297 break;
1298 case k_RegisterIndex:
1299 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1300 break;
1301 case k_Token:
1302 OS << Tok.Data;
1303 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001304 case k_RegList:
1305 OS << "RegList< ";
1306 for (auto Reg : (*RegList.List))
1307 OS << Reg << " ";
1308 OS << ">";
1309 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001310 case k_RegPair:
1311 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1312 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001313 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001314 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001315}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001316} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001317
Jack Carter9e65aa32013-03-22 00:05:30 +00001318namespace llvm {
1319extern const MCInstrDesc MipsInsts[];
1320}
1321static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1322 return MipsInsts[Opcode];
1323}
1324
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001325static bool hasShortDelaySlot(unsigned Opcode) {
1326 switch (Opcode) {
1327 case Mips::JALS_MM:
1328 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001329 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001330 case Mips::BGEZALS_MM:
1331 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001332 return true;
1333 default:
1334 return false;
1335 }
1336}
1337
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001338static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1339 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1340 return &SRExpr->getSymbol();
1341 }
1342
1343 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1344 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1345 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1346
1347 if (LHSSym)
1348 return LHSSym;
1349
1350 if (RHSSym)
1351 return RHSSym;
1352
1353 return nullptr;
1354 }
1355
1356 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1357 return getSingleMCSymbol(UExpr->getSubExpr());
1358
1359 return nullptr;
1360}
1361
1362static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1363 if (isa<MCSymbolRefExpr>(Expr))
1364 return 1;
1365
1366 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1367 return countMCSymbolRefExpr(BExpr->getLHS()) +
1368 countMCSymbolRefExpr(BExpr->getRHS());
1369
1370 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1371 return countMCSymbolRefExpr(UExpr->getSubExpr());
1372
1373 return 0;
1374}
1375
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001376namespace {
1377void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc,
1378 SmallVectorImpl<MCInst> &Instructions) {
1379 MCInst tmpInst;
1380 tmpInst.setOpcode(Opcode);
1381 tmpInst.addOperand(MCOperand::createReg(Reg0));
1382 tmpInst.addOperand(Op1);
1383 tmpInst.setLoc(IDLoc);
1384 Instructions.push_back(tmpInst);
1385}
1386
1387void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc,
1388 SmallVectorImpl<MCInst> &Instructions) {
1389 emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions);
1390}
1391
1392void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc,
1393 SmallVectorImpl<MCInst> &Instructions) {
1394 emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, Instructions);
1395}
1396
1397void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc,
1398 SmallVectorImpl<MCInst> &Instructions) {
1399 MCInst tmpInst;
1400 tmpInst.setOpcode(Opcode);
1401 tmpInst.addOperand(MCOperand::createImm(Imm1));
1402 tmpInst.addOperand(MCOperand::createImm(Imm2));
1403 tmpInst.setLoc(IDLoc);
1404 Instructions.push_back(tmpInst);
1405}
1406
1407void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
1408 SmallVectorImpl<MCInst> &Instructions) {
1409 MCInst tmpInst;
1410 tmpInst.setOpcode(Opcode);
1411 tmpInst.addOperand(MCOperand::createReg(Reg0));
1412 tmpInst.setLoc(IDLoc);
1413 Instructions.push_back(tmpInst);
1414}
1415
1416void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2,
1417 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1418 MCInst tmpInst;
1419 tmpInst.setOpcode(Opcode);
1420 tmpInst.addOperand(MCOperand::createReg(Reg0));
1421 tmpInst.addOperand(MCOperand::createReg(Reg1));
1422 tmpInst.addOperand(Op2);
1423 tmpInst.setLoc(IDLoc);
1424 Instructions.push_back(tmpInst);
1425}
1426
1427void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
1428 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1429 emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc,
1430 Instructions);
1431}
1432
1433void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
1434 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1435 emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc,
1436 Instructions);
1437}
1438
1439void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount,
1440 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1441 if (ShiftAmount >= 32) {
1442 emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc,
1443 Instructions);
1444 return;
1445 }
1446
1447 emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions);
1448}
1449} // end anonymous namespace.
1450
Jack Carter9e65aa32013-03-22 00:05:30 +00001451bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001452 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001453 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001454 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001455
Jack Carter9e65aa32013-03-22 00:05:30 +00001456 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001457
1458 if (MCID.isBranch() || MCID.isCall()) {
1459 const unsigned Opcode = Inst.getOpcode();
1460 MCOperand Offset;
1461
1462 switch (Opcode) {
1463 default:
1464 break;
Kai Nackee0245392015-01-27 19:11:28 +00001465 case Mips::BBIT0:
1466 case Mips::BBIT032:
1467 case Mips::BBIT1:
1468 case Mips::BBIT132:
1469 assert(hasCnMips() && "instruction only valid for octeon cpus");
1470 // Fall through
1471
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001472 case Mips::BEQ:
1473 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001474 case Mips::BEQ_MM:
1475 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001476 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001477 Offset = Inst.getOperand(2);
1478 if (!Offset.isImm())
1479 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001480 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001481 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001482 if (OffsetToAlignment(Offset.getImm(),
1483 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001484 return Error(IDLoc, "branch to misaligned address");
1485 break;
1486 case Mips::BGEZ:
1487 case Mips::BGTZ:
1488 case Mips::BLEZ:
1489 case Mips::BLTZ:
1490 case Mips::BGEZAL:
1491 case Mips::BLTZAL:
1492 case Mips::BC1F:
1493 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001494 case Mips::BGEZ_MM:
1495 case Mips::BGTZ_MM:
1496 case Mips::BLEZ_MM:
1497 case Mips::BLTZ_MM:
1498 case Mips::BGEZAL_MM:
1499 case Mips::BLTZAL_MM:
1500 case Mips::BC1F_MM:
1501 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001502 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001503 Offset = Inst.getOperand(1);
1504 if (!Offset.isImm())
1505 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001506 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001507 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001508 if (OffsetToAlignment(Offset.getImm(),
1509 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001510 return Error(IDLoc, "branch to misaligned address");
1511 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001512 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001513 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001514 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001515 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001516 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1517 Offset = Inst.getOperand(1);
1518 if (!Offset.isImm())
1519 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001520 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001521 return Error(IDLoc, "branch target out of range");
1522 if (OffsetToAlignment(Offset.getImm(), 2LL))
1523 return Error(IDLoc, "branch to misaligned address");
1524 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001525 }
1526 }
1527
Daniel Sandersa84989a2014-06-16 13:25:35 +00001528 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1529 // We still accept it but it is a normal nop.
1530 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1531 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1532 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1533 "nop instruction");
1534 }
1535
Kai Nackee0245392015-01-27 19:11:28 +00001536 if (hasCnMips()) {
1537 const unsigned Opcode = Inst.getOpcode();
1538 MCOperand Opnd;
1539 int Imm;
1540
1541 switch (Opcode) {
1542 default:
1543 break;
1544
1545 case Mips::BBIT0:
1546 case Mips::BBIT032:
1547 case Mips::BBIT1:
1548 case Mips::BBIT132:
1549 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1550 // The offset is handled above
1551 Opnd = Inst.getOperand(1);
1552 if (!Opnd.isImm())
1553 return Error(IDLoc, "expected immediate operand kind");
1554 Imm = Opnd.getImm();
1555 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1556 Opcode == Mips::BBIT1 ? 63 : 31))
1557 return Error(IDLoc, "immediate operand value out of range");
1558 if (Imm > 31) {
1559 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1560 : Mips::BBIT132);
1561 Inst.getOperand(1).setImm(Imm - 32);
1562 }
1563 break;
1564
1565 case Mips::CINS:
1566 case Mips::CINS32:
1567 case Mips::EXTS:
1568 case Mips::EXTS32:
1569 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1570 // Check length
1571 Opnd = Inst.getOperand(3);
1572 if (!Opnd.isImm())
1573 return Error(IDLoc, "expected immediate operand kind");
1574 Imm = Opnd.getImm();
1575 if (Imm < 0 || Imm > 31)
1576 return Error(IDLoc, "immediate operand value out of range");
1577 // Check position
1578 Opnd = Inst.getOperand(2);
1579 if (!Opnd.isImm())
1580 return Error(IDLoc, "expected immediate operand kind");
1581 Imm = Opnd.getImm();
1582 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1583 Opcode == Mips::EXTS ? 63 : 31))
1584 return Error(IDLoc, "immediate operand value out of range");
1585 if (Imm > 31) {
1586 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1587 Inst.getOperand(2).setImm(Imm - 32);
1588 }
1589 break;
1590
1591 case Mips::SEQi:
1592 case Mips::SNEi:
1593 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1594 Opnd = Inst.getOperand(2);
1595 if (!Opnd.isImm())
1596 return Error(IDLoc, "expected immediate operand kind");
1597 Imm = Opnd.getImm();
1598 if (!isInt<10>(Imm))
1599 return Error(IDLoc, "immediate operand value out of range");
1600 break;
1601 }
1602 }
1603
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001604 // This expansion is not in a function called by expandInstruction() because
1605 // the pseudo-instruction doesn't have a distinct opcode.
1606 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1607 inPicMode()) {
1608 warnIfNoMacro(IDLoc);
1609
1610 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1611
1612 // We can do this expansion if there's only 1 symbol in the argument
1613 // expression.
1614 if (countMCSymbolRefExpr(JalExpr) > 1)
1615 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1616
1617 // FIXME: This is checking the expression can be handled by the later stages
1618 // of the assembler. We ought to leave it to those later stages but
1619 // we can't do that until we stop evaluateRelocExpr() rewriting the
1620 // expressions into non-equivalent forms.
1621 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1622
1623 // FIXME: Add support for label+offset operands (currently causes an error).
1624 // FIXME: Add support for forward-declared local symbols.
1625 // FIXME: Add expansion for when the LargeGOT option is enabled.
1626 if (JalSym->isInSection() || JalSym->isTemporary()) {
1627 if (isABI_O32()) {
1628 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001629 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001630 // R_(MICRO)MIPS_GOT16 label
1631 // addiu $25, $25, 0
1632 // R_(MICRO)MIPS_LO16 label
1633 // jalr $25
1634 const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
1635 const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
1636
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001637 emitRRX(Mips::LW, Mips::T9, Mips::GP,
1638 MCOperand::createExpr(Got16RelocExpr), IDLoc, Instructions);
1639 emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1640 MCOperand::createExpr(Lo16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001641 } else if (isABI_N32() || isABI_N64()) {
1642 // If it's a local symbol and the N32/N64 ABIs are being used,
1643 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001644 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001645 // R_(MICRO)MIPS_GOT_DISP label
1646 // jalr $25
1647 const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
1648
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001649 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1650 MCOperand::createExpr(GotDispRelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001651 }
1652 } else {
1653 // If it's an external/weak symbol, we expand to:
1654 // lw/ld $25, 0($gp)
1655 // R_(MICRO)MIPS_CALL16 label
1656 // jalr $25
1657 const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
1658
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001659 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1660 MCOperand::createExpr(Call16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001661 }
1662
1663 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001664 if (IsCpRestoreSet && inMicroMipsMode())
1665 JalrInst.setOpcode(Mips::JALRS_MM);
1666 else
1667 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001668 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1669 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1670
1671 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1672 // This relocation is supposed to be an optimization hint for the linker
1673 // and is not necessary for correctness.
1674
1675 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001676 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001677 }
1678
Jack Carter9e65aa32013-03-22 00:05:30 +00001679 if (MCID.mayLoad() || MCID.mayStore()) {
1680 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001681 // reference or immediate we may have to expand instructions.
1682 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001683 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001684 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1685 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001686 MCOperand &Op = Inst.getOperand(i);
1687 if (Op.isImm()) {
1688 int MemOffset = Op.getImm();
1689 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001690 // Offset can't exceed 16bit value.
1691 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001692 return false;
1693 }
1694 } else if (Op.isExpr()) {
1695 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001696 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001697 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001698 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001699 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001700 // Expand symbol.
1701 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001702 return false;
1703 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001704 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001705 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001706 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001707 }
1708 }
1709 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001710 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001711 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001712
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001713 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001714 if (MCID.mayLoad()) {
1715 // Try to create 16-bit GP relative load instruction.
1716 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1717 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1718 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1719 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1720 MCOperand &Op = Inst.getOperand(i);
1721 if (Op.isImm()) {
1722 int MemOffset = Op.getImm();
1723 MCOperand &DstReg = Inst.getOperand(0);
1724 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00001725 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00001726 getContext().getRegisterInfo()->getRegClass(
1727 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001728 (BaseReg.getReg() == Mips::GP ||
1729 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001730
1731 emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
1732 IDLoc, Instructions);
Jozef Koleke10a02e2015-01-28 17:27:26 +00001733 return false;
1734 }
1735 }
1736 }
1737 } // for
1738 } // if load
1739
1740 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1741
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001742 MCOperand Opnd;
1743 int Imm;
1744
1745 switch (Inst.getOpcode()) {
1746 default:
1747 break;
1748 case Mips::ADDIUS5_MM:
1749 Opnd = Inst.getOperand(2);
1750 if (!Opnd.isImm())
1751 return Error(IDLoc, "expected immediate operand kind");
1752 Imm = Opnd.getImm();
1753 if (Imm < -8 || Imm > 7)
1754 return Error(IDLoc, "immediate operand value out of range");
1755 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001756 case Mips::ADDIUSP_MM:
1757 Opnd = Inst.getOperand(0);
1758 if (!Opnd.isImm())
1759 return Error(IDLoc, "expected immediate operand kind");
1760 Imm = Opnd.getImm();
1761 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1762 Imm % 4 != 0)
1763 return Error(IDLoc, "immediate operand value out of range");
1764 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001765 case Mips::SLL16_MM:
1766 case Mips::SRL16_MM:
1767 Opnd = Inst.getOperand(2);
1768 if (!Opnd.isImm())
1769 return Error(IDLoc, "expected immediate operand kind");
1770 Imm = Opnd.getImm();
1771 if (Imm < 1 || Imm > 8)
1772 return Error(IDLoc, "immediate operand value out of range");
1773 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001774 case Mips::LI16_MM:
1775 Opnd = Inst.getOperand(1);
1776 if (!Opnd.isImm())
1777 return Error(IDLoc, "expected immediate operand kind");
1778 Imm = Opnd.getImm();
1779 if (Imm < -1 || Imm > 126)
1780 return Error(IDLoc, "immediate operand value out of range");
1781 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001782 case Mips::ADDIUR2_MM:
1783 Opnd = Inst.getOperand(2);
1784 if (!Opnd.isImm())
1785 return Error(IDLoc, "expected immediate operand kind");
1786 Imm = Opnd.getImm();
1787 if (!(Imm == 1 || Imm == -1 ||
1788 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1789 return Error(IDLoc, "immediate operand value out of range");
1790 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001791 case Mips::ADDIUR1SP_MM:
1792 Opnd = Inst.getOperand(1);
1793 if (!Opnd.isImm())
1794 return Error(IDLoc, "expected immediate operand kind");
1795 Imm = Opnd.getImm();
1796 if (OffsetToAlignment(Imm, 4LL))
1797 return Error(IDLoc, "misaligned immediate operand value");
1798 if (Imm < 0 || Imm > 255)
1799 return Error(IDLoc, "immediate operand value out of range");
1800 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001801 case Mips::ANDI16_MM:
1802 Opnd = Inst.getOperand(2);
1803 if (!Opnd.isImm())
1804 return Error(IDLoc, "expected immediate operand kind");
1805 Imm = Opnd.getImm();
1806 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1807 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1808 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1809 return Error(IDLoc, "immediate operand value out of range");
1810 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001811 case Mips::LBU16_MM:
1812 Opnd = Inst.getOperand(2);
1813 if (!Opnd.isImm())
1814 return Error(IDLoc, "expected immediate operand kind");
1815 Imm = Opnd.getImm();
1816 if (Imm < -1 || Imm > 14)
1817 return Error(IDLoc, "immediate operand value out of range");
1818 break;
Zoran Jovanovic7ba636c2015-09-17 10:14:09 +00001819 case Mips::TEQ_MM:
1820 case Mips::TGE_MM:
1821 case Mips::TGEU_MM:
1822 case Mips::TLT_MM:
1823 case Mips::TLTU_MM:
1824 case Mips::TNE_MM:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001825 case Mips::SB16_MM:
1826 Opnd = Inst.getOperand(2);
1827 if (!Opnd.isImm())
1828 return Error(IDLoc, "expected immediate operand kind");
1829 Imm = Opnd.getImm();
1830 if (Imm < 0 || Imm > 15)
1831 return Error(IDLoc, "immediate operand value out of range");
1832 break;
1833 case Mips::LHU16_MM:
1834 case Mips::SH16_MM:
1835 Opnd = Inst.getOperand(2);
1836 if (!Opnd.isImm())
1837 return Error(IDLoc, "expected immediate operand kind");
1838 Imm = Opnd.getImm();
1839 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1840 return Error(IDLoc, "immediate operand value out of range");
1841 break;
1842 case Mips::LW16_MM:
1843 case Mips::SW16_MM:
1844 Opnd = Inst.getOperand(2);
1845 if (!Opnd.isImm())
1846 return Error(IDLoc, "expected immediate operand kind");
1847 Imm = Opnd.getImm();
1848 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1849 return Error(IDLoc, "immediate operand value out of range");
1850 break;
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +00001851 case Mips::PREFX_MM:
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001852 case Mips::CACHE:
1853 case Mips::PREF:
1854 Opnd = Inst.getOperand(2);
1855 if (!Opnd.isImm())
1856 return Error(IDLoc, "expected immediate operand kind");
1857 Imm = Opnd.getImm();
1858 if (!isUInt<5>(Imm))
1859 return Error(IDLoc, "immediate operand value out of range");
1860 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001861 case Mips::ADDIUPC_MM:
1862 MCOperand Opnd = Inst.getOperand(1);
1863 if (!Opnd.isImm())
1864 return Error(IDLoc, "expected immediate operand kind");
1865 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00001866 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001867 return Error(IDLoc, "immediate operand value out of range");
1868 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001869 }
1870 }
1871
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001872 if (needsExpansion(Inst)) {
1873 if (expandInstruction(Inst, IDLoc, Instructions))
1874 return true;
1875 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001876 Instructions.push_back(Inst);
1877
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001878 // If this instruction has a delay slot and .set reorder is active,
1879 // emit a NOP after it.
1880 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1881 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1882
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001883 if ((Inst.getOpcode() == Mips::JalOneReg ||
1884 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
1885 isPicAndNotNxxAbi()) {
1886 if (IsCpRestoreSet) {
1887 // We need a NOP between the JALR and the LW:
1888 // If .set reorder has been used, we've already emitted a NOP.
1889 // If .set noreorder has been used, we need to emit a NOP at this point.
1890 if (!AssemblerOptions.back()->isReorder())
1891 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1892
1893 // Load the $gp from the stack.
1894 SmallVector<MCInst, 3> LoadInsts;
1895 createCpRestoreMemOp(true /*IsLoad*/, CpRestoreOffset /*StackOffset*/,
1896 IDLoc, LoadInsts);
1897
1898 for (const MCInst &Inst : LoadInsts)
1899 Instructions.push_back(Inst);
1900
1901 } else
1902 Warning(IDLoc, "no .cprestore used in PIC mode");
1903 }
1904
Jack Carter9e65aa32013-03-22 00:05:30 +00001905 return false;
1906}
1907
Jack Carter30a59822012-10-04 04:03:53 +00001908bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1909
Jack Carterd0bd6422013-04-18 00:41:53 +00001910 switch (Inst.getOpcode()) {
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001911 case Mips::LoadImm32:
1912 case Mips::LoadImm64:
1913 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001914 case Mips::LoadAddrImm64:
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001915 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001916 case Mips::LoadAddrReg64:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001917 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001918 case Mips::B_MMR6_Pseudo:
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001919 case Mips::LWM_MM:
1920 case Mips::SWM_MM:
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001921 case Mips::JalOneReg:
1922 case Mips::JalTwoReg:
Toma Tabacue1e460d2015-06-11 10:36:10 +00001923 case Mips::BneImm:
1924 case Mips::BeqImm:
Toma Tabacu1a108322015-06-17 13:20:24 +00001925 case Mips::BLT:
1926 case Mips::BLE:
1927 case Mips::BGE:
1928 case Mips::BGT:
1929 case Mips::BLTU:
1930 case Mips::BLEU:
1931 case Mips::BGEU:
1932 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00001933 case Mips::BLTL:
1934 case Mips::BLEL:
1935 case Mips::BGEL:
1936 case Mips::BGTL:
1937 case Mips::BLTUL:
1938 case Mips::BLEUL:
1939 case Mips::BGEUL:
1940 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00001941 case Mips::BLTImmMacro:
1942 case Mips::BLEImmMacro:
1943 case Mips::BGEImmMacro:
1944 case Mips::BGTImmMacro:
1945 case Mips::BLTUImmMacro:
1946 case Mips::BLEUImmMacro:
1947 case Mips::BGEUImmMacro:
1948 case Mips::BGTUImmMacro:
1949 case Mips::BLTLImmMacro:
1950 case Mips::BLELImmMacro:
1951 case Mips::BGELImmMacro:
1952 case Mips::BGTLImmMacro:
1953 case Mips::BLTULImmMacro:
1954 case Mips::BLEULImmMacro:
1955 case Mips::BGEULImmMacro:
1956 case Mips::BGTULImmMacro:
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00001957 case Mips::SDivMacro:
1958 case Mips::UDivMacro:
1959 case Mips::DSDivMacro:
1960 case Mips::DUDivMacro:
Daniel Sanders6394ee52015-10-15 14:52:58 +00001961 case Mips::Ulh:
Toma Tabacud88d79c2015-06-23 14:39:42 +00001962 case Mips::Ulhu:
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00001963 case Mips::Ulw:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00001964 case Mips::NORImm:
Jack Carterd0bd6422013-04-18 00:41:53 +00001965 return true;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00001966 case Mips::ADDi:
1967 case Mips::ADDiu:
1968 case Mips::SLTi:
1969 case Mips::SLTiu:
1970 if ((Inst.getNumOperands() == 3) &&
1971 Inst.getOperand(0).isReg() &&
1972 Inst.getOperand(1).isReg() &&
1973 Inst.getOperand(2).isImm()) {
1974 int64_t ImmValue = Inst.getOperand(2).getImm();
1975 return !isInt<16>(ImmValue);
1976 }
1977 return false;
1978 case Mips::ANDi:
1979 case Mips::ORi:
1980 case Mips::XORi:
1981 if ((Inst.getNumOperands() == 3) &&
1982 Inst.getOperand(0).isReg() &&
1983 Inst.getOperand(1).isReg() &&
1984 Inst.getOperand(2).isImm()) {
1985 int64_t ImmValue = Inst.getOperand(2).getImm();
1986 return !isUInt<16>(ImmValue);
1987 }
1988 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001989 default:
1990 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001991 }
1992}
Jack Carter92995f12012-10-06 00:53:28 +00001993
Matheus Almeida3813d572014-06-19 14:39:14 +00001994bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001995 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001996 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001997 default: llvm_unreachable("unimplemented expansion");
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001998 case Mips::LoadImm32:
Toma Tabacu00e98672015-05-01 12:19:27 +00001999 return expandLoadImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002000 case Mips::LoadImm64:
Toma Tabacu00e98672015-05-01 12:19:27 +00002001 return expandLoadImm(Inst, false, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002002 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002003 case Mips::LoadAddrImm64:
2004 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2005 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
2006 "expected immediate operand kind");
2007
2008 return expandLoadAddress(
2009 Inst.getOperand(0).getReg(), Mips::NoRegister, Inst.getOperand(1),
2010 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002011 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002012 case Mips::LoadAddrReg64:
2013 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2014 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2015 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
2016 "expected immediate operand kind");
2017
2018 return expandLoadAddress(
2019 Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(), Inst.getOperand(2),
2020 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002021 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002022 case Mips::B_MMR6_Pseudo:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002023 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002024 case Mips::SWM_MM:
2025 case Mips::LWM_MM:
2026 return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002027 case Mips::JalOneReg:
2028 case Mips::JalTwoReg:
2029 return expandJalWithRegs(Inst, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002030 case Mips::BneImm:
2031 case Mips::BeqImm:
2032 return expandBranchImm(Inst, IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002033 case Mips::BLT:
2034 case Mips::BLE:
2035 case Mips::BGE:
2036 case Mips::BGT:
2037 case Mips::BLTU:
2038 case Mips::BLEU:
2039 case Mips::BGEU:
2040 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002041 case Mips::BLTL:
2042 case Mips::BLEL:
2043 case Mips::BGEL:
2044 case Mips::BGTL:
2045 case Mips::BLTUL:
2046 case Mips::BLEUL:
2047 case Mips::BGEUL:
2048 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002049 case Mips::BLTImmMacro:
2050 case Mips::BLEImmMacro:
2051 case Mips::BGEImmMacro:
2052 case Mips::BGTImmMacro:
2053 case Mips::BLTUImmMacro:
2054 case Mips::BLEUImmMacro:
2055 case Mips::BGEUImmMacro:
2056 case Mips::BGTUImmMacro:
2057 case Mips::BLTLImmMacro:
2058 case Mips::BLELImmMacro:
2059 case Mips::BGELImmMacro:
2060 case Mips::BGTLImmMacro:
2061 case Mips::BLTULImmMacro:
2062 case Mips::BLEULImmMacro:
2063 case Mips::BGEULImmMacro:
2064 case Mips::BGTULImmMacro:
Toma Tabacu1a108322015-06-17 13:20:24 +00002065 return expandCondBranches(Inst, IDLoc, Instructions);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002066 case Mips::SDivMacro:
2067 return expandDiv(Inst, IDLoc, Instructions, false, true);
2068 case Mips::DSDivMacro:
2069 return expandDiv(Inst, IDLoc, Instructions, true, true);
2070 case Mips::UDivMacro:
2071 return expandDiv(Inst, IDLoc, Instructions, false, false);
2072 case Mips::DUDivMacro:
2073 return expandDiv(Inst, IDLoc, Instructions, true, false);
Daniel Sanders6394ee52015-10-15 14:52:58 +00002074 case Mips::Ulh:
2075 return expandUlh(Inst, true, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00002076 case Mips::Ulhu:
Daniel Sanders6394ee52015-10-15 14:52:58 +00002077 return expandUlh(Inst, false, IDLoc, Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00002078 case Mips::Ulw:
2079 return expandUlw(Inst, IDLoc, Instructions);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002080 case Mips::ADDi:
2081 case Mips::ADDiu:
2082 case Mips::ANDi:
2083 case Mips::NORImm:
2084 case Mips::ORi:
2085 case Mips::SLTi:
2086 case Mips::SLTiu:
2087 case Mips::XORi:
2088 return expandAliasImmediate(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00002089 }
Jack Carter30a59822012-10-04 04:03:53 +00002090}
Jack Carter92995f12012-10-06 00:53:28 +00002091
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002092bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
2093 SmallVectorImpl<MCInst> &Instructions) {
2094 // Create a JALR instruction which is going to replace the pseudo-JAL.
2095 MCInst JalrInst;
2096 JalrInst.setLoc(IDLoc);
2097 const MCOperand FirstRegOp = Inst.getOperand(0);
2098 const unsigned Opcode = Inst.getOpcode();
2099
2100 if (Opcode == Mips::JalOneReg) {
2101 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002102 if (IsCpRestoreSet && inMicroMipsMode()) {
2103 JalrInst.setOpcode(Mips::JALRS16_MM);
2104 JalrInst.addOperand(FirstRegOp);
2105 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002106 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002107 JalrInst.addOperand(FirstRegOp);
2108 } else {
2109 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002110 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002111 JalrInst.addOperand(FirstRegOp);
2112 }
2113 } else if (Opcode == Mips::JalTwoReg) {
2114 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002115 if (IsCpRestoreSet && inMicroMipsMode())
2116 JalrInst.setOpcode(Mips::JALRS_MM);
2117 else
2118 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002119 JalrInst.addOperand(FirstRegOp);
2120 const MCOperand SecondRegOp = Inst.getOperand(1);
2121 JalrInst.addOperand(SecondRegOp);
2122 }
2123 Instructions.push_back(JalrInst);
2124
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002125 // If .set reorder is active and branch instruction has a delay slot,
2126 // emit a NOP after it.
2127 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
2128 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002129 createNop(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, Instructions);
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002130 }
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002131
2132 return false;
2133}
2134
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002135/// Can the value be represented by a unsigned N-bit value and a shift left?
2136template<unsigned N>
2137bool isShiftedUIntAtAnyPosition(uint64_t x) {
2138 unsigned BitNum = findFirstSet(x);
2139
2140 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2141}
2142
2143/// Load (or add) an immediate into a register.
2144///
2145/// @param ImmValue The immediate to load.
2146/// @param DstReg The register that will hold the immediate.
2147/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2148/// for a simple initialization.
2149/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2150/// @param IsAddress True if the immediate represents an address. False if it
2151/// is an integer.
2152/// @param IDLoc Location of the immediate in the source file.
2153/// @param Instructions The instructions emitted by this expansion.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002154bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002155 unsigned SrcReg, bool Is32BitImm,
2156 bool IsAddress, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00002157 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00002158 if (!Is32BitImm && !isGP64bit()) {
2159 Error(IDLoc, "instruction requires a 64-bit architecture");
2160 return true;
2161 }
2162
Daniel Sanders03f9c012015-07-14 12:24:22 +00002163 if (Is32BitImm) {
2164 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2165 // Sign extend up to 64-bit so that the predicates match the hardware
2166 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2167 // true.
2168 ImmValue = SignExtend64<32>(ImmValue);
2169 } else {
2170 Error(IDLoc, "instruction requires a 32-bit immediate");
2171 return true;
2172 }
2173 }
2174
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002175 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2176 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2177
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002178 bool UseSrcReg = false;
2179 if (SrcReg != Mips::NoRegister)
2180 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002181
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002182 unsigned TmpReg = DstReg;
2183 if (UseSrcReg && (DstReg == SrcReg)) {
2184 // At this point we need AT to perform the expansions and we exit if it is
2185 // not available.
2186 unsigned ATReg = getATReg(IDLoc);
2187 if (!ATReg)
2188 return true;
2189 TmpReg = ATReg;
2190 }
2191
Daniel Sanders03f9c012015-07-14 12:24:22 +00002192 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002193 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002194 SrcReg = ZeroReg;
2195
2196 // This doesn't quite follow the usual ABI expectations for N32 but matches
2197 // traditional assembler behaviour. N32 would normally use addiu for both
2198 // integers and addresses.
2199 if (IsAddress && !Is32BitImm) {
2200 emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2201 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002202 }
2203
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002204 emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2205 return false;
2206 }
2207
2208 if (isUInt<16>(ImmValue)) {
2209 unsigned TmpReg = DstReg;
2210 if (SrcReg == DstReg) {
2211 TmpReg = getATReg(IDLoc);
2212 if (!TmpReg)
2213 return true;
2214 }
2215
2216 emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002217 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002218 emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2219 return false;
2220 }
2221
2222 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002223 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002224
Toma Tabacu79588102015-04-29 10:19:56 +00002225 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2226 uint16_t Bits15To0 = ImmValue & 0xffff;
2227
Toma Tabacua3d056f2015-05-15 09:42:11 +00002228 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002229 // Traditional behaviour seems to special case this particular value. It's
2230 // not clear why other masks are handled differently.
2231 if (ImmValue == 0xffffffff) {
Daniel Sandersf1ae3672015-08-18 09:55:57 +00002232 emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002233 emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, Instructions);
2234 if (UseSrcReg)
2235 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2236 return false;
2237 }
2238
2239 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002240 // upper 32 bits.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002241 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002242 emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002243 if (Bits15To0)
2244 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
2245 if (UseSrcReg)
2246 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2247 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002248 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002249
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002250 emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions);
2251 if (Bits15To0)
2252 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002253 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002254 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2255 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002256 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002257
2258 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2259 if (Is32BitImm) {
2260 Error(IDLoc, "instruction requires a 32-bit immediate");
2261 return true;
2262 }
2263
2264 // Traditionally, these immediates are shifted as little as possible and as
2265 // such we align the most significant bit to bit 15 of our temporary.
2266 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2267 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2268 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2269 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
2270 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, Instructions);
2271 emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, Instructions);
2272
2273 if (UseSrcReg)
2274 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2275
2276 return false;
2277 }
2278
2279 warnIfNoMacro(IDLoc);
2280
2281 // The remaining case is packed with a sequence of dsll and ori with zeros
2282 // being omitted and any neighbouring dsll's being coalesced.
2283 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2284
2285 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2286 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
2287 IDLoc, Instructions))
2288 return false;
2289
2290 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2291 // skip it and defer the shift to the next chunk.
2292 unsigned ShiftCarriedForwards = 16;
2293 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2294 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2295
2296 if (ImmChunk != 0) {
2297 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2298 Instructions);
2299 emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, Instructions);
2300 ShiftCarriedForwards = 0;
2301 }
2302
2303 ShiftCarriedForwards += 16;
2304 }
2305 ShiftCarriedForwards -= 16;
2306
2307 // Finish any remaining shifts left by trailing zeros.
2308 if (ShiftCarriedForwards)
2309 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2310 Instructions);
2311
2312 if (UseSrcReg)
2313 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2314
Matheus Almeida3813d572014-06-19 14:39:14 +00002315 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002316}
Jack Carter92995f12012-10-06 00:53:28 +00002317
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002318bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
2319 SmallVectorImpl<MCInst> &Instructions) {
2320 const MCOperand &ImmOp = Inst.getOperand(1);
2321 assert(ImmOp.isImm() && "expected immediate operand kind");
2322 const MCOperand &DstRegOp = Inst.getOperand(0);
2323 assert(DstRegOp.isReg() && "expected register operand kind");
2324
2325 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002326 Is32BitImm, false, IDLoc, Instructions))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002327 return true;
2328
2329 return false;
2330}
2331
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002332bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2333 const MCOperand &Offset,
2334 bool Is32BitAddress, SMLoc IDLoc,
2335 SmallVectorImpl<MCInst> &Instructions) {
2336 // la can't produce a usable address when addresses are 64-bit.
2337 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2338 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2339 // We currently can't do this because we depend on the equality
2340 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2341 Error(IDLoc, "la used to load 64-bit address");
2342 // Continue as if we had 'dla' instead.
2343 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002344 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002345
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002346 // dla requires 64-bit addresses.
2347 if (!Is32BitAddress && !ABI.ArePtrs64bit()) {
2348 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002349 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002350 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002351
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002352 if (!Offset.isImm())
2353 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
2354 Is32BitAddress, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002355
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002356 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
2357 IDLoc, Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +00002358}
2359
Toma Tabacuf712ede2015-06-17 14:31:51 +00002360bool MipsAsmParser::loadAndAddSymbolAddress(
2361 const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
2362 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002363 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002364
Daniel Sandersd5a89412015-10-05 13:19:29 +00002365 const MCExpr *Symbol = cast<MCExpr>(SymExpr);
2366 const MipsMCExpr *HiExpr = MipsMCExpr::create(
2367 MCSymbolRefExpr::VK_Mips_ABS_HI, Symbol, getContext());
2368 const MipsMCExpr *LoExpr = MipsMCExpr::create(
2369 MCSymbolRefExpr::VK_Mips_ABS_LO, Symbol, getContext());
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002370
Toma Tabacufb9d1252015-06-22 12:08:39 +00002371 bool UseSrcReg = SrcReg != Mips::NoRegister;
2372
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002373 // This is the 64-bit symbol address expansion.
2374 if (ABI.ArePtrs64bit() && isGP64bit()) {
2375 // We always need AT for the 64-bit expansion.
2376 // If it is not available we exit.
2377 unsigned ATReg = getATReg(IDLoc);
2378 if (!ATReg)
2379 return true;
2380
Daniel Sandersd5a89412015-10-05 13:19:29 +00002381 const MipsMCExpr *HighestExpr = MipsMCExpr::create(
2382 MCSymbolRefExpr::VK_Mips_HIGHEST, Symbol, getContext());
2383 const MipsMCExpr *HigherExpr = MipsMCExpr::create(
2384 MCSymbolRefExpr::VK_Mips_HIGHER, Symbol, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002385
2386 if (UseSrcReg && (DstReg == SrcReg)) {
2387 // If $rs is the same as $rd:
2388 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2389 // daddiu $at, $at, %higher(sym)
2390 // dsll $at, $at, 16
2391 // daddiu $at, $at, %hi(sym)
2392 // dsll $at, $at, 16
2393 // daddiu $at, $at, %lo(sym)
2394 // daddu $rd, $at, $rd
2395 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2396 Instructions);
2397 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr),
2398 IDLoc, Instructions);
2399 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2400 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2401 Instructions);
2402 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2403 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2404 Instructions);
2405 emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions);
2406
2407 return false;
2408 }
2409
2410 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2411 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2412 // lui $at, %hi(sym)
2413 // daddiu $rd, $rd, %higher(sym)
2414 // daddiu $at, $at, %lo(sym)
2415 // dsll32 $rd, $rd, 0
2416 // daddu $rd, $rd, $at
2417 // (daddu $rd, $rd, $rs)
2418 emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2419 Instructions);
2420 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2421 Instructions);
2422 emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr),
2423 IDLoc, Instructions);
2424 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2425 Instructions);
2426 emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions);
2427 emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions);
2428 if (UseSrcReg)
2429 emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions);
2430
2431 return false;
2432 }
2433
2434 // And now, the 32-bit symbol address expansion:
2435 // If $rs is the same as $rd:
2436 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2437 // ori $at, $at, %lo(sym)
2438 // addu $rd, $at, $rd
2439 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2440 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2441 // ori $rd, $rd, %lo(sym)
2442 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002443 unsigned TmpReg = DstReg;
2444 if (UseSrcReg && (DstReg == SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002445 // If $rs is the same as $rd, we need to use AT.
2446 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002447 unsigned ATReg = getATReg(IDLoc);
2448 if (!ATReg)
2449 return true;
2450 TmpReg = ATReg;
2451 }
2452
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002453 emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions);
2454 emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc,
2455 Instructions);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002456
Toma Tabacufb9d1252015-06-22 12:08:39 +00002457 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002458 emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2459 else
2460 assert(DstReg == TmpReg);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002461
Toma Tabacu674825c2015-06-16 12:16:24 +00002462 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002463}
2464
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002465bool MipsAsmParser::expandUncondBranchMMPseudo(
2466 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002467 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2468 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002469
2470 MCOperand Offset = Inst.getOperand(0);
2471 if (Offset.isExpr()) {
2472 Inst.clear();
2473 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002474 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2475 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2476 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002477 } else {
2478 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002479 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002480 // If offset fits into 11 bits then this instruction becomes microMIPS
2481 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002482 if (inMicroMipsMode())
2483 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002484 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002485 if (!isInt<17>(Offset.getImm()))
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002486 Error(IDLoc, "branch target out of range");
2487 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2488 Error(IDLoc, "branch to misaligned address");
2489 Inst.clear();
2490 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002491 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2492 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2493 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002494 }
2495 }
2496 Instructions.push_back(Inst);
2497
Zoran Jovanovicada70912015-09-07 11:56:37 +00002498 // If .set reorder is active and branch instruction has a delay slot,
2499 // emit a NOP after it.
2500 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2501 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Toma Tabacu234482a2015-03-16 12:03:39 +00002502 createNop(true, IDLoc, Instructions);
2503
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002504 return false;
2505}
2506
Toma Tabacue1e460d2015-06-11 10:36:10 +00002507bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2508 SmallVectorImpl<MCInst> &Instructions) {
2509 const MCOperand &DstRegOp = Inst.getOperand(0);
2510 assert(DstRegOp.isReg() && "expected register operand kind");
2511
2512 const MCOperand &ImmOp = Inst.getOperand(1);
2513 assert(ImmOp.isImm() && "expected immediate operand kind");
2514
2515 const MCOperand &MemOffsetOp = Inst.getOperand(2);
2516 assert(MemOffsetOp.isImm() && "expected immediate operand kind");
2517
2518 unsigned OpCode = 0;
2519 switch(Inst.getOpcode()) {
2520 case Mips::BneImm:
2521 OpCode = Mips::BNE;
2522 break;
2523 case Mips::BeqImm:
2524 OpCode = Mips::BEQ;
2525 break;
2526 default:
2527 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2528 break;
2529 }
2530
2531 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002532 if (ImmValue == 0)
2533 emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2534 Instructions);
2535 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002536 warnIfNoMacro(IDLoc);
2537
2538 unsigned ATReg = getATReg(IDLoc);
2539 if (!ATReg)
2540 return true;
2541
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002542 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
2543 IDLoc, Instructions))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002544 return true;
2545
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002546 emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002547 }
2548 return false;
2549}
2550
Jack Carter9e65aa32013-03-22 00:05:30 +00002551void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002552 SmallVectorImpl<MCInst> &Instructions,
2553 bool isLoad, bool isImmOpnd) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002554 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002555 const MCExpr *ExprOffset;
2556 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002557 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002558 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2559 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002560 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002561 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2562 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002563 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002564 if (isImmOpnd) {
2565 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2566 ImmOffset = Inst.getOperand(2).getImm();
2567 LoOffset = ImmOffset & 0x0000ffff;
2568 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002569 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002570 if (LoOffset & 0x8000)
2571 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002572 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002573 ExprOffset = Inst.getOperand(2).getExpr();
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002574 // These are some of the types of expansions we perform here:
2575 // 1) lw $8, sym => lui $8, %hi(sym)
2576 // lw $8, %lo(sym)($8)
2577 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2578 // add $8, $8, $9
2579 // lw $8, %lo(offset)($9)
2580 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2581 // add $at, $at, $8
2582 // lw $8, %lo(offset)($at)
2583 // 4) sw $8, sym => lui $at, %hi(sym)
2584 // sw $8, %lo(sym)($at)
2585 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2586 // add $at, $at, $8
2587 // sw $8, %lo(offset)($at)
2588 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2589 // ldc1 $f0, %lo(sym)($at)
2590 //
2591 // For load instructions we can use the destination register as a temporary
2592 // if base and dst are different (examples 1 and 2) and if the base register
2593 // is general purpose otherwise we must use $at (example 6) and error if it's
2594 // not available. For stores we must use $at (examples 4 and 5) because we
2595 // must not clobber the source register setting up the offset.
2596 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2597 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2598 unsigned RegClassIDOp0 =
2599 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2600 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2601 (RegClassIDOp0 == Mips::GPR64RegClassID);
2602 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002603 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002604 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002605 // At this point we need AT to perform the expansions and we exit if it is
2606 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002607 TmpRegNum = getATReg(IDLoc);
2608 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002609 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002610 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002611
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002612 emitRX(Mips::LUi, TmpRegNum,
2613 isImmOpnd ? MCOperand::createImm(HiOffset)
2614 : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "hi")),
2615 IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00002616 // Add temp register to base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002617 if (BaseRegNum != Mips::ZERO)
2618 emitRRR(Mips::ADDu, TmpRegNum, TmpRegNum, BaseRegNum, IDLoc, Instructions);
Alp Tokercb402912014-01-24 17:20:08 +00002619 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002620 // of offset and new base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002621 emitRRX(Inst.getOpcode(), RegOpNum, TmpRegNum,
2622 isImmOpnd
2623 ? MCOperand::createImm(LoOffset)
2624 : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "lo")),
2625 IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00002626}
2627
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002628bool
2629MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2630 SmallVectorImpl<MCInst> &Instructions) {
2631 unsigned OpNum = Inst.getNumOperands();
2632 unsigned Opcode = Inst.getOpcode();
2633 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2634
2635 assert (Inst.getOperand(OpNum - 1).isImm() &&
2636 Inst.getOperand(OpNum - 2).isReg() &&
2637 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2638
2639 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2640 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2641 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2642 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2643 // It can be implemented as SWM16 or LWM16 instruction.
2644 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2645
2646 Inst.setOpcode(NewOpcode);
2647 Instructions.push_back(Inst);
2648 return false;
2649}
2650
Toma Tabacu1a108322015-06-17 13:20:24 +00002651bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2652 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002653 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00002654 unsigned PseudoOpcode = Inst.getOpcode();
2655 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002656 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00002657 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2658
2659 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002660 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002661
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002662 unsigned TrgReg;
2663 if (TrgOp.isReg())
2664 TrgReg = TrgOp.getReg();
2665 else if (TrgOp.isImm()) {
2666 warnIfNoMacro(IDLoc);
2667 EmittedNoMacroWarning = true;
2668
2669 TrgReg = getATReg(IDLoc);
2670 if (!TrgReg)
2671 return true;
2672
2673 switch(PseudoOpcode) {
2674 default:
2675 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2676 case Mips::BLTImmMacro:
2677 PseudoOpcode = Mips::BLT;
2678 break;
2679 case Mips::BLEImmMacro:
2680 PseudoOpcode = Mips::BLE;
2681 break;
2682 case Mips::BGEImmMacro:
2683 PseudoOpcode = Mips::BGE;
2684 break;
2685 case Mips::BGTImmMacro:
2686 PseudoOpcode = Mips::BGT;
2687 break;
2688 case Mips::BLTUImmMacro:
2689 PseudoOpcode = Mips::BLTU;
2690 break;
2691 case Mips::BLEUImmMacro:
2692 PseudoOpcode = Mips::BLEU;
2693 break;
2694 case Mips::BGEUImmMacro:
2695 PseudoOpcode = Mips::BGEU;
2696 break;
2697 case Mips::BGTUImmMacro:
2698 PseudoOpcode = Mips::BGTU;
2699 break;
2700 case Mips::BLTLImmMacro:
2701 PseudoOpcode = Mips::BLTL;
2702 break;
2703 case Mips::BLELImmMacro:
2704 PseudoOpcode = Mips::BLEL;
2705 break;
2706 case Mips::BGELImmMacro:
2707 PseudoOpcode = Mips::BGEL;
2708 break;
2709 case Mips::BGTLImmMacro:
2710 PseudoOpcode = Mips::BGTL;
2711 break;
2712 case Mips::BLTULImmMacro:
2713 PseudoOpcode = Mips::BLTUL;
2714 break;
2715 case Mips::BLEULImmMacro:
2716 PseudoOpcode = Mips::BLEUL;
2717 break;
2718 case Mips::BGEULImmMacro:
2719 PseudoOpcode = Mips::BGEUL;
2720 break;
2721 case Mips::BGTULImmMacro:
2722 PseudoOpcode = Mips::BGTUL;
2723 break;
2724 }
2725
2726 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
2727 false, IDLoc, Instructions))
2728 return true;
2729 }
2730
Toma Tabacu1a108322015-06-17 13:20:24 +00002731 switch (PseudoOpcode) {
2732 case Mips::BLT:
2733 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002734 case Mips::BLTL:
2735 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002736 AcceptsEquality = false;
2737 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002738 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2739 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002740 ZeroSrcOpcode = Mips::BGTZ;
2741 ZeroTrgOpcode = Mips::BLTZ;
2742 break;
2743 case Mips::BLE:
2744 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002745 case Mips::BLEL:
2746 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002747 AcceptsEquality = true;
2748 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002749 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2750 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002751 ZeroSrcOpcode = Mips::BGEZ;
2752 ZeroTrgOpcode = Mips::BLEZ;
2753 break;
2754 case Mips::BGE:
2755 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002756 case Mips::BGEL:
2757 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002758 AcceptsEquality = true;
2759 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002760 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2761 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002762 ZeroSrcOpcode = Mips::BLEZ;
2763 ZeroTrgOpcode = Mips::BGEZ;
2764 break;
2765 case Mips::BGT:
2766 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002767 case Mips::BGTL:
2768 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002769 AcceptsEquality = false;
2770 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002771 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2772 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002773 ZeroSrcOpcode = Mips::BLTZ;
2774 ZeroTrgOpcode = Mips::BGTZ;
2775 break;
2776 default:
2777 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2778 }
2779
Toma Tabacu1a108322015-06-17 13:20:24 +00002780 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2781 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2782 if (IsSrcRegZero && IsTrgRegZero) {
2783 // FIXME: All of these Opcode-specific if's are needed for compatibility
2784 // with GAS' behaviour. However, they may not generate the most efficient
2785 // code in some circumstances.
2786 if (PseudoOpcode == Mips::BLT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002787 emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2788 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002789 return false;
2790 }
2791 if (PseudoOpcode == Mips::BLE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002792 emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2793 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002794 Warning(IDLoc, "branch is always taken");
2795 return false;
2796 }
2797 if (PseudoOpcode == Mips::BGE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002798 emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2799 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002800 Warning(IDLoc, "branch is always taken");
2801 return false;
2802 }
2803 if (PseudoOpcode == Mips::BGT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002804 emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2805 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002806 return false;
2807 }
2808 if (PseudoOpcode == Mips::BGTU) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002809 emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
2810 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002811 return false;
2812 }
2813 if (AcceptsEquality) {
2814 // If both registers are $0 and the pseudo-branch accepts equality, it
2815 // will always be taken, so we emit an unconditional branch.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002816 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2817 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002818 Warning(IDLoc, "branch is always taken");
2819 return false;
2820 }
2821 // If both registers are $0 and the pseudo-branch does not accept
2822 // equality, it will never be taken, so we don't have to emit anything.
2823 return false;
2824 }
2825 if (IsSrcRegZero || IsTrgRegZero) {
2826 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2827 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2828 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2829 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2830 // the pseudo-branch will never be taken, so we don't emit anything.
2831 // This only applies to unsigned pseudo-branches.
2832 return false;
2833 }
2834 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2835 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2836 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2837 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2838 // the pseudo-branch will always be taken, so we emit an unconditional
2839 // branch.
2840 // This only applies to unsigned pseudo-branches.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002841 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2842 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002843 Warning(IDLoc, "branch is always taken");
2844 return false;
2845 }
2846 if (IsUnsigned) {
2847 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2848 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2849 // the pseudo-branch will be taken only when the non-zero register is
2850 // different from 0, so we emit a BNEZ.
2851 //
2852 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2853 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2854 // the pseudo-branch will be taken only when the non-zero register is
2855 // equal to 0, so we emit a BEQZ.
2856 //
2857 // Because only BLEU and BGEU branch on equality, we can use the
2858 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002859 emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
2860 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
2861 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002862 return false;
2863 }
2864 // If we have a signed pseudo-branch and one of the registers is $0,
2865 // we can use an appropriate compare-to-zero branch. We select which one
2866 // to use in the switch statement above.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002867 emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
2868 IsSrcRegZero ? TrgReg : SrcReg, MCOperand::createExpr(OffsetExpr),
2869 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002870 return false;
2871 }
2872
2873 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2874 // expansions. If it is not available, we return.
2875 unsigned ATRegNum = getATReg(IDLoc);
2876 if (!ATRegNum)
2877 return true;
2878
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002879 if (!EmittedNoMacroWarning)
2880 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00002881
2882 // SLT fits well with 2 of our 4 pseudo-branches:
2883 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2884 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2885 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2886 // This is accomplished by using a BNEZ with the result of the SLT.
2887 //
2888 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2889 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2890 // Because only BGE and BLE branch on equality, we can use the
2891 // AcceptsEquality variable to decide when to emit the BEQZ.
2892 // Note that the order of the SLT arguments doesn't change between
2893 // opposites.
2894 //
2895 // The same applies to the unsigned variants, except that SLTu is used
2896 // instead of SLT.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002897 emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
2898 ReverseOrderSLT ? TrgReg : SrcReg, ReverseOrderSLT ? SrcReg : TrgReg,
2899 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002900
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002901 emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
2902 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
2903 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2904 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002905 return false;
2906}
2907
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002908bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
2909 SmallVectorImpl<MCInst> &Instructions,
2910 const bool IsMips64, const bool Signed) {
2911 if (hasMips32r6()) {
2912 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2913 return false;
2914 }
2915
2916 warnIfNoMacro(IDLoc);
2917
2918 const MCOperand &RsRegOp = Inst.getOperand(0);
2919 assert(RsRegOp.isReg() && "expected register operand kind");
2920 unsigned RsReg = RsRegOp.getReg();
2921
2922 const MCOperand &RtRegOp = Inst.getOperand(1);
2923 assert(RtRegOp.isReg() && "expected register operand kind");
2924 unsigned RtReg = RtRegOp.getReg();
2925 unsigned DivOp;
2926 unsigned ZeroReg;
2927
2928 if (IsMips64) {
2929 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2930 ZeroReg = Mips::ZERO_64;
2931 } else {
2932 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2933 ZeroReg = Mips::ZERO;
2934 }
2935
2936 bool UseTraps = useTraps();
2937
2938 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2939 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2940 Warning(IDLoc, "dividing zero by zero");
2941 if (IsMips64) {
2942 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2943 if (UseTraps) {
2944 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2945 return false;
2946 }
2947
2948 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2949 return false;
2950 }
2951 } else {
2952 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2953 return false;
2954 }
2955 }
2956
2957 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
2958 Warning(IDLoc, "division by zero");
2959 if (Signed) {
2960 if (UseTraps) {
2961 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2962 return false;
2963 }
2964
2965 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2966 return false;
2967 }
2968 }
2969
2970 // FIXME: The values for these two BranchTarget variables may be different in
2971 // micromips. These magic numbers need to be removed.
2972 unsigned BranchTargetNoTraps;
2973 unsigned BranchTarget;
2974
2975 if (UseTraps) {
2976 BranchTarget = IsMips64 ? 12 : 8;
2977 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2978 } else {
2979 BranchTarget = IsMips64 ? 20 : 16;
2980 BranchTargetNoTraps = 8;
2981 // Branch to the li instruction.
2982 emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc,
2983 Instructions);
2984 }
2985
2986 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2987
2988 if (!UseTraps)
2989 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2990
2991 if (!Signed) {
2992 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
2993 return false;
2994 }
2995
2996 unsigned ATReg = getATReg(IDLoc);
2997 if (!ATReg)
2998 return true;
2999
3000 emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, Instructions);
3001 if (IsMips64) {
3002 // Branch to the mflo instruction.
3003 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
3004 emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, Instructions);
3005 emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, Instructions);
3006 } else {
3007 // Branch to the mflo instruction.
3008 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
3009 emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, Instructions);
3010 }
3011
3012 if (UseTraps)
3013 emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, Instructions);
3014 else {
3015 // Branch to the mflo instruction.
3016 emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, Instructions);
3017 emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, Instructions);
3018 emitII(Mips::BREAK, 0x6, 0, IDLoc, Instructions);
3019 }
3020 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
3021 return false;
3022}
3023
Daniel Sanders6394ee52015-10-15 14:52:58 +00003024bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
3025 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00003026 if (hasMips32r6() || hasMips64r6()) {
3027 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3028 return false;
3029 }
3030
3031 warnIfNoMacro(IDLoc);
3032
3033 const MCOperand &DstRegOp = Inst.getOperand(0);
3034 assert(DstRegOp.isReg() && "expected register operand kind");
3035
3036 const MCOperand &SrcRegOp = Inst.getOperand(1);
3037 assert(SrcRegOp.isReg() && "expected register operand kind");
3038
3039 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3040 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3041
3042 unsigned DstReg = DstRegOp.getReg();
3043 unsigned SrcReg = SrcRegOp.getReg();
3044 int64_t OffsetValue = OffsetImmOp.getImm();
3045
3046 // NOTE: We always need AT for ULHU, as it is always used as the source
3047 // register for one of the LBu's.
3048 unsigned ATReg = getATReg(IDLoc);
3049 if (!ATReg)
3050 return true;
3051
3052 // When the value of offset+1 does not fit in 16 bits, we have to load the
3053 // offset in AT, (D)ADDu the original source register (if there was one), and
3054 // then use AT as the source register for the 2 generated LBu's.
3055 bool LoadedOffsetInAT = false;
3056 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3057 LoadedOffsetInAT = true;
3058
3059 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003060 true, IDLoc, Instructions))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003061 return true;
3062
3063 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3064 // because it will make our output more similar to GAS'. For example,
3065 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3066 // instead of just an "ori $1, $9, 32768".
3067 // NOTE: If there is no source register specified in the ULHU, the parser
3068 // will interpret it as $0.
3069 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3070 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3071 }
3072
3073 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3074 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3075 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3076
3077 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3078 if (isLittle()) {
3079 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3080 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3081 } else {
3082 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3083 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3084 }
3085
3086 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3087
Daniel Sanders6394ee52015-10-15 14:52:58 +00003088 emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
3089 FirstLbuOffset, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003090
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003091 emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
3092 Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003093
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003094 emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003095
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003096 emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003097
3098 return false;
3099}
3100
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003101bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
3102 SmallVectorImpl<MCInst> &Instructions) {
3103 if (hasMips32r6() || hasMips64r6()) {
3104 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3105 return false;
3106 }
3107
3108 const MCOperand &DstRegOp = Inst.getOperand(0);
3109 assert(DstRegOp.isReg() && "expected register operand kind");
3110
3111 const MCOperand &SrcRegOp = Inst.getOperand(1);
3112 assert(SrcRegOp.isReg() && "expected register operand kind");
3113
3114 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3115 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3116
3117 unsigned SrcReg = SrcRegOp.getReg();
3118 int64_t OffsetValue = OffsetImmOp.getImm();
3119 unsigned ATReg = 0;
3120
3121 // When the value of offset+3 does not fit in 16 bits, we have to load the
3122 // offset in AT, (D)ADDu the original source register (if there was one), and
3123 // then use AT as the source register for the generated LWL and LWR.
3124 bool LoadedOffsetInAT = false;
3125 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3126 ATReg = getATReg(IDLoc);
3127 if (!ATReg)
3128 return true;
3129 LoadedOffsetInAT = true;
3130
3131 warnIfNoMacro(IDLoc);
3132
3133 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003134 true, IDLoc, Instructions))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003135 return true;
3136
3137 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3138 // because it will make our output more similar to GAS'. For example,
3139 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3140 // instead of just an "ori $1, $9, 32768".
3141 // NOTE: If there is no source register specified in the ULW, the parser
3142 // will interpret it as $0.
3143 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3144 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3145 }
3146
3147 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3148 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3149 if (isLittle()) {
3150 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3151 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3152 } else {
3153 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3154 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3155 }
3156
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003157 emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
3158 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003159
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003160 emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset, IDLoc,
3161 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003162
3163 return false;
3164}
3165
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003166bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
3167 SmallVectorImpl<MCInst> &Instructions) {
3168
3169 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3170 assert (Inst.getOperand(0).isReg() &&
3171 Inst.getOperand(1).isReg() &&
3172 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3173
3174 unsigned ATReg = Mips::NoRegister;
3175 unsigned FinalDstReg = Mips::NoRegister;
3176 unsigned DstReg = Inst.getOperand(0).getReg();
3177 unsigned SrcReg = Inst.getOperand(1).getReg();
3178 int64_t ImmValue = Inst.getOperand(2).getImm();
3179
3180 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3181
3182 unsigned FinalOpcode = Inst.getOpcode();
3183
3184 if (DstReg == SrcReg) {
3185 ATReg = getATReg(Inst.getLoc());
3186 if (!ATReg)
3187 return true;
3188 FinalDstReg = DstReg;
3189 DstReg = ATReg;
3190 }
3191
3192 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Instructions)) {
3193 switch (FinalOpcode) {
3194 default:
3195 llvm_unreachable("unimplemented expansion");
3196 case (Mips::ADDi):
3197 FinalOpcode = Mips::ADD;
3198 break;
3199 case (Mips::ADDiu):
3200 FinalOpcode = Mips::ADDu;
3201 break;
3202 case (Mips::ANDi):
3203 FinalOpcode = Mips::AND;
3204 break;
3205 case (Mips::NORImm):
3206 FinalOpcode = Mips::NOR;
3207 break;
3208 case (Mips::ORi):
3209 FinalOpcode = Mips::OR;
3210 break;
3211 case (Mips::SLTi):
3212 FinalOpcode = Mips::SLT;
3213 break;
3214 case (Mips::SLTiu):
3215 FinalOpcode = Mips::SLTu;
3216 break;
3217 case (Mips::XORi):
3218 FinalOpcode = Mips::XOR;
3219 break;
3220 }
3221
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003222 if (FinalDstReg == Mips::NoRegister)
3223 emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, Instructions);
3224 else
3225 emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc,
3226 Instructions);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003227 return false;
3228 }
3229 return true;
3230}
3231
Toma Tabacu234482a2015-03-16 12:03:39 +00003232void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
3233 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003234 if (hasShortDelaySlot)
3235 emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, Instructions);
3236 else
3237 emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, Instructions);
Toma Tabacu234482a2015-03-16 12:03:39 +00003238}
3239
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003240void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +00003241 unsigned TrgReg, bool Is64Bit,
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003242 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders03f9c012015-07-14 12:24:22 +00003243 emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
3244 Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003245}
3246
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003247void MipsAsmParser::createCpRestoreMemOp(
3248 bool IsLoad, int StackOffset, SMLoc IDLoc,
3249 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003250 // If the offset can not fit into 16 bits, we need to expand.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003251 if (!isInt<16>(StackOffset)) {
3252 MCInst MemInst;
3253 MemInst.setOpcode(IsLoad ? Mips::LW : Mips::SW);
3254 MemInst.addOperand(MCOperand::createReg(Mips::GP));
3255 MemInst.addOperand(MCOperand::createReg(Mips::SP));
3256 MemInst.addOperand(MCOperand::createImm(StackOffset));
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003257 expandMemInst(MemInst, IDLoc, Instructions, IsLoad, true /*HasImmOpnd*/);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003258 return;
3259 }
3260
3261 emitRRI(IsLoad ? Mips::LW : Mips::SW, Mips::GP, Mips::SP, StackOffset, IDLoc,
3262 Instructions);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003263}
3264
Matheus Almeida595fcab2014-06-11 15:05:56 +00003265unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3266 // As described by the Mips32r2 spec, the registers Rd and Rs for
3267 // jalr.hb must be different.
3268 unsigned Opcode = Inst.getOpcode();
3269
3270 if (Opcode == Mips::JALR_HB &&
3271 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3272 return Match_RequiresDifferentSrcAndDst;
3273
3274 return Match_Success;
3275}
3276
David Blaikie960ea3f2014-06-08 16:18:35 +00003277bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3278 OperandVector &Operands,
3279 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003280 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003281 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003282
Jack Carterb4dbc172012-09-05 23:34:03 +00003283 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00003284 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00003285 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003286 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003287
3288 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003289 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003290 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00003291 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00003292 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00003293 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00003294 return false;
3295 }
3296 case Match_MissingFeature:
3297 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3298 return true;
3299 case Match_InvalidOperand: {
3300 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003301 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003302 if (ErrorInfo >= Operands.size())
3303 return Error(IDLoc, "too few operands for instruction");
3304
David Blaikie960ea3f2014-06-08 16:18:35 +00003305 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003306 if (ErrorLoc == SMLoc())
3307 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003308 }
3309
3310 return Error(ErrorLoc, "invalid operand for instruction");
3311 }
3312 case Match_MnemonicFail:
3313 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003314 case Match_RequiresDifferentSrcAndDst:
3315 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00003316 }
Craig Topper589ceee2015-01-03 08:16:34 +00003317
3318 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003319}
3320
Toma Tabacud9d344b2015-04-27 14:05:04 +00003321void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3322 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3323 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3324 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003325}
3326
Toma Tabacu81496c12015-05-20 08:54:45 +00003327void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3328 if (!AssemblerOptions.back()->isMacro())
3329 Warning(Loc, "macro instruction expanded into multiple instructions");
3330}
3331
Daniel Sandersef638fe2014-10-03 15:37:37 +00003332void
3333MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3334 SMRange Range, bool ShowColors) {
3335 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003336 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003337 ShowColors);
3338}
3339
Jack Carter1ac53222013-02-20 23:11:17 +00003340int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003341 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003342
Vladimir Medic4c299852013-11-06 11:27:05 +00003343 CC = StringSwitch<unsigned>(Name)
3344 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003345 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003346 .Case("a0", 4)
3347 .Case("a1", 5)
3348 .Case("a2", 6)
3349 .Case("a3", 7)
3350 .Case("v0", 2)
3351 .Case("v1", 3)
3352 .Case("s0", 16)
3353 .Case("s1", 17)
3354 .Case("s2", 18)
3355 .Case("s3", 19)
3356 .Case("s4", 20)
3357 .Case("s5", 21)
3358 .Case("s6", 22)
3359 .Case("s7", 23)
3360 .Case("k0", 26)
3361 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003362 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003363 .Case("sp", 29)
3364 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003365 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003366 .Case("ra", 31)
3367 .Case("t0", 8)
3368 .Case("t1", 9)
3369 .Case("t2", 10)
3370 .Case("t3", 11)
3371 .Case("t4", 12)
3372 .Case("t5", 13)
3373 .Case("t6", 14)
3374 .Case("t7", 15)
3375 .Case("t8", 24)
3376 .Case("t9", 25)
3377 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003378
Toma Tabacufda445c2014-09-15 15:33:01 +00003379 if (!(isABI_N32() || isABI_N64()))
3380 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003381
Daniel Sandersef638fe2014-10-03 15:37:37 +00003382 if (12 <= CC && CC <= 15) {
3383 // Name is one of t4-t7
3384 AsmToken RegTok = getLexer().peekTok();
3385 SMRange RegRange = RegTok.getLocRange();
3386
3387 StringRef FixedName = StringSwitch<StringRef>(Name)
3388 .Case("t4", "t0")
3389 .Case("t5", "t1")
3390 .Case("t6", "t2")
3391 .Case("t7", "t3")
3392 .Default("");
3393 assert(FixedName != "" && "Register name is not one of t4-t7.");
3394
3395 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3396 "Did you mean $" + FixedName + "?", RegRange);
3397 }
3398
Toma Tabacufda445c2014-09-15 15:33:01 +00003399 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3400 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3401 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3402 if (8 <= CC && CC <= 11)
3403 CC += 4;
3404
3405 if (CC == -1)
3406 CC = StringSwitch<unsigned>(Name)
3407 .Case("a4", 8)
3408 .Case("a5", 9)
3409 .Case("a6", 10)
3410 .Case("a7", 11)
3411 .Case("kt0", 26)
3412 .Case("kt1", 27)
3413 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003414
3415 return CC;
3416}
Jack Carterd0bd6422013-04-18 00:41:53 +00003417
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003418int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3419 int CC;
3420
3421 CC = StringSwitch<unsigned>(Name)
3422 .Case("hwr_cpunum", 0)
3423 .Case("hwr_synci_step", 1)
3424 .Case("hwr_cc", 2)
3425 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003426 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003427 .Default(-1);
3428
3429 return CC;
3430}
3431
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003432int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003433
Jack Cartera63b16a2012-09-07 00:23:42 +00003434 if (Name[0] == 'f') {
3435 StringRef NumString = Name.substr(1);
3436 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003437 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003438 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003439 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003440 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003441 return IntVal;
3442 }
3443 return -1;
3444}
Jack Cartera63b16a2012-09-07 00:23:42 +00003445
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003446int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3447
3448 if (Name.startswith("fcc")) {
3449 StringRef NumString = Name.substr(3);
3450 unsigned IntVal;
3451 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003452 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003453 if (IntVal > 7) // There are only 8 fcc registers.
3454 return -1;
3455 return IntVal;
3456 }
3457 return -1;
3458}
3459
3460int MipsAsmParser::matchACRegisterName(StringRef Name) {
3461
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003462 if (Name.startswith("ac")) {
3463 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003464 unsigned IntVal;
3465 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003466 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003467 if (IntVal > 3) // There are only 3 acc registers.
3468 return -1;
3469 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003470 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003471 return -1;
3472}
Jack Carterd0bd6422013-04-18 00:41:53 +00003473
Jack Carter5dc8ac92013-09-25 23:50:44 +00003474int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3475 unsigned IntVal;
3476
3477 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3478 return -1;
3479
3480 if (IntVal > 31)
3481 return -1;
3482
3483 return IntVal;
3484}
3485
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003486int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3487 int CC;
3488
3489 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003490 .Case("msair", 0)
3491 .Case("msacsr", 1)
3492 .Case("msaaccess", 2)
3493 .Case("msasave", 3)
3494 .Case("msamodify", 4)
3495 .Case("msarequest", 5)
3496 .Case("msamap", 6)
3497 .Case("msaunmap", 7)
3498 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003499
3500 return CC;
3501}
3502
Toma Tabacu89a712b2015-04-15 10:48:56 +00003503unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00003504 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00003505 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00003506 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00003507 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00003508 return 0;
3509 }
3510 unsigned AT = getReg(
3511 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00003512 return AT;
3513}
Jack Carter0b744b32012-10-04 02:29:46 +00003514
Jack Carterd0bd6422013-04-18 00:41:53 +00003515unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00003516 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00003517}
3518
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003519unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003520 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00003521 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003522}
3523
Jack Carter873c7242013-01-12 01:03:14 +00003524int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003525 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00003526 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00003527 return -1;
3528
Jack Carter873c7242013-01-12 01:03:14 +00003529 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00003530}
3531
Toma Tabacu13964452014-09-04 13:23:44 +00003532bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003533 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003534 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003535
Jack Carter30a59822012-10-04 04:03:53 +00003536 // Check if the current operand has a custom associated parser, if so, try to
3537 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00003538 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3539 if (ResTy == MatchOperand_Success)
3540 return false;
3541 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3542 // there was a match, but an error occurred, in which case, just return that
3543 // the operand parsing failed.
3544 if (ResTy == MatchOperand_ParseFail)
3545 return true;
3546
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003547 DEBUG(dbgs() << ".. Generic Parser\n");
3548
Jack Carterb4dbc172012-09-05 23:34:03 +00003549 switch (getLexer().getKind()) {
3550 default:
3551 Error(Parser.getTok().getLoc(), "unexpected token in operand");
3552 return true;
3553 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003554 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00003555 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00003556
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003557 // Almost all registers have been parsed by custom parsers. There is only
3558 // one exception to this. $zero (and it's alias $0) will reach this point
3559 // for div, divu, and similar instructions because it is not an operand
3560 // to the instruction definition but an explicit register. Special case
3561 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00003562 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00003563 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003564
Jack Carterd0bd6422013-04-18 00:41:53 +00003565 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00003566 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003567 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00003568 return true;
3569
Jack Carter873c7242013-01-12 01:03:14 +00003570 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00003571 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00003572 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00003573 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003574 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00003575
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003576 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003577 return false;
3578 }
Vladimir Medic4c299852013-11-06 11:27:05 +00003579 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00003580 case AsmToken::LParen:
3581 case AsmToken::Minus:
3582 case AsmToken::Plus:
3583 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003584 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00003585 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003586 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003587 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003588 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00003589 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00003590 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003591 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003592 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003593 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00003594 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00003595 return true;
3596
Jack Carter873c7242013-01-12 01:03:14 +00003597 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3598
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003599 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00003600 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003601 } // case AsmToken::Percent
3602 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00003603 return true;
3604}
3605
Vladimir Medic4c299852013-11-06 11:27:05 +00003606const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00003607 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003608 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00003609 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003610 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00003611 // It's a constant, evaluate reloc value.
3612 int16_t Val;
3613 switch (getVariantKind(RelocStr)) {
3614 case MCSymbolRefExpr::VK_Mips_ABS_LO:
3615 // Get the 1st 16-bits.
3616 Val = MCE->getValue() & 0xffff;
3617 break;
3618 case MCSymbolRefExpr::VK_Mips_ABS_HI:
3619 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
3620 // 16 bits being negative.
3621 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
3622 break;
3623 case MCSymbolRefExpr::VK_Mips_HIGHER:
3624 // Get the 3rd 16-bits.
3625 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
3626 break;
3627 case MCSymbolRefExpr::VK_Mips_HIGHEST:
3628 // Get the 4th 16-bits.
3629 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
3630 break;
3631 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00003632 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00003633 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00003634 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003635 }
3636
Jack Carterb5cf5902013-04-17 00:18:04 +00003637 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003638 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00003639 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00003640 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003641 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003642 return Res;
3643 }
3644
3645 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00003646 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
3647
Sasa Stankovic06c47802014-04-03 10:37:45 +00003648 // Try to create target expression.
3649 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00003650 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003651
Jack Carterd0bd6422013-04-18 00:41:53 +00003652 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
3653 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003654 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003655 return Res;
3656 }
3657
3658 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003659 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003660 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00003661 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00003662 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003663 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003664 return Expr;
3665}
3666
3667bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
3668
3669 switch (Expr->getKind()) {
3670 case MCExpr::Constant:
3671 return true;
3672 case MCExpr::SymbolRef:
3673 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
3674 case MCExpr::Binary:
3675 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
3676 if (!isEvaluated(BE->getLHS()))
3677 return false;
3678 return isEvaluated(BE->getRHS());
3679 }
3680 case MCExpr::Unary:
3681 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003682 case MCExpr::Target:
3683 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003684 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003685 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00003686}
Jack Carterd0bd6422013-04-18 00:41:53 +00003687
Jack Carterb5cf5902013-04-17 00:18:04 +00003688bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003689 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003690 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00003691 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00003692 if (Tok.isNot(AsmToken::Identifier))
3693 return true;
3694
Yaron Keren075759a2015-03-30 15:42:36 +00003695 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00003696
Jack Carterd0bd6422013-04-18 00:41:53 +00003697 Parser.Lex(); // Eat the identifier.
3698 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003699 const MCExpr *IdVal;
3700 SMLoc EndLoc;
3701
3702 if (getLexer().getKind() == AsmToken::LParen) {
3703 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003704 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003705 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003706 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003707 const AsmToken &nextTok = Parser.getTok();
3708 if (nextTok.isNot(AsmToken::Identifier))
3709 return true;
3710 Str += "(%";
3711 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00003712 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00003713 if (getLexer().getKind() != AsmToken::LParen)
3714 return true;
3715 } else
3716 break;
3717 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003718 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00003719 return true;
3720
3721 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00003722 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003723
3724 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00003725 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003726
Jack Carterd0bd6422013-04-18 00:41:53 +00003727 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00003728 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003729}
3730
Jack Carterb4dbc172012-09-05 23:34:03 +00003731bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
3732 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003733 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00003734 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003735 if (ResTy == MatchOperand_Success) {
3736 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00003737 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003738 StartLoc = Operand.getStartLoc();
3739 EndLoc = Operand.getEndLoc();
3740
3741 // AFAIK, we only support numeric registers and named GPR's in CFI
3742 // directives.
3743 // Don't worry about eating tokens before failing. Using an unrecognised
3744 // register is a parse error.
3745 if (Operand.isGPRAsmReg()) {
3746 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003747 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003748 }
3749
3750 return (RegNo == (unsigned)-1);
3751 }
3752
3753 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00003754 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00003755}
3756
Jack Carterb5cf5902013-04-17 00:18:04 +00003757bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003758 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00003759 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003760 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003761 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00003762
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003763 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003764 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003765 ++NumOfLParen;
3766 }
Jack Carter873c7242013-01-12 01:03:14 +00003767
Jack Carterd0bd6422013-04-18 00:41:53 +00003768 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003769 default:
3770 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00003771 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00003772 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00003773 case AsmToken::Integer:
3774 case AsmToken::Minus:
3775 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00003776 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003777 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00003778 else
3779 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00003780 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00003781 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003782 break;
Jack Carter873c7242013-01-12 01:03:14 +00003783 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00003784 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003785 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003786 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003787}
3788
David Blaikie960ea3f2014-06-08 16:18:35 +00003789MipsAsmParser::OperandMatchResultTy
3790MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003791 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003792 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00003793 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00003794 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003795 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003796 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00003797 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00003798 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00003799
Jack Carterb5cf5902013-04-17 00:18:04 +00003800 if (getLexer().getKind() == AsmToken::LParen) {
3801 Parser.Lex();
3802 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003803 }
3804
Jack Carterb5cf5902013-04-17 00:18:04 +00003805 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003806 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00003807 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003808
Jack Carterd0bd6422013-04-18 00:41:53 +00003809 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003810 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003811 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003812 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003813 SMLoc E =
3814 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003815 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003816 return MatchOperand_Success;
3817 }
3818 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003819 SMLoc E =
3820 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00003821
Jack Carterd0bd6422013-04-18 00:41:53 +00003822 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003823 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00003824 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003825 S, E, *this);
3826 Operands.push_back(
3827 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003828 return MatchOperand_Success;
3829 }
3830 Error(Parser.getTok().getLoc(), "'(' expected");
3831 return MatchOperand_ParseFail;
3832 }
3833
Jack Carterd0bd6422013-04-18 00:41:53 +00003834 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003835 }
3836
Toma Tabacu13964452014-09-04 13:23:44 +00003837 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003838 if (Res != MatchOperand_Success)
3839 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003840
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003841 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003842 Error(Parser.getTok().getLoc(), "')' expected");
3843 return MatchOperand_ParseFail;
3844 }
3845
Jack Carter873c7242013-01-12 01:03:14 +00003846 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3847
Jack Carterd0bd6422013-04-18 00:41:53 +00003848 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003849
Craig Topper062a2ba2014-04-25 05:30:21 +00003850 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003851 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003852
Jack Carterd0bd6422013-04-18 00:41:53 +00003853 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00003854 std::unique_ptr<MipsOperand> op(
3855 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00003856 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003857 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003858 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00003859 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003860 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
3861 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003862 if (IdVal->evaluateAsAbsolute(Imm))
3863 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003864 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003865 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00003866 getContext());
3867 }
3868
David Blaikie960ea3f2014-06-08 16:18:35 +00003869 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003870 return MatchOperand_Success;
3871}
3872
David Blaikie960ea3f2014-06-08 16:18:35 +00003873bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003874 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00003875 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00003876 if (Sym) {
3877 SMLoc S = Parser.getTok().getLoc();
3878 const MCExpr *Expr;
3879 if (Sym->isVariable())
3880 Expr = Sym->getVariableValue();
3881 else
3882 return false;
3883 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003884 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00003885 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00003886 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003887 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003888 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00003889 if (ResTy == MatchOperand_Success) {
3890 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00003891 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00003892 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003893 llvm_unreachable("Should never ParseFail");
3894 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00003895 }
3896 } else if (Expr->getKind() == MCExpr::Constant) {
3897 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00003898 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00003899 Operands.push_back(
3900 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00003901 return true;
3902 }
3903 }
3904 return false;
3905}
Jack Carterd0bd6422013-04-18 00:41:53 +00003906
Jack Carter873c7242013-01-12 01:03:14 +00003907MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003908MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00003909 StringRef Identifier,
3910 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003911 int Index = matchCPURegisterName(Identifier);
3912 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003913 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003914 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3915 return MatchOperand_Success;
3916 }
3917
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003918 Index = matchHWRegsRegisterName(Identifier);
3919 if (Index != -1) {
3920 Operands.push_back(MipsOperand::createHWRegsReg(
3921 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3922 return MatchOperand_Success;
3923 }
3924
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003925 Index = matchFPURegisterName(Identifier);
3926 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003927 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003928 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3929 return MatchOperand_Success;
3930 }
3931
3932 Index = matchFCCRegisterName(Identifier);
3933 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003934 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003935 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3936 return MatchOperand_Success;
3937 }
3938
3939 Index = matchACRegisterName(Identifier);
3940 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003941 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003942 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3943 return MatchOperand_Success;
3944 }
3945
3946 Index = matchMSA128RegisterName(Identifier);
3947 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003948 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003949 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3950 return MatchOperand_Success;
3951 }
3952
3953 Index = matchMSA128CtrlRegisterName(Identifier);
3954 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003955 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003956 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3957 return MatchOperand_Success;
3958 }
3959
3960 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00003961}
3962
3963MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003964MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003965 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00003966 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003967
3968 if (Token.is(AsmToken::Identifier)) {
3969 DEBUG(dbgs() << ".. identifier\n");
3970 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00003971 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003972 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00003973 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003974 } else if (Token.is(AsmToken::Integer)) {
3975 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003976 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003977 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
3978 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003979 return MatchOperand_Success;
3980 }
3981
3982 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
3983
3984 return MatchOperand_NoMatch;
3985}
3986
David Blaikie960ea3f2014-06-08 16:18:35 +00003987MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003988MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003989 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003990 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003991
3992 auto Token = Parser.getTok();
3993
3994 SMLoc S = Token.getLoc();
3995
3996 if (Token.isNot(AsmToken::Dollar)) {
3997 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
3998 if (Token.is(AsmToken::Identifier)) {
3999 if (searchSymbolAlias(Operands))
4000 return MatchOperand_Success;
4001 }
4002 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4003 return MatchOperand_NoMatch;
4004 }
4005 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004006
Toma Tabacu13964452014-09-04 13:23:44 +00004007 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004008 if (ResTy == MatchOperand_Success) {
4009 Parser.Lex(); // $
4010 Parser.Lex(); // identifier
4011 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004012 return ResTy;
4013}
4014
4015MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004016MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004017 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004018 switch (getLexer().getKind()) {
4019 default:
4020 return MatchOperand_NoMatch;
4021 case AsmToken::LParen:
4022 case AsmToken::Minus:
4023 case AsmToken::Plus:
4024 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004025 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004026 case AsmToken::String:
4027 break;
4028 }
4029
4030 const MCExpr *IdVal;
4031 SMLoc S = Parser.getTok().getLoc();
4032 if (getParser().parseExpression(IdVal))
4033 return MatchOperand_ParseFail;
4034
4035 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4036 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4037 return MatchOperand_Success;
4038}
4039
David Blaikie960ea3f2014-06-08 16:18:35 +00004040MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004041MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004042 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004043 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004044
4045 SMLoc S = getLexer().getLoc();
4046
4047 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00004048 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004049 if (ResTy != MatchOperand_NoMatch)
4050 return ResTy;
4051
Daniel Sanders315386c2014-04-01 10:40:14 +00004052 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00004053 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00004054 if (ResTy != MatchOperand_NoMatch)
4055 return ResTy;
4056
Daniel Sandersffd84362014-04-01 10:41:48 +00004057 const MCExpr *Expr = nullptr;
4058 if (Parser.parseExpression(Expr)) {
4059 // We have no way of knowing if a symbol was consumed so we must ParseFail
4060 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004061 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004062 Operands.push_back(
4063 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004064 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004065}
4066
Vladimir Medic2b953d02013-10-01 09:48:56 +00004067MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004068MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004069 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004070 const MCExpr *IdVal;
4071 // If the first token is '$' we may have register operand.
4072 if (Parser.getTok().is(AsmToken::Dollar))
4073 return MatchOperand_NoMatch;
4074 SMLoc S = Parser.getTok().getLoc();
4075 if (getParser().parseExpression(IdVal))
4076 return MatchOperand_ParseFail;
4077 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004078 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004079 int64_t Val = MCE->getValue();
4080 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4081 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004082 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004083 return MatchOperand_Success;
4084}
4085
Matheus Almeida779c5932013-11-18 12:32:49 +00004086MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004087MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004088 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00004089 switch (getLexer().getKind()) {
4090 default:
4091 return MatchOperand_NoMatch;
4092 case AsmToken::LParen:
4093 case AsmToken::Plus:
4094 case AsmToken::Minus:
4095 case AsmToken::Integer:
4096 break;
4097 }
4098
4099 const MCExpr *Expr;
4100 SMLoc S = Parser.getTok().getLoc();
4101
4102 if (getParser().parseExpression(Expr))
4103 return MatchOperand_ParseFail;
4104
4105 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004106 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00004107 Error(S, "expected immediate value");
4108 return MatchOperand_ParseFail;
4109 }
4110
4111 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
4112 // and because the CPU always adds one to the immediate field, the allowed
4113 // range becomes 1..4. We'll only check the range here and will deal
4114 // with the addition/subtraction when actually decoding/encoding
4115 // the instruction.
4116 if (Val < 1 || Val > 4) {
4117 Error(S, "immediate not in range (1..4)");
4118 return MatchOperand_ParseFail;
4119 }
4120
Jack Carter3b2c96e2014-01-22 23:31:38 +00004121 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004122 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00004123 return MatchOperand_Success;
4124}
4125
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004126MipsAsmParser::OperandMatchResultTy
4127MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4128 MCAsmParser &Parser = getParser();
4129 SmallVector<unsigned, 10> Regs;
4130 unsigned RegNo;
4131 unsigned PrevReg = Mips::NoRegister;
4132 bool RegRange = false;
4133 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4134
4135 if (Parser.getTok().isNot(AsmToken::Dollar))
4136 return MatchOperand_ParseFail;
4137
4138 SMLoc S = Parser.getTok().getLoc();
4139 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4140 SMLoc E = getLexer().getLoc();
4141 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4142 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4143 if (RegRange) {
4144 // Remove last register operand because registers from register range
4145 // should be inserted first.
4146 if (RegNo == Mips::RA) {
4147 Regs.push_back(RegNo);
4148 } else {
4149 unsigned TmpReg = PrevReg + 1;
4150 while (TmpReg <= RegNo) {
4151 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
4152 Error(E, "invalid register operand");
4153 return MatchOperand_ParseFail;
4154 }
4155
4156 PrevReg = TmpReg;
4157 Regs.push_back(TmpReg++);
4158 }
4159 }
4160
4161 RegRange = false;
4162 } else {
4163 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
4164 (RegNo != Mips::RA)) {
4165 Error(E, "$16 or $31 expected");
4166 return MatchOperand_ParseFail;
4167 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
4168 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
4169 Error(E, "invalid register operand");
4170 return MatchOperand_ParseFail;
4171 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
4172 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
4173 Error(E, "consecutive register numbers expected");
4174 return MatchOperand_ParseFail;
4175 }
4176
4177 Regs.push_back(RegNo);
4178 }
4179
4180 if (Parser.getTok().is(AsmToken::Minus))
4181 RegRange = true;
4182
4183 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4184 !Parser.getTok().isNot(AsmToken::Comma)) {
4185 Error(E, "',' or '-' expected");
4186 return MatchOperand_ParseFail;
4187 }
4188
4189 Lex(); // Consume comma or minus
4190 if (Parser.getTok().isNot(AsmToken::Dollar))
4191 break;
4192
4193 PrevReg = RegNo;
4194 }
4195
4196 SMLoc E = Parser.getTok().getLoc();
4197 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4198 parseMemOperand(Operands);
4199 return MatchOperand_Success;
4200}
4201
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004202MipsAsmParser::OperandMatchResultTy
4203MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4204 MCAsmParser &Parser = getParser();
4205
4206 SMLoc S = Parser.getTok().getLoc();
4207 if (parseAnyRegister(Operands) != MatchOperand_Success)
4208 return MatchOperand_ParseFail;
4209
4210 SMLoc E = Parser.getTok().getLoc();
4211 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
4212 unsigned Reg = Op.getGPR32Reg();
4213 Operands.pop_back();
4214 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
4215 return MatchOperand_Success;
4216}
4217
Zoran Jovanovic41688672015-02-10 16:36:20 +00004218MipsAsmParser::OperandMatchResultTy
4219MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4220 MCAsmParser &Parser = getParser();
4221 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4222 SmallVector<unsigned, 10> Regs;
4223
4224 if (Parser.getTok().isNot(AsmToken::Dollar))
4225 return MatchOperand_ParseFail;
4226
4227 SMLoc S = Parser.getTok().getLoc();
4228
4229 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4230 return MatchOperand_ParseFail;
4231
4232 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4233 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4234 Regs.push_back(RegNo);
4235
4236 SMLoc E = Parser.getTok().getLoc();
4237 if (Parser.getTok().isNot(AsmToken::Comma)) {
4238 Error(E, "',' expected");
4239 return MatchOperand_ParseFail;
4240 }
4241
4242 // Remove comma.
4243 Parser.Lex();
4244
4245 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4246 return MatchOperand_ParseFail;
4247
4248 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4249 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4250 Regs.push_back(RegNo);
4251
4252 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4253
4254 return MatchOperand_Success;
4255}
4256
Jack Carterdc1e35d2012-09-06 20:00:02 +00004257MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
4258
Vladimir Medic4c299852013-11-06 11:27:05 +00004259 MCSymbolRefExpr::VariantKind VK =
4260 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
4261 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
4262 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
4263 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
4264 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
4265 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
4266 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
4267 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
4268 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
4269 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
4270 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
4271 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
4272 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
4273 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
4274 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
4275 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
4276 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
4277 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00004278 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
4279 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
4280 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
4281 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
4282 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
4283 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00004284 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
4285 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00004286 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004287
Matheus Almeida2852af82014-04-22 10:15:54 +00004288 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00004289
Jack Carterdc1e35d2012-09-06 20:00:02 +00004290 return VK;
4291}
Jack Cartera63b16a2012-09-07 00:23:42 +00004292
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004293/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4294/// either this.
4295/// ::= '(', register, ')'
4296/// handle it before we iterate so we don't get tripped up by the lack of
4297/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004298bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004299 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004300 if (getLexer().is(AsmToken::LParen)) {
4301 Operands.push_back(
4302 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4303 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004304 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004305 SMLoc Loc = getLexer().getLoc();
4306 Parser.eatToEndOfStatement();
4307 return Error(Loc, "unexpected token in argument list");
4308 }
4309 if (Parser.getTok().isNot(AsmToken::RParen)) {
4310 SMLoc Loc = getLexer().getLoc();
4311 Parser.eatToEndOfStatement();
4312 return Error(Loc, "unexpected token, expected ')'");
4313 }
4314 Operands.push_back(
4315 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4316 Parser.Lex();
4317 }
4318 return false;
4319}
4320
4321/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4322/// either one of these.
4323/// ::= '[', register, ']'
4324/// ::= '[', integer, ']'
4325/// handle it before we iterate so we don't get tripped up by the lack of
4326/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004327bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004328 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004329 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004330 if (getLexer().is(AsmToken::LBrac)) {
4331 Operands.push_back(
4332 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4333 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004334 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004335 SMLoc Loc = getLexer().getLoc();
4336 Parser.eatToEndOfStatement();
4337 return Error(Loc, "unexpected token in argument list");
4338 }
4339 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4340 SMLoc Loc = getLexer().getLoc();
4341 Parser.eatToEndOfStatement();
4342 return Error(Loc, "unexpected token, expected ']'");
4343 }
4344 Operands.push_back(
4345 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4346 Parser.Lex();
4347 }
4348 return false;
4349}
4350
David Blaikie960ea3f2014-06-08 16:18:35 +00004351bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4352 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004353 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004354 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004355
4356 // We have reached first instruction, module directive are now forbidden.
4357 getTargetStreamer().forbidModuleDirective();
4358
Vladimir Medic74593e62013-07-17 15:00:42 +00004359 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004360 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004361 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004362 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004363 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004364 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004365 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004366
4367 // Read the remaining operands.
4368 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4369 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004370 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004371 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004372 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004373 return Error(Loc, "unexpected token in argument list");
4374 }
Toma Tabacu13964452014-09-04 13:23:44 +00004375 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004376 return true;
4377 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004378
Jack Carterd0bd6422013-04-18 00:41:53 +00004379 while (getLexer().is(AsmToken::Comma)) {
4380 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004381 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004382 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004383 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004384 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004385 return Error(Loc, "unexpected token in argument list");
4386 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004387 // Parse bracket and parenthesis suffixes before we iterate
4388 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004389 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004390 return true;
4391 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004392 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004393 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004394 }
4395 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004396 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4397 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004398 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004399 return Error(Loc, "unexpected token in argument list");
4400 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004401 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004402 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004403}
4404
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004405bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004406 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004407 SMLoc Loc = getLexer().getLoc();
4408 Parser.eatToEndOfStatement();
4409 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004410}
4411
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004412bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004413 return Error(Loc, ErrorMsg);
4414}
4415
Jack Carter0b744b32012-10-04 02:29:46 +00004416bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004417 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004418 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004419
4420 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004421 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004422
4423 Parser.Lex(); // Eat "noat".
4424
Jack Carterd0bd6422013-04-18 00:41:53 +00004425 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004426 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004427 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004428 return false;
4429 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004430
4431 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004432 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004433 return false;
4434}
Jack Carterd0bd6422013-04-18 00:41:53 +00004435
Jack Carter0b744b32012-10-04 02:29:46 +00004436bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004437 // Line can be: ".set at", which sets $at to $1
4438 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004439 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004440 Parser.Lex(); // Eat "at".
4441
Jack Carter0b744b32012-10-04 02:29:46 +00004442 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004443 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004444 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004445
4446 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004447 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004448 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004449 }
4450
4451 if (getLexer().isNot(AsmToken::Equal)) {
4452 reportParseError("unexpected token, expected equals sign");
4453 return false;
4454 }
4455 Parser.Lex(); // Eat "=".
4456
4457 if (getLexer().isNot(AsmToken::Dollar)) {
4458 if (getLexer().is(AsmToken::EndOfStatement)) {
4459 reportParseError("no register specified");
4460 return false;
4461 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004462 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004463 return false;
4464 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004465 }
4466 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004467
Toma Tabacu16a74492015-02-13 10:30:57 +00004468 // Find out what "reg" is.
4469 unsigned AtRegNo;
4470 const AsmToken &Reg = Parser.getTok();
4471 if (Reg.is(AsmToken::Identifier)) {
4472 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4473 } else if (Reg.is(AsmToken::Integer)) {
4474 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004475 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004476 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004477 return false;
4478 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004479
4480 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004481 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004482 reportParseError("invalid register");
4483 return false;
4484 }
4485 Parser.Lex(); // Eat "reg".
4486
4487 // If this is not the end of the statement, report an error.
4488 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4489 reportParseError("unexpected token, expected end of statement");
4490 return false;
4491 }
4492
4493 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4494
4495 Parser.Lex(); // Consume the EndOfStatement.
4496 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004497}
4498
4499bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004500 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004501 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004502 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004503 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004504 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004505 return false;
4506 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004507 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004508 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004509 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004510 return false;
4511}
4512
4513bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004514 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004515 Parser.Lex();
4516 // If this is not the end of the statement, report an error.
4517 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004518 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004519 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00004520 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004521 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00004522 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004523 Parser.Lex(); // Consume the EndOfStatement.
4524 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004525}
4526
4527bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004528 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004529 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004530 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004531 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004532 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004533 return false;
4534 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004535 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004536 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004537 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004538 return false;
4539}
4540
4541bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004542 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004543 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004544 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004545 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004546 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004547 return false;
4548 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004549 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00004550 reportParseError("`noreorder' must be set before `nomacro'");
4551 return false;
4552 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004553 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004554 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004555 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004556 return false;
4557}
Jack Carterd76b2372013-03-21 21:44:16 +00004558
Daniel Sanders44934432014-08-07 12:03:36 +00004559bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004560 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004561 Parser.Lex();
4562
4563 // If this is not the end of the statement, report an error.
4564 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004565 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004566
4567 setFeatureBits(Mips::FeatureMSA, "msa");
4568 getTargetStreamer().emitDirectiveSetMsa();
4569 return false;
4570}
4571
4572bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004573 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004574 Parser.Lex();
4575
4576 // If this is not the end of the statement, report an error.
4577 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004578 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004579
4580 clearFeatureBits(Mips::FeatureMSA, "msa");
4581 getTargetStreamer().emitDirectiveSetNoMsa();
4582 return false;
4583}
4584
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004585bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004586 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004587 Parser.Lex(); // Eat "nodsp".
4588
4589 // If this is not the end of the statement, report an error.
4590 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4591 reportParseError("unexpected token, expected end of statement");
4592 return false;
4593 }
4594
4595 clearFeatureBits(Mips::FeatureDSP, "dsp");
4596 getTargetStreamer().emitDirectiveSetNoDsp();
4597 return false;
4598}
4599
Toma Tabacucc2502d2014-11-04 17:18:07 +00004600bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004601 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004602 Parser.Lex(); // Eat "mips16".
4603
Jack Carter39536722014-01-22 23:08:42 +00004604 // If this is not the end of the statement, report an error.
4605 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004606 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00004607 return false;
4608 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00004609
4610 setFeatureBits(Mips::FeatureMips16, "mips16");
4611 getTargetStreamer().emitDirectiveSetMips16();
4612 Parser.Lex(); // Consume the EndOfStatement.
4613 return false;
4614}
4615
4616bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004617 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004618 Parser.Lex(); // Eat "nomips16".
4619
4620 // If this is not the end of the statement, report an error.
4621 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4622 reportParseError("unexpected token, expected end of statement");
4623 return false;
4624 }
4625
4626 clearFeatureBits(Mips::FeatureMips16, "mips16");
4627 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00004628 Parser.Lex(); // Consume the EndOfStatement.
4629 return false;
4630}
4631
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004632bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004633 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004634 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004635 // Line can be: .set fp=32
4636 // .set fp=xx
4637 // .set fp=64
4638 Parser.Lex(); // Eat fp token
4639 AsmToken Tok = Parser.getTok();
4640 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004641 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004642 return false;
4643 }
4644 Parser.Lex(); // Eat '=' token.
4645 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004646
4647 if (!parseFpABIValue(FpAbiVal, ".set"))
4648 return false;
4649
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004650 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004651 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004652 return false;
4653 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004654 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004655 Parser.Lex(); // Consume the EndOfStatement.
4656 return false;
4657}
4658
Toma Tabacu32c72aa2015-06-30 09:36:50 +00004659bool MipsAsmParser::parseSetOddSPRegDirective() {
4660 MCAsmParser &Parser = getParser();
4661
4662 Parser.Lex(); // Eat "oddspreg".
4663 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4664 reportParseError("unexpected token, expected end of statement");
4665 return false;
4666 }
4667
4668 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4669 getTargetStreamer().emitDirectiveSetOddSPReg();
4670 return false;
4671}
4672
4673bool MipsAsmParser::parseSetNoOddSPRegDirective() {
4674 MCAsmParser &Parser = getParser();
4675
4676 Parser.Lex(); // Eat "nooddspreg".
4677 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4678 reportParseError("unexpected token, expected end of statement");
4679 return false;
4680 }
4681
4682 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4683 getTargetStreamer().emitDirectiveSetNoOddSPReg();
4684 return false;
4685}
4686
Toma Tabacu9db22db2014-09-09 10:15:38 +00004687bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004688 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004689 SMLoc Loc = getLexer().getLoc();
4690
4691 Parser.Lex();
4692 if (getLexer().isNot(AsmToken::EndOfStatement))
4693 return reportParseError("unexpected token, expected end of statement");
4694
4695 // Always keep an element on the options "stack" to prevent the user
4696 // from changing the initial options. This is how we remember them.
4697 if (AssemblerOptions.size() == 2)
4698 return reportParseError(Loc, ".set pop with no .set push");
4699
4700 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00004701 setAvailableFeatures(
4702 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
4703 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00004704
4705 getTargetStreamer().emitDirectiveSetPop();
4706 return false;
4707}
4708
4709bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004710 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004711 Parser.Lex();
4712 if (getLexer().isNot(AsmToken::EndOfStatement))
4713 return reportParseError("unexpected token, expected end of statement");
4714
4715 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00004716 AssemblerOptions.push_back(
4717 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00004718
4719 getTargetStreamer().emitDirectiveSetPush();
4720 return false;
4721}
4722
Toma Tabacu29696502015-06-02 09:48:04 +00004723bool MipsAsmParser::parseSetSoftFloatDirective() {
4724 MCAsmParser &Parser = getParser();
4725 Parser.Lex();
4726 if (getLexer().isNot(AsmToken::EndOfStatement))
4727 return reportParseError("unexpected token, expected end of statement");
4728
4729 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4730 getTargetStreamer().emitDirectiveSetSoftFloat();
4731 return false;
4732}
4733
4734bool MipsAsmParser::parseSetHardFloatDirective() {
4735 MCAsmParser &Parser = getParser();
4736 Parser.Lex();
4737 if (getLexer().isNot(AsmToken::EndOfStatement))
4738 return reportParseError("unexpected token, expected end of statement");
4739
4740 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4741 getTargetStreamer().emitDirectiveSetHardFloat();
4742 return false;
4743}
4744
Jack Carterd76b2372013-03-21 21:44:16 +00004745bool MipsAsmParser::parseSetAssignment() {
4746 StringRef Name;
4747 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00004748 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00004749
4750 if (Parser.parseIdentifier(Name))
4751 reportParseError("expected identifier after .set");
4752
4753 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004754 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00004755 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00004756
Jack Carter3b2c96e2014-01-22 23:31:38 +00004757 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00004758 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00004759
Jim Grosbach6f482002015-05-18 18:43:14 +00004760 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00004761 Sym->setVariableValue(Value);
4762
4763 return false;
4764}
Jack Carterd0bd6422013-04-18 00:41:53 +00004765
Toma Tabacu26647792014-09-09 12:52:14 +00004766bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004767 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00004768 Parser.Lex();
4769 if (getLexer().isNot(AsmToken::EndOfStatement))
4770 return reportParseError("unexpected token, expected end of statement");
4771
4772 // Reset assembler options to their initial values.
Toma Tabacu465acfd2015-06-09 13:33:26 +00004773 setAvailableFeatures(
4774 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
4775 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00004776 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
4777
4778 getTargetStreamer().emitDirectiveSetMips0();
4779 return false;
4780}
4781
Toma Tabacu85618b32014-08-19 14:22:52 +00004782bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004783 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00004784 Parser.Lex();
4785 if (getLexer().isNot(AsmToken::Equal))
4786 return reportParseError("unexpected token, expected equals sign");
4787
4788 Parser.Lex();
4789 StringRef Arch;
4790 if (Parser.parseIdentifier(Arch))
4791 return reportParseError("expected arch identifier");
4792
4793 StringRef ArchFeatureName =
4794 StringSwitch<StringRef>(Arch)
4795 .Case("mips1", "mips1")
4796 .Case("mips2", "mips2")
4797 .Case("mips3", "mips3")
4798 .Case("mips4", "mips4")
4799 .Case("mips5", "mips5")
4800 .Case("mips32", "mips32")
4801 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004802 .Case("mips32r3", "mips32r3")
4803 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004804 .Case("mips32r6", "mips32r6")
4805 .Case("mips64", "mips64")
4806 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004807 .Case("mips64r3", "mips64r3")
4808 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004809 .Case("mips64r6", "mips64r6")
4810 .Case("cnmips", "cnmips")
4811 .Case("r4000", "mips3") // This is an implementation of Mips3.
4812 .Default("");
4813
4814 if (ArchFeatureName.empty())
4815 return reportParseError("unsupported architecture");
4816
4817 selectArch(ArchFeatureName);
4818 getTargetStreamer().emitDirectiveSetArch(Arch);
4819 return false;
4820}
4821
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004822bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004823 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004824 Parser.Lex();
4825 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004826 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004827
Matheus Almeida2852af82014-04-22 10:15:54 +00004828 switch (Feature) {
4829 default:
4830 llvm_unreachable("Unimplemented feature");
4831 case Mips::FeatureDSP:
4832 setFeatureBits(Mips::FeatureDSP, "dsp");
4833 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004834 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004835 case Mips::FeatureMicroMips:
4836 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004837 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004838 case Mips::FeatureMips1:
4839 selectArch("mips1");
4840 getTargetStreamer().emitDirectiveSetMips1();
4841 break;
4842 case Mips::FeatureMips2:
4843 selectArch("mips2");
4844 getTargetStreamer().emitDirectiveSetMips2();
4845 break;
4846 case Mips::FeatureMips3:
4847 selectArch("mips3");
4848 getTargetStreamer().emitDirectiveSetMips3();
4849 break;
4850 case Mips::FeatureMips4:
4851 selectArch("mips4");
4852 getTargetStreamer().emitDirectiveSetMips4();
4853 break;
4854 case Mips::FeatureMips5:
4855 selectArch("mips5");
4856 getTargetStreamer().emitDirectiveSetMips5();
4857 break;
4858 case Mips::FeatureMips32:
4859 selectArch("mips32");
4860 getTargetStreamer().emitDirectiveSetMips32();
4861 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004862 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004863 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004864 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004865 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004866 case Mips::FeatureMips32r3:
4867 selectArch("mips32r3");
4868 getTargetStreamer().emitDirectiveSetMips32R3();
4869 break;
4870 case Mips::FeatureMips32r5:
4871 selectArch("mips32r5");
4872 getTargetStreamer().emitDirectiveSetMips32R5();
4873 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004874 case Mips::FeatureMips32r6:
4875 selectArch("mips32r6");
4876 getTargetStreamer().emitDirectiveSetMips32R6();
4877 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004878 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004879 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00004880 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00004881 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004882 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004883 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004884 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00004885 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004886 case Mips::FeatureMips64r3:
4887 selectArch("mips64r3");
4888 getTargetStreamer().emitDirectiveSetMips64R3();
4889 break;
4890 case Mips::FeatureMips64r5:
4891 selectArch("mips64r5");
4892 getTargetStreamer().emitDirectiveSetMips64R5();
4893 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004894 case Mips::FeatureMips64r6:
4895 selectArch("mips64r6");
4896 getTargetStreamer().emitDirectiveSetMips64R6();
4897 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004898 }
4899 return false;
4900}
4901
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004902bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004903 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004904 if (getLexer().isNot(AsmToken::Comma)) {
4905 SMLoc Loc = getLexer().getLoc();
4906 Parser.eatToEndOfStatement();
4907 return Error(Loc, ErrorStr);
4908 }
4909
Matheus Almeida2852af82014-04-22 10:15:54 +00004910 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004911 return true;
4912}
4913
Daniel Sanderse2982ad2015-09-17 16:08:39 +00004914// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
4915// In this class, it is only used for .cprestore.
4916// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
4917// MipsTargetELFStreamer and MipsAsmParser.
4918bool MipsAsmParser::isPicAndNotNxxAbi() {
4919 return inPicMode() && !(isABI_N32() || isABI_N64());
4920}
4921
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004922bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00004923 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00004924 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004925
Toma Tabacudde4c462014-11-06 10:02:45 +00004926 if (inMips16Mode()) {
4927 reportParseError(".cpload is not supported in Mips16 mode");
4928 return false;
4929 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004930
David Blaikie960ea3f2014-06-08 16:18:35 +00004931 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00004932 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004933 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4934 reportParseError("expected register containing function address");
4935 return false;
4936 }
4937
David Blaikie960ea3f2014-06-08 16:18:35 +00004938 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
4939 if (!RegOpnd.isGPRAsmReg()) {
4940 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004941 return false;
4942 }
4943
Toma Tabacudde4c462014-11-06 10:02:45 +00004944 // If this is not the end of the statement, report an error.
4945 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4946 reportParseError("unexpected token, expected end of statement");
4947 return false;
4948 }
4949
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004950 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004951 return false;
4952}
4953
Daniel Sanderse2982ad2015-09-17 16:08:39 +00004954bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
4955 MCAsmParser &Parser = getParser();
4956
4957 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
4958 // is used in non-PIC mode.
4959
4960 if (inMips16Mode()) {
4961 reportParseError(".cprestore is not supported in Mips16 mode");
4962 return false;
4963 }
4964
4965 // Get the stack offset value.
4966 const MCExpr *StackOffset;
4967 int64_t StackOffsetVal;
4968 if (Parser.parseExpression(StackOffset)) {
4969 reportParseError("expected stack offset value");
4970 return false;
4971 }
4972
4973 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
4974 reportParseError("stack offset is not an absolute expression");
4975 return false;
4976 }
4977
4978 if (StackOffsetVal < 0) {
4979 Warning(Loc, ".cprestore with negative stack offset has no effect");
4980 IsCpRestoreSet = false;
4981 } else {
4982 IsCpRestoreSet = true;
4983 CpRestoreOffset = StackOffsetVal;
4984 }
4985
4986 // If this is not the end of the statement, report an error.
4987 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4988 reportParseError("unexpected token, expected end of statement");
4989 return false;
4990 }
4991
4992 // Store the $gp on the stack.
4993 SmallVector<MCInst, 3> StoreInsts;
4994 createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc,
4995 StoreInsts);
4996
4997 getTargetStreamer().emitDirectiveCpRestore(StoreInsts, CpRestoreOffset);
4998 Parser.Lex(); // Consume the EndOfStatement.
4999 return false;
5000}
5001
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005002bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005003 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005004 unsigned FuncReg;
5005 unsigned Save;
5006 bool SaveIsReg = true;
5007
Matheus Almeida7e815762014-06-18 13:08:59 +00005008 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005009 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005010 if (ResTy == MatchOperand_NoMatch) {
5011 reportParseError("expected register containing function address");
5012 Parser.eatToEndOfStatement();
5013 return false;
5014 }
5015
5016 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5017 if (!FuncRegOpnd.isGPRAsmReg()) {
5018 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
5019 Parser.eatToEndOfStatement();
5020 return false;
5021 }
5022
5023 FuncReg = FuncRegOpnd.getGPR32Reg();
5024 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005025
Toma Tabacu65f10572014-09-16 15:00:52 +00005026 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005027 return true;
5028
Toma Tabacu13964452014-09-04 13:23:44 +00005029 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005030 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005031 const MCExpr *OffsetExpr;
5032 int64_t OffsetVal;
5033 SMLoc ExprLoc = getLexer().getLoc();
5034
5035 if (Parser.parseExpression(OffsetExpr) ||
5036 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5037 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005038 Parser.eatToEndOfStatement();
5039 return false;
5040 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005041
5042 Save = OffsetVal;
5043 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005044 } else {
5045 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5046 if (!SaveOpnd.isGPRAsmReg()) {
5047 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5048 Parser.eatToEndOfStatement();
5049 return false;
5050 }
5051 Save = SaveOpnd.getGPR32Reg();
5052 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005053
Toma Tabacu65f10572014-09-16 15:00:52 +00005054 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005055 return true;
5056
Toma Tabacu8874eac2015-02-18 13:46:53 +00005057 const MCExpr *Expr;
5058 if (Parser.parseExpression(Expr)) {
5059 reportParseError("expected expression");
5060 return false;
5061 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005062
Toma Tabacu8874eac2015-02-18 13:46:53 +00005063 if (Expr->getKind() != MCExpr::SymbolRef) {
5064 reportParseError("expected symbol");
5065 return false;
5066 }
5067 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5068
Daniel Sandersf173dda2015-09-22 10:50:09 +00005069 CpSaveLocation = Save;
5070 CpSaveLocationIsRegister = SaveIsReg;
5071
Toma Tabacu8874eac2015-02-18 13:46:53 +00005072 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5073 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005074 return false;
5075}
5076
Daniel Sandersf173dda2015-09-22 10:50:09 +00005077bool MipsAsmParser::parseDirectiveCPReturn() {
5078 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5079 CpSaveLocationIsRegister);
5080 return false;
5081}
5082
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005083bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005084 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005085 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5086 const AsmToken &Tok = Parser.getTok();
5087
5088 if (Tok.getString() == "2008") {
5089 Parser.Lex();
5090 getTargetStreamer().emitDirectiveNaN2008();
5091 return false;
5092 } else if (Tok.getString() == "legacy") {
5093 Parser.Lex();
5094 getTargetStreamer().emitDirectiveNaNLegacy();
5095 return false;
5096 }
5097 }
5098 // If we don't recognize the option passed to the .nan
5099 // directive (e.g. no option or unknown option), emit an error.
5100 reportParseError("invalid option in .nan directive");
5101 return false;
5102}
5103
Jack Carter0b744b32012-10-04 02:29:46 +00005104bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005105 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005106 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005107 const AsmToken &Tok = Parser.getTok();
5108
5109 if (Tok.getString() == "noat") {
5110 return parseSetNoAtDirective();
5111 } else if (Tok.getString() == "at") {
5112 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005113 } else if (Tok.getString() == "arch") {
5114 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005115 } else if (Tok.getString() == "fp") {
5116 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005117 } else if (Tok.getString() == "oddspreg") {
5118 return parseSetOddSPRegDirective();
5119 } else if (Tok.getString() == "nooddspreg") {
5120 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005121 } else if (Tok.getString() == "pop") {
5122 return parseSetPopDirective();
5123 } else if (Tok.getString() == "push") {
5124 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005125 } else if (Tok.getString() == "reorder") {
5126 return parseSetReorderDirective();
5127 } else if (Tok.getString() == "noreorder") {
5128 return parseSetNoReorderDirective();
5129 } else if (Tok.getString() == "macro") {
5130 return parseSetMacroDirective();
5131 } else if (Tok.getString() == "nomacro") {
5132 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005133 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005134 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005135 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005136 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005137 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005138 getTargetStreamer().emitDirectiveSetNoMicroMips();
5139 Parser.eatToEndOfStatement();
5140 return false;
5141 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005142 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005143 } else if (Tok.getString() == "mips0") {
5144 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005145 } else if (Tok.getString() == "mips1") {
5146 return parseSetFeature(Mips::FeatureMips1);
5147 } else if (Tok.getString() == "mips2") {
5148 return parseSetFeature(Mips::FeatureMips2);
5149 } else if (Tok.getString() == "mips3") {
5150 return parseSetFeature(Mips::FeatureMips3);
5151 } else if (Tok.getString() == "mips4") {
5152 return parseSetFeature(Mips::FeatureMips4);
5153 } else if (Tok.getString() == "mips5") {
5154 return parseSetFeature(Mips::FeatureMips5);
5155 } else if (Tok.getString() == "mips32") {
5156 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005157 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005158 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005159 } else if (Tok.getString() == "mips32r3") {
5160 return parseSetFeature(Mips::FeatureMips32r3);
5161 } else if (Tok.getString() == "mips32r5") {
5162 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005163 } else if (Tok.getString() == "mips32r6") {
5164 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005165 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005166 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005167 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005168 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005169 } else if (Tok.getString() == "mips64r3") {
5170 return parseSetFeature(Mips::FeatureMips64r3);
5171 } else if (Tok.getString() == "mips64r5") {
5172 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005173 } else if (Tok.getString() == "mips64r6") {
5174 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005175 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005176 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005177 } else if (Tok.getString() == "nodsp") {
5178 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005179 } else if (Tok.getString() == "msa") {
5180 return parseSetMsaDirective();
5181 } else if (Tok.getString() == "nomsa") {
5182 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005183 } else if (Tok.getString() == "softfloat") {
5184 return parseSetSoftFloatDirective();
5185 } else if (Tok.getString() == "hardfloat") {
5186 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005187 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005188 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005189 parseSetAssignment();
5190 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005191 }
Jack Carter07c818d2013-01-25 01:31:34 +00005192
Jack Carter0b744b32012-10-04 02:29:46 +00005193 return true;
5194}
5195
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005196/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005197/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005198bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005199 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005200 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5201 for (;;) {
5202 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005203 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005204 return true;
5205
5206 getParser().getStreamer().EmitValue(Value, Size);
5207
5208 if (getLexer().is(AsmToken::EndOfStatement))
5209 break;
5210
Jack Carter07c818d2013-01-25 01:31:34 +00005211 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005212 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005213 Parser.Lex();
5214 }
5215 }
5216
5217 Parser.Lex();
5218 return false;
5219}
5220
Vladimir Medic4c299852013-11-06 11:27:05 +00005221/// parseDirectiveGpWord
5222/// ::= .gpword local_sym
5223bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005224 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005225 const MCExpr *Value;
5226 // EmitGPRel32Value requires an expression, so we are using base class
5227 // method to evaluate the expression.
5228 if (getParser().parseExpression(Value))
5229 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005230 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005231
Vladimir Medice10c1122013-11-13 13:18:04 +00005232 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005233 return Error(getLexer().getLoc(),
5234 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005235 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005236 return false;
5237}
5238
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005239/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005240/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005241bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005242 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005243 const MCExpr *Value;
5244 // EmitGPRel64Value requires an expression, so we are using base class
5245 // method to evaluate the expression.
5246 if (getParser().parseExpression(Value))
5247 return true;
5248 getParser().getStreamer().EmitGPRel64Value(Value);
5249
5250 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005251 return Error(getLexer().getLoc(),
5252 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005253 Parser.Lex(); // Eat EndOfStatement token.
5254 return false;
5255}
5256
Jack Carter0cd3c192014-01-06 23:27:31 +00005257bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005258 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005259 // Get the option token.
5260 AsmToken Tok = Parser.getTok();
5261 // At the moment only identifiers are supported.
5262 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005263 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005264 Parser.eatToEndOfStatement();
5265 return false;
5266 }
5267
5268 StringRef Option = Tok.getIdentifier();
5269
5270 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005271 // MipsAsmParser needs to know if the current PIC mode changes.
5272 IsPicEnabled = false;
5273
Jack Carter0cd3c192014-01-06 23:27:31 +00005274 getTargetStreamer().emitDirectiveOptionPic0();
5275 Parser.Lex();
5276 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5277 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005278 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005279 Parser.eatToEndOfStatement();
5280 }
5281 return false;
5282 }
5283
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005284 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005285 // MipsAsmParser needs to know if the current PIC mode changes.
5286 IsPicEnabled = true;
5287
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005288 getTargetStreamer().emitDirectiveOptionPic2();
5289 Parser.Lex();
5290 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5291 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005292 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005293 Parser.eatToEndOfStatement();
5294 }
5295 return false;
5296 }
5297
Jack Carter0cd3c192014-01-06 23:27:31 +00005298 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005299 Warning(Parser.getTok().getLoc(),
5300 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005301 Parser.eatToEndOfStatement();
5302 return false;
5303}
5304
Toma Tabacu9ca50962015-04-16 09:53:47 +00005305/// parseInsnDirective
5306/// ::= .insn
5307bool MipsAsmParser::parseInsnDirective() {
5308 // If this is not the end of the statement, report an error.
5309 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5310 reportParseError("unexpected token, expected end of statement");
5311 return false;
5312 }
5313
5314 // The actual label marking happens in
5315 // MipsELFStreamer::createPendingLabelRelocs().
5316 getTargetStreamer().emitDirectiveInsn();
5317
5318 getParser().Lex(); // Eat EndOfStatement token.
5319 return false;
5320}
5321
Daniel Sanders7e527422014-07-10 13:38:23 +00005322/// parseDirectiveModule
5323/// ::= .module oddspreg
5324/// ::= .module nooddspreg
5325/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005326/// ::= .module softfloat
5327/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005328bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005329 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005330 MCAsmLexer &Lexer = getLexer();
5331 SMLoc L = Lexer.getLoc();
5332
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005333 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005334 // TODO : get a better message.
5335 reportParseError(".module directive must appear before any code");
5336 return false;
5337 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005338
Toma Tabacuc405c822015-01-23 10:40:19 +00005339 StringRef Option;
5340 if (Parser.parseIdentifier(Option)) {
5341 reportParseError("expected .module option identifier");
5342 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005343 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005344
Toma Tabacuc405c822015-01-23 10:40:19 +00005345 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005346 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005347
Toma Tabacu3c499582015-06-25 10:56:57 +00005348 // Synchronize the abiflags information with the FeatureBits information we
5349 // changed above.
5350 getTargetStreamer().updateABIInfo(*this);
5351
5352 // If printing assembly, use the recently updated abiflags information.
5353 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5354 // emitted at the end).
5355 getTargetStreamer().emitDirectiveModuleOddSPReg();
5356
Toma Tabacuc405c822015-01-23 10:40:19 +00005357 // If this is not the end of the statement, report an error.
5358 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5359 reportParseError("unexpected token, expected end of statement");
5360 return false;
5361 }
5362
5363 return false; // parseDirectiveModule has finished successfully.
5364 } else if (Option == "nooddspreg") {
5365 if (!isABI_O32()) {
5366 Error(L, "'.module nooddspreg' requires the O32 ABI");
5367 return false;
5368 }
5369
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005370 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005371
Toma Tabacu3c499582015-06-25 10:56:57 +00005372 // Synchronize the abiflags information with the FeatureBits information we
5373 // changed above.
5374 getTargetStreamer().updateABIInfo(*this);
5375
5376 // If printing assembly, use the recently updated abiflags information.
5377 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5378 // emitted at the end).
5379 getTargetStreamer().emitDirectiveModuleOddSPReg();
5380
Toma Tabacuc405c822015-01-23 10:40:19 +00005381 // If this is not the end of the statement, report an error.
5382 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5383 reportParseError("unexpected token, expected end of statement");
5384 return false;
5385 }
5386
5387 return false; // parseDirectiveModule has finished successfully.
5388 } else if (Option == "fp") {
5389 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005390 } else if (Option == "softfloat") {
5391 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5392
5393 // Synchronize the ABI Flags information with the FeatureBits information we
5394 // updated above.
5395 getTargetStreamer().updateABIInfo(*this);
5396
5397 // If printing assembly, use the recently updated ABI Flags information.
5398 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5399 // emitted later).
5400 getTargetStreamer().emitDirectiveModuleSoftFloat();
5401
5402 // If this is not the end of the statement, report an error.
5403 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5404 reportParseError("unexpected token, expected end of statement");
5405 return false;
5406 }
5407
5408 return false; // parseDirectiveModule has finished successfully.
5409 } else if (Option == "hardfloat") {
5410 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5411
5412 // Synchronize the ABI Flags information with the FeatureBits information we
5413 // updated above.
5414 getTargetStreamer().updateABIInfo(*this);
5415
5416 // If printing assembly, use the recently updated ABI Flags information.
5417 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5418 // emitted later).
5419 getTargetStreamer().emitDirectiveModuleHardFloat();
5420
5421 // If this is not the end of the statement, report an error.
5422 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5423 reportParseError("unexpected token, expected end of statement");
5424 return false;
5425 }
5426
5427 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005428 } else {
5429 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5430 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005431}
5432
5433/// parseDirectiveModuleFP
5434/// ::= =32
5435/// ::= =xx
5436/// ::= =64
5437bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005438 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005439 MCAsmLexer &Lexer = getLexer();
5440
5441 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005442 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005443 return false;
5444 }
5445 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005446
Daniel Sanders7e527422014-07-10 13:38:23 +00005447 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005448 if (!parseFpABIValue(FpABI, ".module"))
5449 return false;
5450
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005451 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005452 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005453 return false;
5454 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005455
Toma Tabacua64e5402015-06-25 12:44:38 +00005456 // Synchronize the abiflags information with the FeatureBits information we
5457 // changed above.
5458 getTargetStreamer().updateABIInfo(*this);
5459
5460 // If printing assembly, use the recently updated abiflags information.
5461 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5462 // emitted at the end).
5463 getTargetStreamer().emitDirectiveModuleFP();
5464
Daniel Sanders7e527422014-07-10 13:38:23 +00005465 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005466 return false;
5467}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005468
Daniel Sanders7e527422014-07-10 13:38:23 +00005469bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005470 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005471 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005472 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005473 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005474
5475 if (Lexer.is(AsmToken::Identifier)) {
5476 StringRef Value = Parser.getTok().getString();
5477 Parser.Lex();
5478
5479 if (Value != "xx") {
5480 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5481 return false;
5482 }
5483
5484 if (!isABI_O32()) {
5485 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5486 return false;
5487 }
5488
Daniel Sanders7e527422014-07-10 13:38:23 +00005489 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005490 if (ModuleLevelOptions) {
5491 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5492 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5493 } else {
5494 setFeatureBits(Mips::FeatureFPXX, "fpxx");
5495 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5496 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005497 return true;
5498 }
5499
5500 if (Lexer.is(AsmToken::Integer)) {
5501 unsigned Value = Parser.getTok().getIntVal();
5502 Parser.Lex();
5503
5504 if (Value != 32 && Value != 64) {
5505 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5506 return false;
5507 }
5508
5509 if (Value == 32) {
5510 if (!isABI_O32()) {
5511 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
5512 return false;
5513 }
5514
Daniel Sanders7e527422014-07-10 13:38:23 +00005515 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005516 if (ModuleLevelOptions) {
5517 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5518 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5519 } else {
5520 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5521 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5522 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005523 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00005524 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005525 if (ModuleLevelOptions) {
5526 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5527 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5528 } else {
5529 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5530 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
5531 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005532 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005533
Daniel Sanders7e527422014-07-10 13:38:23 +00005534 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005535 }
5536
5537 return false;
5538}
5539
Jack Carter0b744b32012-10-04 02:29:46 +00005540bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005541 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005542 StringRef IDVal = DirectiveID.getString();
5543
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005544 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005545 return parseDirectiveCpLoad(DirectiveID.getLoc());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005546 if (IDVal == ".cprestore")
5547 return parseDirectiveCpRestore(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00005548 if (IDVal == ".dword") {
5549 parseDataDirective(8, DirectiveID.getLoc());
5550 return false;
5551 }
Jack Carterd0bd6422013-04-18 00:41:53 +00005552 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005553 StringRef SymbolName;
5554
5555 if (Parser.parseIdentifier(SymbolName)) {
5556 reportParseError("expected identifier after .ent");
5557 return false;
5558 }
5559
5560 // There's an undocumented extension that allows an integer to
5561 // follow the name of the procedure which AFAICS is ignored by GAS.
5562 // Example: .ent foo,2
5563 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5564 if (getLexer().isNot(AsmToken::Comma)) {
5565 // Even though we accept this undocumented extension for compatibility
5566 // reasons, the additional integer argument does not actually change
5567 // the behaviour of the '.ent' directive, so we would like to discourage
5568 // its use. We do this by not referring to the extended version in
5569 // error messages which are not directly related to its use.
5570 reportParseError("unexpected token, expected end of statement");
5571 return false;
5572 }
5573 Parser.Lex(); // Eat the comma.
5574 const MCExpr *DummyNumber;
5575 int64_t DummyNumberVal;
5576 // If the user was explicitly trying to use the extended version,
5577 // we still give helpful extension-related error messages.
5578 if (Parser.parseExpression(DummyNumber)) {
5579 reportParseError("expected number after comma");
5580 return false;
5581 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00005582 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005583 reportParseError("expected an absolute expression after comma");
5584 return false;
5585 }
5586 }
5587
5588 // If this is not the end of the statement, report an error.
5589 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5590 reportParseError("unexpected token, expected end of statement");
5591 return false;
5592 }
5593
Jim Grosbach6f482002015-05-18 18:43:14 +00005594 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005595
5596 getTargetStreamer().emitDirectiveEnt(*Sym);
5597 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005598 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005599 return false;
5600 }
5601
Jack Carter07c818d2013-01-25 01:31:34 +00005602 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005603 StringRef SymbolName;
5604
5605 if (Parser.parseIdentifier(SymbolName)) {
5606 reportParseError("expected identifier after .end");
5607 return false;
5608 }
5609
5610 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5611 reportParseError("unexpected token, expected end of statement");
5612 return false;
5613 }
5614
5615 if (CurrentFn == nullptr) {
5616 reportParseError(".end used without .ent");
5617 return false;
5618 }
5619
5620 if ((SymbolName != CurrentFn->getName())) {
5621 reportParseError(".end symbol does not match .ent symbol");
5622 return false;
5623 }
5624
5625 getTargetStreamer().emitDirectiveEnd(SymbolName);
5626 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005627 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005628 return false;
5629 }
5630
Jack Carter07c818d2013-01-25 01:31:34 +00005631 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005632 // .frame $stack_reg, frame_size_in_bytes, $return_reg
5633 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005634 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005635 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5636 reportParseError("expected stack register");
5637 return false;
5638 }
5639
5640 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5641 if (!StackRegOpnd.isGPRAsmReg()) {
5642 reportParseError(StackRegOpnd.getStartLoc(),
5643 "expected general purpose register");
5644 return false;
5645 }
5646 unsigned StackReg = StackRegOpnd.getGPR32Reg();
5647
5648 if (Parser.getTok().is(AsmToken::Comma))
5649 Parser.Lex();
5650 else {
5651 reportParseError("unexpected token, expected comma");
5652 return false;
5653 }
5654
5655 // Parse the frame size.
5656 const MCExpr *FrameSize;
5657 int64_t FrameSizeVal;
5658
5659 if (Parser.parseExpression(FrameSize)) {
5660 reportParseError("expected frame size value");
5661 return false;
5662 }
5663
Jim Grosbach13760bd2015-05-30 01:25:56 +00005664 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005665 reportParseError("frame size not an absolute expression");
5666 return false;
5667 }
5668
5669 if (Parser.getTok().is(AsmToken::Comma))
5670 Parser.Lex();
5671 else {
5672 reportParseError("unexpected token, expected comma");
5673 return false;
5674 }
5675
5676 // Parse the return register.
5677 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00005678 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005679 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5680 reportParseError("expected return register");
5681 return false;
5682 }
5683
5684 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5685 if (!ReturnRegOpnd.isGPRAsmReg()) {
5686 reportParseError(ReturnRegOpnd.getStartLoc(),
5687 "expected general purpose register");
5688 return false;
5689 }
5690
5691 // If this is not the end of the statement, report an error.
5692 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5693 reportParseError("unexpected token, expected end of statement");
5694 return false;
5695 }
5696
5697 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
5698 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005699 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005700 return false;
5701 }
5702
Jack Carter07c818d2013-01-25 01:31:34 +00005703 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00005704 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00005705 }
5706
Daniel Sandersd97a6342014-08-13 10:07:34 +00005707 if (IDVal == ".mask" || IDVal == ".fmask") {
5708 // .mask bitmask, frame_offset
5709 // bitmask: One bit for each register used.
5710 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
5711 // first register is expected to be saved.
5712 // Examples:
5713 // .mask 0x80000000, -4
5714 // .fmask 0x80000000, -4
5715 //
Jack Carterbe332172012-09-07 00:48:02 +00005716
Daniel Sandersd97a6342014-08-13 10:07:34 +00005717 // Parse the bitmask
5718 const MCExpr *BitMask;
5719 int64_t BitMaskVal;
5720
5721 if (Parser.parseExpression(BitMask)) {
5722 reportParseError("expected bitmask value");
5723 return false;
5724 }
5725
Jim Grosbach13760bd2015-05-30 01:25:56 +00005726 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005727 reportParseError("bitmask not an absolute expression");
5728 return false;
5729 }
5730
5731 if (Parser.getTok().is(AsmToken::Comma))
5732 Parser.Lex();
5733 else {
5734 reportParseError("unexpected token, expected comma");
5735 return false;
5736 }
5737
5738 // Parse the frame_offset
5739 const MCExpr *FrameOffset;
5740 int64_t FrameOffsetVal;
5741
5742 if (Parser.parseExpression(FrameOffset)) {
5743 reportParseError("expected frame offset value");
5744 return false;
5745 }
5746
Jim Grosbach13760bd2015-05-30 01:25:56 +00005747 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005748 reportParseError("frame offset not an absolute expression");
5749 return false;
5750 }
5751
5752 // If this is not the end of the statement, report an error.
5753 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5754 reportParseError("unexpected token, expected end of statement");
5755 return false;
5756 }
5757
5758 if (IDVal == ".mask")
5759 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
5760 else
5761 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00005762 return false;
5763 }
5764
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005765 if (IDVal == ".nan")
5766 return parseDirectiveNaN();
5767
Jack Carter07c818d2013-01-25 01:31:34 +00005768 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005769 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00005770 return false;
5771 }
5772
Rafael Espindolab59fb732014-03-28 18:50:26 +00005773 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005774 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005775 return false;
5776 }
5777
Jack Carter07c818d2013-01-25 01:31:34 +00005778 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005779 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00005780 return false;
5781 }
5782
Jack Carter0cd3c192014-01-06 23:27:31 +00005783 if (IDVal == ".option")
5784 return parseDirectiveOption();
5785
5786 if (IDVal == ".abicalls") {
5787 getTargetStreamer().emitDirectiveAbiCalls();
5788 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005789 Error(Parser.getTok().getLoc(),
5790 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005791 // Clear line
5792 Parser.eatToEndOfStatement();
5793 }
5794 return false;
5795 }
5796
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005797 if (IDVal == ".cpsetup")
5798 return parseDirectiveCPSetup();
5799
Daniel Sandersf173dda2015-09-22 10:50:09 +00005800 if (IDVal == ".cpreturn")
5801 return parseDirectiveCPReturn();
5802
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005803 if (IDVal == ".module")
5804 return parseDirectiveModule();
5805
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005806 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
5807 return parseInternalDirectiveReallowModule();
5808
Toma Tabacu9ca50962015-04-16 09:53:47 +00005809 if (IDVal == ".insn")
5810 return parseInsnDirective();
5811
Rafael Espindola870c4e92012-01-11 03:56:41 +00005812 return true;
5813}
5814
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005815bool MipsAsmParser::parseInternalDirectiveReallowModule() {
5816 // If this is not the end of the statement, report an error.
5817 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5818 reportParseError("unexpected token, expected end of statement");
5819 return false;
5820 }
5821
5822 getTargetStreamer().reallowModuleDirective();
5823
5824 getParser().Lex(); // Eat EndOfStatement token.
5825 return false;
5826}
5827
Rafael Espindola870c4e92012-01-11 03:56:41 +00005828extern "C" void LLVMInitializeMipsAsmParser() {
5829 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
5830 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
5831 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
5832 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
5833}
Jack Carterb4dbc172012-09-05 23:34:03 +00005834
5835#define GET_REGISTER_MATCHER
5836#define GET_MATCHER_IMPLEMENTATION
5837#include "MipsGenAsmMatcher.inc"