blob: 5a3cf65a3c884e8e1616f7a81d01abeeac4fdd15 [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;
Jack Carter0b744b32012-10-04 02:29:46 +0000119
Daniel Sandersef638fe2014-10-03 15:37:37 +0000120 // Print a warning along with its fix-it message at the given range.
121 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
122 SMRange Range, bool ShowColors = true);
123
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000124#define GET_ASSEMBLER_HEADER
125#include "MipsGenAsmMatcher.inc"
126
Matheus Almeida595fcab2014-06-11 15:05:56 +0000127 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
128
Chad Rosier49963552012-10-13 00:26:04 +0000129 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000130 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000131 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000132 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000133
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000134 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000135 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000136
Toma Tabacu13964452014-09-04 13:23:44 +0000137 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000138
Toma Tabacu13964452014-09-04 13:23:44 +0000139 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000140
David Blaikie960ea3f2014-06-08 16:18:35 +0000141 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
142 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000143
Craig Topper56c590a2014-04-29 07:58:02 +0000144 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000145
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000146 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
147 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000148 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000149 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000150 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
151 SMLoc S);
152 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
153 OperandMatchResultTy parseImm(OperandVector &Operands);
154 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
155 OperandMatchResultTy parseInvNum(OperandVector &Operands);
156 OperandMatchResultTy parseLSAImm(OperandVector &Operands);
157 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
158 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
159 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000160
David Blaikie960ea3f2014-06-08 16:18:35 +0000161 bool searchSymbolAlias(OperandVector &Operands);
162
Toma Tabacu13964452014-09-04 13:23:44 +0000163 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000164
Jack Carter30a59822012-10-04 04:03:53 +0000165 bool needsExpansion(MCInst &Inst);
166
Matheus Almeida3813d572014-06-19 14:39:14 +0000167 // Expands assembly pseudo instructions.
168 // Returns false on success, true otherwise.
169 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000170 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000171
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000172 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
173 SmallVectorImpl<MCInst> &Instructions);
174
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000175 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000176 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000177 SmallVectorImpl<MCInst> &Instructions);
178
Toma Tabacuf712ede2015-06-17 14:31:51 +0000179 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
180 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
181 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacu674825c2015-06-16 12:16:24 +0000182
Toma Tabacu00e98672015-05-01 12:19:27 +0000183 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000184 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000185
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000186 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
187 const MCOperand &Offset, bool Is32BitAddress,
188 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000189
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000190 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
191 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000192
Jack Carter9e65aa32013-03-22 00:05:30 +0000193 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000194 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
195 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000196
197 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
198 SmallVectorImpl<MCInst> &Instructions);
199
Toma Tabacue1e460d2015-06-11 10:36:10 +0000200 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc,
201 SmallVectorImpl<MCInst> &Instructions);
202
Toma Tabacu1a108322015-06-17 13:20:24 +0000203 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc,
204 SmallVectorImpl<MCInst> &Instructions);
205
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000206 bool expandDiv(MCInst &Inst, SMLoc IDLoc,
207 SmallVectorImpl<MCInst> &Instructions, const bool IsMips64,
208 const bool Signed);
209
Toma Tabacud88d79c2015-06-23 14:39:42 +0000210 bool expandUlhu(MCInst &Inst, SMLoc IDLoc,
211 SmallVectorImpl<MCInst> &Instructions);
212
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000213 bool expandUlw(MCInst &Inst, SMLoc IDLoc,
214 SmallVectorImpl<MCInst> &Instructions);
215
Toma Tabacu234482a2015-03-16 12:03:39 +0000216 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
217 SmallVectorImpl<MCInst> &Instructions);
218
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000219 void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +0000220 bool Is64Bit, SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000221
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000222 bool reportParseError(Twine ErrorMsg);
223 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000224
Jack Carterb5cf5902013-04-17 00:18:04 +0000225 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000226 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000227
Vladimir Medic4c299852013-11-06 11:27:05 +0000228 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000229
230 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000231 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000232 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000233 bool parseSetFeature(uint64_t Feature);
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000234 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000235 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000236 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000237 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000238 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000239 bool parseInsnDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000240
241 bool parseSetAtDirective();
242 bool parseSetNoAtDirective();
243 bool parseSetMacroDirective();
244 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000245 bool parseSetMsaDirective();
246 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000247 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000248 bool parseSetReorderDirective();
249 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000250 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000251 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000252 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000253 bool parseSetOddSPRegDirective();
254 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000255 bool parseSetPopDirective();
256 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000257 bool parseSetSoftFloatDirective();
258 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000259
Jack Carterd76b2372013-03-21 21:44:16 +0000260 bool parseSetAssignment();
261
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000262 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000263 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000264 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000265 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000266 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000267 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
268 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000269
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000270 bool parseInternalDirectiveReallowModule();
271
Jack Carterdc1e35d2012-09-06 20:00:02 +0000272 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000273
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000274 bool eatComma(StringRef ErrorStr);
275
Jack Carter1ac53222013-02-20 23:11:17 +0000276 int matchCPURegisterName(StringRef Symbol);
277
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000278 int matchHWRegsRegisterName(StringRef Symbol);
279
Jack Carter873c7242013-01-12 01:03:14 +0000280 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000281
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000282 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000283
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000284 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000285
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000286 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000287
Jack Carter5dc8ac92013-09-25 23:50:44 +0000288 int matchMSA128RegisterName(StringRef Name);
289
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000290 int matchMSA128CtrlRegisterName(StringRef Name);
291
Jack Carterd0bd6422013-04-18 00:41:53 +0000292 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000293
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000294 unsigned getGPR(int RegNo);
295
Toma Tabacu89a712b2015-04-15 10:48:56 +0000296 /// Returns the internal register number for the current AT. Also checks if
297 /// the current AT is unavailable (set to $0) and gives an error if it is.
298 /// This should be used in pseudo-instruction expansions which need AT.
299 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000300
301 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000302 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000303
304 // Helper function that checks if the value of a vector index is within the
305 // boundaries of accepted values for each RegisterKind
306 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
307 bool validateMSAIndex(int Val, int RegKind);
308
Daniel Sandersf0df2212014-08-04 12:20:00 +0000309 // Selects a new architecture by updating the FeatureBits with the necessary
310 // info including implied dependencies.
311 // Internally, it clears all the feature bits related to *any* architecture
312 // and selects the new one using the ToggleFeature functionality of the
313 // MCSubtargetInfo object that handles implied dependencies. The reason we
314 // clear all the arch related bits manually is because ToggleFeature only
315 // clears the features that imply the feature being cleared and not the
316 // features implied by the feature being cleared. This is easier to see
317 // with an example:
318 // --------------------------------------------------
319 // | Feature | Implies |
320 // | -------------------------------------------------|
321 // | FeatureMips1 | None |
322 // | FeatureMips2 | FeatureMips1 |
323 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
324 // | FeatureMips4 | FeatureMips3 |
325 // | ... | |
326 // --------------------------------------------------
327 //
328 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
329 // FeatureMipsGP64 | FeatureMips1)
330 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
331 void selectArch(StringRef ArchFeature) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000332 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000333 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
334 STI.setFeatureBits(FeatureBits);
335 setAvailableFeatures(
336 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000337 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000338 }
339
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000340 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000341 if (!(STI.getFeatureBits()[Feature])) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000342 setAvailableFeatures(
343 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000344 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000345 }
346 }
347
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000348 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000349 if (STI.getFeatureBits()[Feature]) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000350 setAvailableFeatures(
351 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000352 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000353 }
354 }
355
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000356 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
357 setFeatureBits(Feature, FeatureString);
358 AssemblerOptions.front()->setFeatures(STI.getFeatureBits());
359 }
360
361 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
362 clearFeatureBits(Feature, FeatureString);
363 AssemblerOptions.front()->setFeatures(STI.getFeatureBits());
364 }
365
Rafael Espindola870c4e92012-01-11 03:56:41 +0000366public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000367 enum MipsMatchResultTy {
368 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
369#define GET_OPERAND_DIAGNOSTIC_TYPES
370#include "MipsGenAsmMatcher.inc"
371#undef GET_OPERAND_DIAGNOSTIC_TYPES
372
373 };
374
Joey Gouly0e76fa72013-09-12 10:28:05 +0000375 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000376 const MCInstrInfo &MII, const MCTargetOptions &Options)
Colin LeMahieufe2c8b82015-07-27 21:56:53 +0000377 : MCTargetAsmParser(Options), STI(sti),
Daniel Sanders153010c2015-09-15 14:08:28 +0000378 ABI(MipsABIInfo::computeTargetABI(sti.getTargetTuple(), sti.getCPU(),
379 Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000380 MCAsmParserExtension::Initialize(parser);
381
Toma Tabacu11e14a92015-04-21 11:50:52 +0000382 parser.addAliasForDirective(".asciiz", ".asciz");
383
Jack Carterb4dbc172012-09-05 23:34:03 +0000384 // Initialize the set of available features.
385 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000386
Toma Tabacu9db22db2014-09-09 10:15:38 +0000387 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000388 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000389 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000390
Toma Tabacu9db22db2014-09-09 10:15:38 +0000391 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000392 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000393 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000394
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000395 getTargetStreamer().updateABIInfo(*this);
396
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000397 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000398 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000399
400 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000401
Daniel Sandersa6994442015-08-18 12:33:54 +0000402 IsPicEnabled =
403 (getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_);
404
Daniel Sanders153010c2015-09-15 14:08:28 +0000405 const TargetTuple &TT = sti.getTargetTuple();
406 if ((TT.getArch() == TargetTuple::mips) ||
407 (TT.getArch() == TargetTuple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000408 IsLittleEndian = false;
409 else
410 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000411 }
412
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000413 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
414 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
415
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000416 bool isGP64bit() const { return STI.getFeatureBits()[Mips::FeatureGP64Bit]; }
417 bool isFP64bit() const { return STI.getFeatureBits()[Mips::FeatureFP64Bit]; }
Eric Christophera5762812015-01-26 17:33:46 +0000418 const MipsABIInfo &getABI() const { return ABI; }
419 bool isABI_N32() const { return ABI.IsN32(); }
420 bool isABI_N64() const { return ABI.IsN64(); }
421 bool isABI_O32() const { return ABI.IsO32(); }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000422 bool isABI_FPXX() const { return STI.getFeatureBits()[Mips::FeatureFPXX]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000423
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000424 bool useOddSPReg() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000425 return !(STI.getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000426 }
427
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000428 bool inMicroMipsMode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000429 return STI.getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000430 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000431 bool hasMips1() const { return STI.getFeatureBits()[Mips::FeatureMips1]; }
432 bool hasMips2() const { return STI.getFeatureBits()[Mips::FeatureMips2]; }
433 bool hasMips3() const { return STI.getFeatureBits()[Mips::FeatureMips3]; }
434 bool hasMips4() const { return STI.getFeatureBits()[Mips::FeatureMips4]; }
435 bool hasMips5() const { return STI.getFeatureBits()[Mips::FeatureMips5]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000436 bool hasMips32() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000437 return STI.getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000438 }
439 bool hasMips64() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000440 return STI.getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000441 }
442 bool hasMips32r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000443 return STI.getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000444 }
445 bool hasMips64r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000446 return STI.getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000447 }
Daniel Sanders17793142015-02-18 16:24:50 +0000448 bool hasMips32r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000449 return (STI.getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000450 }
451 bool hasMips64r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000452 return (STI.getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000453 }
454 bool hasMips32r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000455 return (STI.getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000456 }
457 bool hasMips64r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000458 return (STI.getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000459 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000460 bool hasMips32r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000461 return STI.getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000462 }
463 bool hasMips64r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000464 return STI.getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000465 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000466
467 bool hasDSP() const { return STI.getFeatureBits()[Mips::FeatureDSP]; }
468 bool hasDSPR2() const { return STI.getFeatureBits()[Mips::FeatureDSPR2]; }
469 bool hasMSA() const { return STI.getFeatureBits()[Mips::FeatureMSA]; }
Kai Nackee0245392015-01-27 19:11:28 +0000470 bool hasCnMips() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000471 return (STI.getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000472 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000473
Daniel Sandersa6994442015-08-18 12:33:54 +0000474 bool inPicMode() {
475 return IsPicEnabled;
476 }
477
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000478 bool inMips16Mode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000479 return STI.getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000480 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000481
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000482 bool useTraps() const {
483 return STI.getFeatureBits()[Mips::FeatureUseTCCInDIV];
484 }
485
Eric Christophere8ae3e32015-05-07 23:10:21 +0000486 bool useSoftFloat() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000487 return STI.getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000488 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000489
Toma Tabacud9d344b2015-04-27 14:05:04 +0000490 /// Warn if RegIndex is the same as the current AT.
491 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000492
493 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000494
495 bool isLittle() const { return IsLittleEndian; }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000496};
497}
498
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000499namespace {
500
501/// MipsOperand - Instances of this class represent a parsed Mips machine
502/// instruction.
503class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000504public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000505 /// Broad categories of register classes
506 /// The exact class is finalized by the render method.
507 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000508 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000509 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000510 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000511 RegKind_FCC = 4, /// FCC
512 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
513 RegKind_MSACtrl = 16, /// MSA control registers
514 RegKind_COP2 = 32, /// COP2
515 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
516 /// context).
517 RegKind_CCR = 128, /// CCR
518 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000519 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000520 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000521 /// Potentially any (e.g. $1)
522 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
523 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000524 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000525 };
526
527private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000528 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000529 k_Immediate, /// An immediate (possibly involving symbol references)
530 k_Memory, /// Base + Offset Memory Address
531 k_PhysRegister, /// A physical register from the Mips namespace
532 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000533 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000534 k_RegList, /// A physical register list
535 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000536 } Kind;
537
David Blaikie960ea3f2014-06-08 16:18:35 +0000538public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000539 MipsOperand(KindTy K, MipsAsmParser &Parser)
540 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
541
David Blaikie960ea3f2014-06-08 16:18:35 +0000542private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000543 /// For diagnostics, and checking the assembler temporary
544 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000545
Eric Christopher8996c5d2013-03-15 00:42:55 +0000546 struct Token {
547 const char *Data;
548 unsigned Length;
549 };
550
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000551 struct PhysRegOp {
552 unsigned Num; /// Register Number
553 };
554
555 struct RegIdxOp {
556 unsigned Index; /// Index into the register class
557 RegKind Kind; /// Bitfield of the kinds it could possibly be
558 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000559 };
560
561 struct ImmOp {
562 const MCExpr *Val;
563 };
564
565 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000566 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000567 const MCExpr *Off;
568 };
569
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000570 struct RegListOp {
571 SmallVector<unsigned, 10> *List;
572 };
573
Jack Carterb4dbc172012-09-05 23:34:03 +0000574 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000575 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000576 struct PhysRegOp PhysReg;
577 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000578 struct ImmOp Imm;
579 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000580 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000581 };
582
583 SMLoc StartLoc, EndLoc;
584
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000585 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000586 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
587 const MCRegisterInfo *RegInfo,
588 SMLoc S, SMLoc E,
589 MipsAsmParser &Parser) {
590 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000591 Op->RegIdx.Index = Index;
592 Op->RegIdx.RegInfo = RegInfo;
593 Op->RegIdx.Kind = RegKind;
594 Op->StartLoc = S;
595 Op->EndLoc = E;
596 return Op;
597 }
598
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000599public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000600 /// Coerce the register to GPR32 and return the real register for the current
601 /// target.
602 unsigned getGPR32Reg() const {
603 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000604 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000605 unsigned ClassID = Mips::GPR32RegClassID;
606 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000607 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000608
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000609 /// Coerce the register to GPR32 and return the real register for the current
610 /// target.
611 unsigned getGPRMM16Reg() const {
612 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
613 unsigned ClassID = Mips::GPR32RegClassID;
614 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
615 }
616
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000617 /// Coerce the register to GPR64 and return the real register for the current
618 /// target.
619 unsigned getGPR64Reg() const {
620 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
621 unsigned ClassID = Mips::GPR64RegClassID;
622 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000623 }
624
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000625private:
626 /// Coerce the register to AFGR64 and return the real register for the current
627 /// target.
628 unsigned getAFGR64Reg() const {
629 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
630 if (RegIdx.Index % 2 != 0)
631 AsmParser.Warning(StartLoc, "Float register should be even.");
632 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
633 .getRegister(RegIdx.Index / 2);
634 }
635
636 /// Coerce the register to FGR64 and return the real register for the current
637 /// target.
638 unsigned getFGR64Reg() const {
639 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
640 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
641 .getRegister(RegIdx.Index);
642 }
643
644 /// Coerce the register to FGR32 and return the real register for the current
645 /// target.
646 unsigned getFGR32Reg() const {
647 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
648 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
649 .getRegister(RegIdx.Index);
650 }
651
652 /// Coerce the register to FGRH32 and return the real register for the current
653 /// target.
654 unsigned getFGRH32Reg() const {
655 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
656 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
657 .getRegister(RegIdx.Index);
658 }
659
660 /// Coerce the register to FCC and return the real register for the current
661 /// target.
662 unsigned getFCCReg() const {
663 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
664 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
665 .getRegister(RegIdx.Index);
666 }
667
668 /// Coerce the register to MSA128 and return the real register for the current
669 /// target.
670 unsigned getMSA128Reg() const {
671 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
672 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
673 // identical
674 unsigned ClassID = Mips::MSA128BRegClassID;
675 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
676 }
677
678 /// Coerce the register to MSACtrl and return the real register for the
679 /// current target.
680 unsigned getMSACtrlReg() const {
681 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
682 unsigned ClassID = Mips::MSACtrlRegClassID;
683 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
684 }
685
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000686 /// Coerce the register to COP0 and return the real register for the
687 /// current target.
688 unsigned getCOP0Reg() const {
689 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
690 unsigned ClassID = Mips::COP0RegClassID;
691 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
692 }
693
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000694 /// Coerce the register to COP2 and return the real register for the
695 /// current target.
696 unsigned getCOP2Reg() const {
697 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
698 unsigned ClassID = Mips::COP2RegClassID;
699 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
700 }
701
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000702 /// Coerce the register to COP3 and return the real register for the
703 /// current target.
704 unsigned getCOP3Reg() const {
705 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
706 unsigned ClassID = Mips::COP3RegClassID;
707 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
708 }
709
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000710 /// Coerce the register to ACC64DSP and return the real register for the
711 /// current target.
712 unsigned getACC64DSPReg() const {
713 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
714 unsigned ClassID = Mips::ACC64DSPRegClassID;
715 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
716 }
717
718 /// Coerce the register to HI32DSP and return the real register for the
719 /// current target.
720 unsigned getHI32DSPReg() const {
721 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
722 unsigned ClassID = Mips::HI32DSPRegClassID;
723 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
724 }
725
726 /// Coerce the register to LO32DSP and return the real register for the
727 /// current target.
728 unsigned getLO32DSPReg() const {
729 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
730 unsigned ClassID = Mips::LO32DSPRegClassID;
731 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
732 }
733
734 /// Coerce the register to CCR and return the real register for the
735 /// current target.
736 unsigned getCCRReg() const {
737 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
738 unsigned ClassID = Mips::CCRRegClassID;
739 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
740 }
741
742 /// Coerce the register to HWRegs and return the real register for the
743 /// current target.
744 unsigned getHWRegsReg() const {
745 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
746 unsigned ClassID = Mips::HWRegsRegClassID;
747 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
748 }
749
750public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000751 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000752 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000753 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000754 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000755 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000756 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000757 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000758 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000759 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000760
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000761 void addRegOperands(MCInst &Inst, unsigned N) const {
762 llvm_unreachable("Use a custom parser instead");
763 }
764
Daniel Sanders21bce302014-04-01 12:35:23 +0000765 /// Render the operand to an MCInst as a GPR32
766 /// Asserts if the wrong number of operands are requested, or the operand
767 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000768 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
769 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000770 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000771 }
772
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000773 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
774 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000775 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000776 }
777
Jozef Kolek1904fa22014-11-24 14:25:53 +0000778 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
779 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000780 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000781 }
782
Zoran Jovanovic41688672015-02-10 16:36:20 +0000783 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
784 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000785 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000786 }
787
Daniel Sanders21bce302014-04-01 12:35:23 +0000788 /// Render the operand to an MCInst as a GPR64
789 /// Asserts if the wrong number of operands are requested, or the operand
790 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000791 void addGPR64AsmRegOperands(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(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000794 }
795
796 void addAFGR64AsmRegOperands(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(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000799 }
800
801 void addFGR64AsmRegOperands(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(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000804 }
805
806 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
807 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000808 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000809 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000810 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000811 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
812 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000813 }
814
815 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
816 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000817 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000818 }
819
820 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
821 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000822 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000823 }
824
825 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
826 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000827 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000828 }
829
830 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
831 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000832 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000833 }
834
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000835 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
836 assert(N == 1 && "Invalid number of operands!");
837 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
838 }
839
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000840 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
841 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000842 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000843 }
844
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000845 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
846 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000847 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000848 }
849
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000850 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
851 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000852 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000853 }
854
855 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
856 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000857 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000858 }
859
860 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
861 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000862 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000863 }
864
865 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
866 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000867 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000868 }
869
870 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
871 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000872 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000873 }
874
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000875 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000876 assert(N == 1 && "Invalid number of operands!");
877 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000878 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000879 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000880
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000881 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000882 assert(N == 2 && "Invalid number of operands!");
883
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000884 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
885 ? getMemBase()->getGPR64Reg()
886 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000887
888 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000889 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000890 }
891
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000892 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
893 assert(N == 2 && "Invalid number of operands!");
894
Jim Grosbache9119e42015-05-13 18:37:00 +0000895 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000896
897 const MCExpr *Expr = getMemOff();
898 addExpr(Inst, Expr);
899 }
900
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000901 void addRegListOperands(MCInst &Inst, unsigned N) const {
902 assert(N == 1 && "Invalid number of operands!");
903
904 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000905 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000906 }
907
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000908 void addRegPairOperands(MCInst &Inst, unsigned N) const {
909 assert(N == 2 && "Invalid number of operands!");
910 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +0000911 Inst.addOperand(MCOperand::createReg(RegNo++));
912 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000913 }
914
Zoran Jovanovic41688672015-02-10 16:36:20 +0000915 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
916 assert(N == 2 && "Invalid number of operands!");
917 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000918 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000919 }
920
Craig Topper56c590a2014-04-29 07:58:02 +0000921 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000922 // As a special case until we sort out the definition of div/divu, pretend
923 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
924 if (isGPRAsmReg() && RegIdx.Index == 0)
925 return true;
926
927 return Kind == k_PhysRegister;
928 }
929 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000930 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000931 bool isConstantImm() const {
932 return isImm() && dyn_cast<MCConstantExpr>(getImm());
933 }
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +0000934 template <unsigned Bits> bool isUImm() const {
935 return isImm() && isConstantImm() && isUInt<Bits>(getConstantImm());
936 }
Craig Topper56c590a2014-04-29 07:58:02 +0000937 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000938 // Note: It's not possible to pretend that other operand kinds are tokens.
939 // The matcher emitter checks tokens first.
940 return Kind == k_Token;
941 }
Craig Topper56c590a2014-04-29 07:58:02 +0000942 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000943 bool isConstantMemOff() const {
944 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
945 }
946 template <unsigned Bits> bool isMemWithSimmOffset() const {
Zoran Jovanovica6593ff2015-08-18 12:53:08 +0000947 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
948 && getMemBase()->isGPRAsmReg();
949 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000950 bool isMemWithGRPMM16Base() const {
951 return isMem() && getMemBase()->isMM16AsmReg();
952 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000953 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
954 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
955 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
956 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000957 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
958 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
959 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
960 && (getMemBase()->getGPR32Reg() == Mips::SP);
961 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000962 bool isRegList16() const {
963 if (!isRegList())
964 return false;
965
966 int Size = RegList.List->size();
967 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
968 RegList.List->back() != Mips::RA)
969 return false;
970
971 int PrevReg = *RegList.List->begin();
972 for (int i = 1; i < Size - 1; i++) {
973 int Reg = (*(RegList.List))[i];
974 if ( Reg != PrevReg + 1)
975 return false;
976 PrevReg = Reg;
977 }
978
979 return true;
980 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000981 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000982 bool isLSAImm() const {
983 if (!isConstantImm())
984 return false;
985 int64_t Val = getConstantImm();
986 return 1 <= Val && Val <= 4;
987 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000988 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +0000989 bool isMovePRegPair() const {
990 if (Kind != k_RegList || RegList.List->size() != 2)
991 return false;
992
993 unsigned R0 = RegList.List->front();
994 unsigned R1 = RegList.List->back();
995
996 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
997 (R0 == Mips::A1 && R1 == Mips::A3) ||
998 (R0 == Mips::A2 && R1 == Mips::A3) ||
999 (R0 == Mips::A0 && R1 == Mips::S5) ||
1000 (R0 == Mips::A0 && R1 == Mips::S6) ||
1001 (R0 == Mips::A0 && R1 == Mips::A1) ||
1002 (R0 == Mips::A0 && R1 == Mips::A2) ||
1003 (R0 == Mips::A0 && R1 == Mips::A3))
1004 return true;
1005
1006 return false;
1007 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001008
1009 StringRef getToken() const {
1010 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001011 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001012 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001013 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001014
Craig Topper56c590a2014-04-29 07:58:02 +00001015 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001016 // As a special case until we sort out the definition of div/divu, pretend
1017 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1018 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1019 RegIdx.Kind & RegKind_GPR)
1020 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001021
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001022 assert(Kind == k_PhysRegister && "Invalid access!");
1023 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001024 }
1025
Jack Carterb4dbc172012-09-05 23:34:03 +00001026 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001027 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001028 return Imm.Val;
1029 }
1030
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001031 int64_t getConstantImm() const {
1032 const MCExpr *Val = getImm();
1033 return static_cast<const MCConstantExpr *>(Val)->getValue();
1034 }
1035
1036 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001037 assert((Kind == k_Memory) && "Invalid access!");
1038 return Mem.Base;
1039 }
1040
1041 const MCExpr *getMemOff() const {
1042 assert((Kind == k_Memory) && "Invalid access!");
1043 return Mem.Off;
1044 }
1045
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001046 int64_t getConstantMemOff() const {
1047 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1048 }
1049
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001050 const SmallVectorImpl<unsigned> &getRegList() const {
1051 assert((Kind == k_RegList) && "Invalid access!");
1052 return *(RegList.List);
1053 }
1054
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001055 unsigned getRegPair() const {
1056 assert((Kind == k_RegPair) && "Invalid access!");
1057 return RegIdx.Index;
1058 }
1059
David Blaikie960ea3f2014-06-08 16:18:35 +00001060 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1061 MipsAsmParser &Parser) {
1062 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001063 Op->Tok.Data = Str.data();
1064 Op->Tok.Length = Str.size();
1065 Op->StartLoc = S;
1066 Op->EndLoc = S;
1067 return Op;
1068 }
1069
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001070 /// Create a numeric register (e.g. $1). The exact register remains
1071 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001072 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001073 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001074 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001075 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001076 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001077 }
1078
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001079 /// Create a register that is definitely a GPR.
1080 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001081 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001082 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001083 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001084 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001085 }
1086
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001087 /// Create a register that is definitely a FGR.
1088 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001089 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001090 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001091 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001092 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1093 }
1094
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001095 /// Create a register that is definitely a HWReg.
1096 /// This is typically only used for named registers such as $hwr_cpunum.
1097 static std::unique_ptr<MipsOperand>
1098 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1099 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1100 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1101 }
1102
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001103 /// Create a register that is definitely an FCC.
1104 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001105 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001106 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001107 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001108 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1109 }
1110
1111 /// Create a register that is definitely an ACC.
1112 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001113 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001114 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001115 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001116 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1117 }
1118
1119 /// Create a register that is definitely an MSA128.
1120 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001121 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001122 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001123 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001124 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1125 }
1126
1127 /// Create a register that is definitely an MSACtrl.
1128 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001129 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001130 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001131 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001132 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1133 }
1134
David Blaikie960ea3f2014-06-08 16:18:35 +00001135 static std::unique_ptr<MipsOperand>
1136 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1137 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001138 Op->Imm.Val = Val;
1139 Op->StartLoc = S;
1140 Op->EndLoc = E;
1141 return Op;
1142 }
1143
David Blaikie960ea3f2014-06-08 16:18:35 +00001144 static std::unique_ptr<MipsOperand>
1145 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1146 SMLoc E, MipsAsmParser &Parser) {
1147 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1148 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001149 Op->Mem.Off = Off;
1150 Op->StartLoc = S;
1151 Op->EndLoc = E;
1152 return Op;
1153 }
1154
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001155 static std::unique_ptr<MipsOperand>
1156 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1157 MipsAsmParser &Parser) {
1158 assert (Regs.size() > 0 && "Empty list not allowed");
1159
1160 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001161 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001162 Op->StartLoc = StartLoc;
1163 Op->EndLoc = EndLoc;
1164 return Op;
1165 }
1166
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001167 static std::unique_ptr<MipsOperand>
1168 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1169 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1170 Op->RegIdx.Index = RegNo;
1171 Op->StartLoc = S;
1172 Op->EndLoc = E;
1173 return Op;
1174 }
1175
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001176 bool isGPRAsmReg() const {
1177 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001178 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001179 bool isMM16AsmReg() const {
1180 if (!(isRegIdx() && RegIdx.Kind))
1181 return false;
1182 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1183 || RegIdx.Index == 16 || RegIdx.Index == 17);
1184 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001185 bool isMM16AsmRegZero() const {
1186 if (!(isRegIdx() && RegIdx.Kind))
1187 return false;
1188 return (RegIdx.Index == 0 ||
1189 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1190 RegIdx.Index == 17);
1191 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001192 bool isMM16AsmRegMoveP() const {
1193 if (!(isRegIdx() && RegIdx.Kind))
1194 return false;
1195 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1196 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1197 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001198 bool isFGRAsmReg() const {
1199 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1200 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001201 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001202 bool isHWRegsAsmReg() const {
1203 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001204 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001205 bool isCCRAsmReg() const {
1206 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001207 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001208 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001209 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1210 return false;
1211 if (!AsmParser.hasEightFccRegisters())
1212 return RegIdx.Index == 0;
1213 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001214 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001215 bool isACCAsmReg() const {
1216 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001217 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001218 bool isCOP0AsmReg() const {
1219 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1220 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001221 bool isCOP2AsmReg() const {
1222 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001223 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001224 bool isCOP3AsmReg() const {
1225 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1226 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001227 bool isMSA128AsmReg() const {
1228 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001229 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001230 bool isMSACtrlAsmReg() const {
1231 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001232 }
1233
Jack Carterb4dbc172012-09-05 23:34:03 +00001234 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001235 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001236 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001237 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001238
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001239 virtual ~MipsOperand() {
1240 switch (Kind) {
1241 case k_Immediate:
1242 break;
1243 case k_Memory:
1244 delete Mem.Base;
1245 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001246 case k_RegList:
1247 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001248 case k_PhysRegister:
1249 case k_RegisterIndex:
1250 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001251 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001252 break;
1253 }
1254 }
1255
Craig Topper56c590a2014-04-29 07:58:02 +00001256 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001257 switch (Kind) {
1258 case k_Immediate:
1259 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001260 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001261 OS << ">";
1262 break;
1263 case k_Memory:
1264 OS << "Mem<";
1265 Mem.Base->print(OS);
1266 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001267 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001268 OS << ">";
1269 break;
1270 case k_PhysRegister:
1271 OS << "PhysReg<" << PhysReg.Num << ">";
1272 break;
1273 case k_RegisterIndex:
1274 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1275 break;
1276 case k_Token:
1277 OS << Tok.Data;
1278 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001279 case k_RegList:
1280 OS << "RegList< ";
1281 for (auto Reg : (*RegList.List))
1282 OS << Reg << " ";
1283 OS << ">";
1284 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001285 case k_RegPair:
1286 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1287 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001288 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001289 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001290}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001291} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001292
Jack Carter9e65aa32013-03-22 00:05:30 +00001293namespace llvm {
1294extern const MCInstrDesc MipsInsts[];
1295}
1296static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1297 return MipsInsts[Opcode];
1298}
1299
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001300static bool hasShortDelaySlot(unsigned Opcode) {
1301 switch (Opcode) {
1302 case Mips::JALS_MM:
1303 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001304 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001305 case Mips::BGEZALS_MM:
1306 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001307 return true;
1308 default:
1309 return false;
1310 }
1311}
1312
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001313static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1314 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1315 return &SRExpr->getSymbol();
1316 }
1317
1318 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1319 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1320 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1321
1322 if (LHSSym)
1323 return LHSSym;
1324
1325 if (RHSSym)
1326 return RHSSym;
1327
1328 return nullptr;
1329 }
1330
1331 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1332 return getSingleMCSymbol(UExpr->getSubExpr());
1333
1334 return nullptr;
1335}
1336
1337static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1338 if (isa<MCSymbolRefExpr>(Expr))
1339 return 1;
1340
1341 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1342 return countMCSymbolRefExpr(BExpr->getLHS()) +
1343 countMCSymbolRefExpr(BExpr->getRHS());
1344
1345 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1346 return countMCSymbolRefExpr(UExpr->getSubExpr());
1347
1348 return 0;
1349}
1350
Jack Carter9e65aa32013-03-22 00:05:30 +00001351bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001352 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001353 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001354
Jack Carter9e65aa32013-03-22 00:05:30 +00001355 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001356
1357 if (MCID.isBranch() || MCID.isCall()) {
1358 const unsigned Opcode = Inst.getOpcode();
1359 MCOperand Offset;
1360
1361 switch (Opcode) {
1362 default:
1363 break;
Kai Nackee0245392015-01-27 19:11:28 +00001364 case Mips::BBIT0:
1365 case Mips::BBIT032:
1366 case Mips::BBIT1:
1367 case Mips::BBIT132:
1368 assert(hasCnMips() && "instruction only valid for octeon cpus");
1369 // Fall through
1370
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001371 case Mips::BEQ:
1372 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001373 case Mips::BEQ_MM:
1374 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001375 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001376 Offset = Inst.getOperand(2);
1377 if (!Offset.isImm())
1378 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001379 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001380 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001381 if (OffsetToAlignment(Offset.getImm(),
1382 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001383 return Error(IDLoc, "branch to misaligned address");
1384 break;
1385 case Mips::BGEZ:
1386 case Mips::BGTZ:
1387 case Mips::BLEZ:
1388 case Mips::BLTZ:
1389 case Mips::BGEZAL:
1390 case Mips::BLTZAL:
1391 case Mips::BC1F:
1392 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001393 case Mips::BGEZ_MM:
1394 case Mips::BGTZ_MM:
1395 case Mips::BLEZ_MM:
1396 case Mips::BLTZ_MM:
1397 case Mips::BGEZAL_MM:
1398 case Mips::BLTZAL_MM:
1399 case Mips::BC1F_MM:
1400 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001401 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001402 Offset = Inst.getOperand(1);
1403 if (!Offset.isImm())
1404 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001405 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001406 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001407 if (OffsetToAlignment(Offset.getImm(),
1408 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001409 return Error(IDLoc, "branch to misaligned address");
1410 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001411 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001412 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001413 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001414 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001415 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1416 Offset = Inst.getOperand(1);
1417 if (!Offset.isImm())
1418 break; // We'll deal with this situation later on when applying fixups.
1419 if (!isIntN(8, Offset.getImm()))
1420 return Error(IDLoc, "branch target out of range");
1421 if (OffsetToAlignment(Offset.getImm(), 2LL))
1422 return Error(IDLoc, "branch to misaligned address");
1423 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001424 }
1425 }
1426
Daniel Sandersa84989a2014-06-16 13:25:35 +00001427 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1428 // We still accept it but it is a normal nop.
1429 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1430 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1431 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1432 "nop instruction");
1433 }
1434
Kai Nackee0245392015-01-27 19:11:28 +00001435 if (hasCnMips()) {
1436 const unsigned Opcode = Inst.getOpcode();
1437 MCOperand Opnd;
1438 int Imm;
1439
1440 switch (Opcode) {
1441 default:
1442 break;
1443
1444 case Mips::BBIT0:
1445 case Mips::BBIT032:
1446 case Mips::BBIT1:
1447 case Mips::BBIT132:
1448 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1449 // The offset is handled above
1450 Opnd = Inst.getOperand(1);
1451 if (!Opnd.isImm())
1452 return Error(IDLoc, "expected immediate operand kind");
1453 Imm = Opnd.getImm();
1454 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1455 Opcode == Mips::BBIT1 ? 63 : 31))
1456 return Error(IDLoc, "immediate operand value out of range");
1457 if (Imm > 31) {
1458 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1459 : Mips::BBIT132);
1460 Inst.getOperand(1).setImm(Imm - 32);
1461 }
1462 break;
1463
1464 case Mips::CINS:
1465 case Mips::CINS32:
1466 case Mips::EXTS:
1467 case Mips::EXTS32:
1468 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1469 // Check length
1470 Opnd = Inst.getOperand(3);
1471 if (!Opnd.isImm())
1472 return Error(IDLoc, "expected immediate operand kind");
1473 Imm = Opnd.getImm();
1474 if (Imm < 0 || Imm > 31)
1475 return Error(IDLoc, "immediate operand value out of range");
1476 // Check position
1477 Opnd = Inst.getOperand(2);
1478 if (!Opnd.isImm())
1479 return Error(IDLoc, "expected immediate operand kind");
1480 Imm = Opnd.getImm();
1481 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1482 Opcode == Mips::EXTS ? 63 : 31))
1483 return Error(IDLoc, "immediate operand value out of range");
1484 if (Imm > 31) {
1485 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1486 Inst.getOperand(2).setImm(Imm - 32);
1487 }
1488 break;
1489
1490 case Mips::SEQi:
1491 case Mips::SNEi:
1492 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1493 Opnd = Inst.getOperand(2);
1494 if (!Opnd.isImm())
1495 return Error(IDLoc, "expected immediate operand kind");
1496 Imm = Opnd.getImm();
1497 if (!isInt<10>(Imm))
1498 return Error(IDLoc, "immediate operand value out of range");
1499 break;
1500 }
1501 }
1502
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001503 // This expansion is not in a function called by expandInstruction() because
1504 // the pseudo-instruction doesn't have a distinct opcode.
1505 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1506 inPicMode()) {
1507 warnIfNoMacro(IDLoc);
1508
1509 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1510
1511 // We can do this expansion if there's only 1 symbol in the argument
1512 // expression.
1513 if (countMCSymbolRefExpr(JalExpr) > 1)
1514 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1515
1516 // FIXME: This is checking the expression can be handled by the later stages
1517 // of the assembler. We ought to leave it to those later stages but
1518 // we can't do that until we stop evaluateRelocExpr() rewriting the
1519 // expressions into non-equivalent forms.
1520 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1521
1522 // FIXME: Add support for label+offset operands (currently causes an error).
1523 // FIXME: Add support for forward-declared local symbols.
1524 // FIXME: Add expansion for when the LargeGOT option is enabled.
1525 if (JalSym->isInSection() || JalSym->isTemporary()) {
1526 if (isABI_O32()) {
1527 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001528 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001529 // R_(MICRO)MIPS_GOT16 label
1530 // addiu $25, $25, 0
1531 // R_(MICRO)MIPS_LO16 label
1532 // jalr $25
1533 const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
1534 const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
1535
1536 MCInst LwInst;
1537 LwInst.setOpcode(Mips::LW);
1538 LwInst.addOperand(MCOperand::createReg(Mips::T9));
1539 LwInst.addOperand(MCOperand::createReg(Mips::GP));
1540 LwInst.addOperand(MCOperand::createExpr(Got16RelocExpr));
1541 Instructions.push_back(LwInst);
1542
1543 MCInst AddiuInst;
1544 AddiuInst.setOpcode(Mips::ADDiu);
1545 AddiuInst.addOperand(MCOperand::createReg(Mips::T9));
1546 AddiuInst.addOperand(MCOperand::createReg(Mips::T9));
1547 AddiuInst.addOperand(MCOperand::createExpr(Lo16RelocExpr));
1548 Instructions.push_back(AddiuInst);
1549 } else if (isABI_N32() || isABI_N64()) {
1550 // If it's a local symbol and the N32/N64 ABIs are being used,
1551 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001552 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001553 // R_(MICRO)MIPS_GOT_DISP label
1554 // jalr $25
1555 const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
1556
1557 MCInst LoadInst;
1558 LoadInst.setOpcode(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW);
1559 LoadInst.addOperand(MCOperand::createReg(Mips::T9));
1560 LoadInst.addOperand(MCOperand::createReg(Mips::GP));
1561 LoadInst.addOperand(MCOperand::createExpr(GotDispRelocExpr));
1562 Instructions.push_back(LoadInst);
1563 }
1564 } else {
1565 // If it's an external/weak symbol, we expand to:
1566 // lw/ld $25, 0($gp)
1567 // R_(MICRO)MIPS_CALL16 label
1568 // jalr $25
1569 const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
1570
1571 MCInst LoadInst;
1572 LoadInst.setOpcode(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW);
1573 LoadInst.addOperand(MCOperand::createReg(Mips::T9));
1574 LoadInst.addOperand(MCOperand::createReg(Mips::GP));
1575 LoadInst.addOperand(MCOperand::createExpr(Call16RelocExpr));
1576 Instructions.push_back(LoadInst);
1577 }
1578
1579 MCInst JalrInst;
1580 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
1581 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1582 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1583
1584 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1585 // This relocation is supposed to be an optimization hint for the linker
1586 // and is not necessary for correctness.
1587
1588 Inst = JalrInst;
1589 }
1590
Jack Carter9e65aa32013-03-22 00:05:30 +00001591 if (MCID.mayLoad() || MCID.mayStore()) {
1592 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001593 // reference or immediate we may have to expand instructions.
1594 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001595 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001596 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1597 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001598 MCOperand &Op = Inst.getOperand(i);
1599 if (Op.isImm()) {
1600 int MemOffset = Op.getImm();
1601 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001602 // Offset can't exceed 16bit value.
1603 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001604 return false;
1605 }
1606 } else if (Op.isExpr()) {
1607 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001608 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001609 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001610 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001611 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001612 // Expand symbol.
1613 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001614 return false;
1615 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001616 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001617 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001618 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001619 }
1620 }
1621 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001622 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001623 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001624
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001625 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001626 if (MCID.mayLoad()) {
1627 // Try to create 16-bit GP relative load instruction.
1628 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1629 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1630 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1631 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1632 MCOperand &Op = Inst.getOperand(i);
1633 if (Op.isImm()) {
1634 int MemOffset = Op.getImm();
1635 MCOperand &DstReg = Inst.getOperand(0);
1636 MCOperand &BaseReg = Inst.getOperand(1);
1637 if (isIntN(9, MemOffset) && (MemOffset % 4 == 0) &&
1638 getContext().getRegisterInfo()->getRegClass(
1639 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001640 (BaseReg.getReg() == Mips::GP ||
1641 BaseReg.getReg() == Mips::GP_64)) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001642 MCInst TmpInst;
1643 TmpInst.setLoc(IDLoc);
1644 TmpInst.setOpcode(Mips::LWGP_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00001645 TmpInst.addOperand(MCOperand::createReg(DstReg.getReg()));
1646 TmpInst.addOperand(MCOperand::createReg(Mips::GP));
1647 TmpInst.addOperand(MCOperand::createImm(MemOffset));
Jozef Koleke10a02e2015-01-28 17:27:26 +00001648 Instructions.push_back(TmpInst);
1649 return false;
1650 }
1651 }
1652 }
1653 } // for
1654 } // if load
1655
1656 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1657
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001658 MCOperand Opnd;
1659 int Imm;
1660
1661 switch (Inst.getOpcode()) {
1662 default:
1663 break;
1664 case Mips::ADDIUS5_MM:
1665 Opnd = Inst.getOperand(2);
1666 if (!Opnd.isImm())
1667 return Error(IDLoc, "expected immediate operand kind");
1668 Imm = Opnd.getImm();
1669 if (Imm < -8 || Imm > 7)
1670 return Error(IDLoc, "immediate operand value out of range");
1671 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001672 case Mips::ADDIUSP_MM:
1673 Opnd = Inst.getOperand(0);
1674 if (!Opnd.isImm())
1675 return Error(IDLoc, "expected immediate operand kind");
1676 Imm = Opnd.getImm();
1677 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1678 Imm % 4 != 0)
1679 return Error(IDLoc, "immediate operand value out of range");
1680 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001681 case Mips::SLL16_MM:
1682 case Mips::SRL16_MM:
1683 Opnd = Inst.getOperand(2);
1684 if (!Opnd.isImm())
1685 return Error(IDLoc, "expected immediate operand kind");
1686 Imm = Opnd.getImm();
1687 if (Imm < 1 || Imm > 8)
1688 return Error(IDLoc, "immediate operand value out of range");
1689 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001690 case Mips::LI16_MM:
1691 Opnd = Inst.getOperand(1);
1692 if (!Opnd.isImm())
1693 return Error(IDLoc, "expected immediate operand kind");
1694 Imm = Opnd.getImm();
1695 if (Imm < -1 || Imm > 126)
1696 return Error(IDLoc, "immediate operand value out of range");
1697 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001698 case Mips::ADDIUR2_MM:
1699 Opnd = Inst.getOperand(2);
1700 if (!Opnd.isImm())
1701 return Error(IDLoc, "expected immediate operand kind");
1702 Imm = Opnd.getImm();
1703 if (!(Imm == 1 || Imm == -1 ||
1704 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1705 return Error(IDLoc, "immediate operand value out of range");
1706 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001707 case Mips::ADDIUR1SP_MM:
1708 Opnd = Inst.getOperand(1);
1709 if (!Opnd.isImm())
1710 return Error(IDLoc, "expected immediate operand kind");
1711 Imm = Opnd.getImm();
1712 if (OffsetToAlignment(Imm, 4LL))
1713 return Error(IDLoc, "misaligned immediate operand value");
1714 if (Imm < 0 || Imm > 255)
1715 return Error(IDLoc, "immediate operand value out of range");
1716 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001717 case Mips::ANDI16_MM:
1718 Opnd = Inst.getOperand(2);
1719 if (!Opnd.isImm())
1720 return Error(IDLoc, "expected immediate operand kind");
1721 Imm = Opnd.getImm();
1722 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1723 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1724 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1725 return Error(IDLoc, "immediate operand value out of range");
1726 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001727 case Mips::LBU16_MM:
1728 Opnd = Inst.getOperand(2);
1729 if (!Opnd.isImm())
1730 return Error(IDLoc, "expected immediate operand kind");
1731 Imm = Opnd.getImm();
1732 if (Imm < -1 || Imm > 14)
1733 return Error(IDLoc, "immediate operand value out of range");
1734 break;
1735 case Mips::SB16_MM:
1736 Opnd = Inst.getOperand(2);
1737 if (!Opnd.isImm())
1738 return Error(IDLoc, "expected immediate operand kind");
1739 Imm = Opnd.getImm();
1740 if (Imm < 0 || Imm > 15)
1741 return Error(IDLoc, "immediate operand value out of range");
1742 break;
1743 case Mips::LHU16_MM:
1744 case Mips::SH16_MM:
1745 Opnd = Inst.getOperand(2);
1746 if (!Opnd.isImm())
1747 return Error(IDLoc, "expected immediate operand kind");
1748 Imm = Opnd.getImm();
1749 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1750 return Error(IDLoc, "immediate operand value out of range");
1751 break;
1752 case Mips::LW16_MM:
1753 case Mips::SW16_MM:
1754 Opnd = Inst.getOperand(2);
1755 if (!Opnd.isImm())
1756 return Error(IDLoc, "expected immediate operand kind");
1757 Imm = Opnd.getImm();
1758 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1759 return Error(IDLoc, "immediate operand value out of range");
1760 break;
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001761 case Mips::CACHE:
1762 case Mips::PREF:
1763 Opnd = Inst.getOperand(2);
1764 if (!Opnd.isImm())
1765 return Error(IDLoc, "expected immediate operand kind");
1766 Imm = Opnd.getImm();
1767 if (!isUInt<5>(Imm))
1768 return Error(IDLoc, "immediate operand value out of range");
1769 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001770 case Mips::ADDIUPC_MM:
1771 MCOperand Opnd = Inst.getOperand(1);
1772 if (!Opnd.isImm())
1773 return Error(IDLoc, "expected immediate operand kind");
1774 int Imm = Opnd.getImm();
1775 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1776 return Error(IDLoc, "immediate operand value out of range");
1777 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001778 }
1779 }
1780
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001781 if (needsExpansion(Inst)) {
1782 if (expandInstruction(Inst, IDLoc, Instructions))
1783 return true;
1784 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001785 Instructions.push_back(Inst);
1786
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001787 // If this instruction has a delay slot and .set reorder is active,
1788 // emit a NOP after it.
1789 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1790 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1791
Jack Carter9e65aa32013-03-22 00:05:30 +00001792 return false;
1793}
1794
Jack Carter30a59822012-10-04 04:03:53 +00001795bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1796
Jack Carterd0bd6422013-04-18 00:41:53 +00001797 switch (Inst.getOpcode()) {
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001798 case Mips::LoadImm32:
1799 case Mips::LoadImm64:
1800 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001801 case Mips::LoadAddrImm64:
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001802 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001803 case Mips::LoadAddrReg64:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001804 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001805 case Mips::B_MMR6_Pseudo:
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001806 case Mips::LWM_MM:
1807 case Mips::SWM_MM:
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001808 case Mips::JalOneReg:
1809 case Mips::JalTwoReg:
Toma Tabacue1e460d2015-06-11 10:36:10 +00001810 case Mips::BneImm:
1811 case Mips::BeqImm:
Toma Tabacu1a108322015-06-17 13:20:24 +00001812 case Mips::BLT:
1813 case Mips::BLE:
1814 case Mips::BGE:
1815 case Mips::BGT:
1816 case Mips::BLTU:
1817 case Mips::BLEU:
1818 case Mips::BGEU:
1819 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00001820 case Mips::BLTL:
1821 case Mips::BLEL:
1822 case Mips::BGEL:
1823 case Mips::BGTL:
1824 case Mips::BLTUL:
1825 case Mips::BLEUL:
1826 case Mips::BGEUL:
1827 case Mips::BGTUL:
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00001828 case Mips::SDivMacro:
1829 case Mips::UDivMacro:
1830 case Mips::DSDivMacro:
1831 case Mips::DUDivMacro:
Toma Tabacud88d79c2015-06-23 14:39:42 +00001832 case Mips::Ulhu:
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00001833 case Mips::Ulw:
Jack Carterd0bd6422013-04-18 00:41:53 +00001834 return true;
1835 default:
1836 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001837 }
1838}
Jack Carter92995f12012-10-06 00:53:28 +00001839
Matheus Almeida3813d572014-06-19 14:39:14 +00001840bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001841 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001842 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001843 default: llvm_unreachable("unimplemented expansion");
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001844 case Mips::LoadImm32:
Toma Tabacu00e98672015-05-01 12:19:27 +00001845 return expandLoadImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001846 case Mips::LoadImm64:
Toma Tabacu00e98672015-05-01 12:19:27 +00001847 return expandLoadImm(Inst, false, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001848 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001849 case Mips::LoadAddrImm64:
1850 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1851 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1852 "expected immediate operand kind");
1853
1854 return expandLoadAddress(
1855 Inst.getOperand(0).getReg(), Mips::NoRegister, Inst.getOperand(1),
1856 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001857 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001858 case Mips::LoadAddrReg64:
1859 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1860 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1861 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
1862 "expected immediate operand kind");
1863
1864 return expandLoadAddress(
1865 Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(), Inst.getOperand(2),
1866 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001867 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001868 case Mips::B_MMR6_Pseudo:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001869 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001870 case Mips::SWM_MM:
1871 case Mips::LWM_MM:
1872 return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001873 case Mips::JalOneReg:
1874 case Mips::JalTwoReg:
1875 return expandJalWithRegs(Inst, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00001876 case Mips::BneImm:
1877 case Mips::BeqImm:
1878 return expandBranchImm(Inst, IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00001879 case Mips::BLT:
1880 case Mips::BLE:
1881 case Mips::BGE:
1882 case Mips::BGT:
1883 case Mips::BLTU:
1884 case Mips::BLEU:
1885 case Mips::BGEU:
1886 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00001887 case Mips::BLTL:
1888 case Mips::BLEL:
1889 case Mips::BGEL:
1890 case Mips::BGTL:
1891 case Mips::BLTUL:
1892 case Mips::BLEUL:
1893 case Mips::BGEUL:
1894 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00001895 return expandCondBranches(Inst, IDLoc, Instructions);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00001896 case Mips::SDivMacro:
1897 return expandDiv(Inst, IDLoc, Instructions, false, true);
1898 case Mips::DSDivMacro:
1899 return expandDiv(Inst, IDLoc, Instructions, true, true);
1900 case Mips::UDivMacro:
1901 return expandDiv(Inst, IDLoc, Instructions, false, false);
1902 case Mips::DUDivMacro:
1903 return expandDiv(Inst, IDLoc, Instructions, true, false);
Toma Tabacud88d79c2015-06-23 14:39:42 +00001904 case Mips::Ulhu:
1905 return expandUlhu(Inst, IDLoc, Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00001906 case Mips::Ulw:
1907 return expandUlw(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001908 }
Jack Carter30a59822012-10-04 04:03:53 +00001909}
Jack Carter92995f12012-10-06 00:53:28 +00001910
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001911namespace {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001912void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc,
Daniel Sanders03f9c012015-07-14 12:24:22 +00001913 SmallVectorImpl<MCInst> &Instructions) {
1914 MCInst tmpInst;
1915 tmpInst.setOpcode(Opcode);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001916 tmpInst.addOperand(MCOperand::createReg(Reg0));
1917 tmpInst.addOperand(Op1);
Daniel Sanders03f9c012015-07-14 12:24:22 +00001918 tmpInst.setLoc(IDLoc);
1919 Instructions.push_back(tmpInst);
1920}
1921
Daniel Sandersf1ae3672015-08-18 09:55:57 +00001922void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc,
Daniel Sanders03f9c012015-07-14 12:24:22 +00001923 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001924 emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00001925}
1926
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00001927void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc,
1928 SmallVectorImpl<MCInst> &Instructions) {
1929 emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, Instructions);
1930}
1931
1932void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc,
1933 SmallVectorImpl<MCInst> &Instructions) {
1934 MCInst tmpInst;
1935 tmpInst.setOpcode(Opcode);
1936 tmpInst.addOperand(MCOperand::createImm(Imm1));
1937 tmpInst.addOperand(MCOperand::createImm(Imm2));
1938 tmpInst.setLoc(IDLoc);
1939 Instructions.push_back(tmpInst);
1940}
1941
1942void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
1943 SmallVectorImpl<MCInst> &Instructions) {
1944 MCInst tmpInst;
1945 tmpInst.setOpcode(Opcode);
1946 tmpInst.addOperand(MCOperand::createReg(Reg0));
1947 tmpInst.setLoc(IDLoc);
1948 Instructions.push_back(tmpInst);
1949}
1950
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001951void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2,
Daniel Sanders03f9c012015-07-14 12:24:22 +00001952 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1953 MCInst tmpInst;
1954 tmpInst.setOpcode(Opcode);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001955 tmpInst.addOperand(MCOperand::createReg(Reg0));
1956 tmpInst.addOperand(MCOperand::createReg(Reg1));
1957 tmpInst.addOperand(Op2);
Daniel Sanders03f9c012015-07-14 12:24:22 +00001958 tmpInst.setLoc(IDLoc);
1959 Instructions.push_back(tmpInst);
1960}
1961
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001962void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
Daniel Sanders03f9c012015-07-14 12:24:22 +00001963 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001964 emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc,
Daniel Sanders03f9c012015-07-14 12:24:22 +00001965 Instructions);
1966}
1967
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001968void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
1969 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1970 emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc,
1971 Instructions);
1972}
Daniel Sanders03f9c012015-07-14 12:24:22 +00001973
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001974void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount,
1975 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1976 if (ShiftAmount >= 32) {
1977 emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc,
1978 Instructions);
Toma Tabacu7dea2e32015-04-28 14:06:35 +00001979 return;
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001980 }
Toma Tabacu7dea2e32015-04-28 14:06:35 +00001981
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001982 emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001983}
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001984} // end anonymous namespace.
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001985
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001986bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
1987 SmallVectorImpl<MCInst> &Instructions) {
1988 // Create a JALR instruction which is going to replace the pseudo-JAL.
1989 MCInst JalrInst;
1990 JalrInst.setLoc(IDLoc);
1991 const MCOperand FirstRegOp = Inst.getOperand(0);
1992 const unsigned Opcode = Inst.getOpcode();
1993
1994 if (Opcode == Mips::JalOneReg) {
1995 // jal $rs => jalr $rs
1996 if (inMicroMipsMode()) {
1997 JalrInst.setOpcode(Mips::JALR16_MM);
1998 JalrInst.addOperand(FirstRegOp);
1999 } else {
2000 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002001 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002002 JalrInst.addOperand(FirstRegOp);
2003 }
2004 } else if (Opcode == Mips::JalTwoReg) {
2005 // jal $rd, $rs => jalr $rd, $rs
2006 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
2007 JalrInst.addOperand(FirstRegOp);
2008 const MCOperand SecondRegOp = Inst.getOperand(1);
2009 JalrInst.addOperand(SecondRegOp);
2010 }
2011 Instructions.push_back(JalrInst);
2012
2013 // If .set reorder is active, emit a NOP after it.
2014 if (AssemblerOptions.back()->isReorder()) {
2015 // This is a 32-bit NOP because these 2 pseudo-instructions
2016 // do not have a short delay slot.
2017 MCInst NopInst;
2018 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00002019 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2020 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2021 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002022 Instructions.push_back(NopInst);
2023 }
2024
2025 return false;
2026}
2027
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002028/// Can the value be represented by a unsigned N-bit value and a shift left?
2029template<unsigned N>
2030bool isShiftedUIntAtAnyPosition(uint64_t x) {
2031 unsigned BitNum = findFirstSet(x);
2032
2033 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2034}
2035
2036/// Load (or add) an immediate into a register.
2037///
2038/// @param ImmValue The immediate to load.
2039/// @param DstReg The register that will hold the immediate.
2040/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2041/// for a simple initialization.
2042/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2043/// @param IsAddress True if the immediate represents an address. False if it
2044/// is an integer.
2045/// @param IDLoc Location of the immediate in the source file.
2046/// @param Instructions The instructions emitted by this expansion.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002047bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002048 unsigned SrcReg, bool Is32BitImm,
2049 bool IsAddress, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00002050 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00002051 if (!Is32BitImm && !isGP64bit()) {
2052 Error(IDLoc, "instruction requires a 64-bit architecture");
2053 return true;
2054 }
2055
Daniel Sanders03f9c012015-07-14 12:24:22 +00002056 if (Is32BitImm) {
2057 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2058 // Sign extend up to 64-bit so that the predicates match the hardware
2059 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2060 // true.
2061 ImmValue = SignExtend64<32>(ImmValue);
2062 } else {
2063 Error(IDLoc, "instruction requires a 32-bit immediate");
2064 return true;
2065 }
2066 }
2067
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002068 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2069 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2070
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002071 bool UseSrcReg = false;
2072 if (SrcReg != Mips::NoRegister)
2073 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002074
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002075 unsigned TmpReg = DstReg;
2076 if (UseSrcReg && (DstReg == SrcReg)) {
2077 // At this point we need AT to perform the expansions and we exit if it is
2078 // not available.
2079 unsigned ATReg = getATReg(IDLoc);
2080 if (!ATReg)
2081 return true;
2082 TmpReg = ATReg;
2083 }
2084
Daniel Sanders03f9c012015-07-14 12:24:22 +00002085 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002086 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002087 SrcReg = ZeroReg;
2088
2089 // This doesn't quite follow the usual ABI expectations for N32 but matches
2090 // traditional assembler behaviour. N32 would normally use addiu for both
2091 // integers and addresses.
2092 if (IsAddress && !Is32BitImm) {
2093 emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2094 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002095 }
2096
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002097 emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2098 return false;
2099 }
2100
2101 if (isUInt<16>(ImmValue)) {
2102 unsigned TmpReg = DstReg;
2103 if (SrcReg == DstReg) {
2104 TmpReg = getATReg(IDLoc);
2105 if (!TmpReg)
2106 return true;
2107 }
2108
2109 emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002110 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002111 emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2112 return false;
2113 }
2114
2115 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002116 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002117
Toma Tabacu79588102015-04-29 10:19:56 +00002118 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2119 uint16_t Bits15To0 = ImmValue & 0xffff;
2120
Toma Tabacua3d056f2015-05-15 09:42:11 +00002121 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002122 // Traditional behaviour seems to special case this particular value. It's
2123 // not clear why other masks are handled differently.
2124 if (ImmValue == 0xffffffff) {
Daniel Sandersf1ae3672015-08-18 09:55:57 +00002125 emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002126 emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, Instructions);
2127 if (UseSrcReg)
2128 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2129 return false;
2130 }
2131
2132 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002133 // upper 32 bits.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002134 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002135 emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002136 if (Bits15To0)
2137 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
2138 if (UseSrcReg)
2139 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2140 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002141 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002142
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002143 emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions);
2144 if (Bits15To0)
2145 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002146 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002147 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2148 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002149 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002150
2151 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2152 if (Is32BitImm) {
2153 Error(IDLoc, "instruction requires a 32-bit immediate");
2154 return true;
2155 }
2156
2157 // Traditionally, these immediates are shifted as little as possible and as
2158 // such we align the most significant bit to bit 15 of our temporary.
2159 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2160 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2161 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2162 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
2163 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, Instructions);
2164 emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, Instructions);
2165
2166 if (UseSrcReg)
2167 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2168
2169 return false;
2170 }
2171
2172 warnIfNoMacro(IDLoc);
2173
2174 // The remaining case is packed with a sequence of dsll and ori with zeros
2175 // being omitted and any neighbouring dsll's being coalesced.
2176 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2177
2178 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2179 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
2180 IDLoc, Instructions))
2181 return false;
2182
2183 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2184 // skip it and defer the shift to the next chunk.
2185 unsigned ShiftCarriedForwards = 16;
2186 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2187 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2188
2189 if (ImmChunk != 0) {
2190 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2191 Instructions);
2192 emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, Instructions);
2193 ShiftCarriedForwards = 0;
2194 }
2195
2196 ShiftCarriedForwards += 16;
2197 }
2198 ShiftCarriedForwards -= 16;
2199
2200 // Finish any remaining shifts left by trailing zeros.
2201 if (ShiftCarriedForwards)
2202 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2203 Instructions);
2204
2205 if (UseSrcReg)
2206 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2207
Matheus Almeida3813d572014-06-19 14:39:14 +00002208 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002209}
Jack Carter92995f12012-10-06 00:53:28 +00002210
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002211bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
2212 SmallVectorImpl<MCInst> &Instructions) {
2213 const MCOperand &ImmOp = Inst.getOperand(1);
2214 assert(ImmOp.isImm() && "expected immediate operand kind");
2215 const MCOperand &DstRegOp = Inst.getOperand(0);
2216 assert(DstRegOp.isReg() && "expected register operand kind");
2217
2218 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002219 Is32BitImm, false, IDLoc, Instructions))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002220 return true;
2221
2222 return false;
2223}
2224
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002225bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2226 const MCOperand &Offset,
2227 bool Is32BitAddress, SMLoc IDLoc,
2228 SmallVectorImpl<MCInst> &Instructions) {
2229 // la can't produce a usable address when addresses are 64-bit.
2230 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2231 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2232 // We currently can't do this because we depend on the equality
2233 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2234 Error(IDLoc, "la used to load 64-bit address");
2235 // Continue as if we had 'dla' instead.
2236 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002237 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002238
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002239 // dla requires 64-bit addresses.
2240 if (!Is32BitAddress && !ABI.ArePtrs64bit()) {
2241 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002242 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002243 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002244
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002245 if (!Offset.isImm())
2246 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
2247 Is32BitAddress, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002248
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002249 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
2250 IDLoc, Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +00002251}
2252
Toma Tabacuf712ede2015-06-17 14:31:51 +00002253bool MipsAsmParser::loadAndAddSymbolAddress(
2254 const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
2255 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002256 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002257
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002258 // FIXME: The way we're handling symbols right now prevents simple expressions
2259 // like foo+8. We'll be able to fix this once our unary operators (%hi
2260 // and similar) are treated as operators rather than as fixup types.
Toma Tabacu674825c2015-06-16 12:16:24 +00002261 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymExpr);
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002262 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::create(
2263 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
2264 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::create(
2265 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
2266
Toma Tabacufb9d1252015-06-22 12:08:39 +00002267 bool UseSrcReg = SrcReg != Mips::NoRegister;
2268
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002269 // This is the 64-bit symbol address expansion.
2270 if (ABI.ArePtrs64bit() && isGP64bit()) {
2271 // We always need AT for the 64-bit expansion.
2272 // If it is not available we exit.
2273 unsigned ATReg = getATReg(IDLoc);
2274 if (!ATReg)
2275 return true;
2276
2277 const MCSymbolRefExpr *HighestExpr = MCSymbolRefExpr::create(
2278 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
2279 const MCSymbolRefExpr *HigherExpr = MCSymbolRefExpr::create(
2280 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
2281
2282 if (UseSrcReg && (DstReg == SrcReg)) {
2283 // If $rs is the same as $rd:
2284 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2285 // daddiu $at, $at, %higher(sym)
2286 // dsll $at, $at, 16
2287 // daddiu $at, $at, %hi(sym)
2288 // dsll $at, $at, 16
2289 // daddiu $at, $at, %lo(sym)
2290 // daddu $rd, $at, $rd
2291 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2292 Instructions);
2293 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr),
2294 IDLoc, Instructions);
2295 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2296 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2297 Instructions);
2298 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2299 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2300 Instructions);
2301 emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions);
2302
2303 return false;
2304 }
2305
2306 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2307 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2308 // lui $at, %hi(sym)
2309 // daddiu $rd, $rd, %higher(sym)
2310 // daddiu $at, $at, %lo(sym)
2311 // dsll32 $rd, $rd, 0
2312 // daddu $rd, $rd, $at
2313 // (daddu $rd, $rd, $rs)
2314 emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2315 Instructions);
2316 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2317 Instructions);
2318 emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr),
2319 IDLoc, Instructions);
2320 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2321 Instructions);
2322 emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions);
2323 emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions);
2324 if (UseSrcReg)
2325 emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions);
2326
2327 return false;
2328 }
2329
2330 // And now, the 32-bit symbol address expansion:
2331 // If $rs is the same as $rd:
2332 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2333 // ori $at, $at, %lo(sym)
2334 // addu $rd, $at, $rd
2335 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2336 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2337 // ori $rd, $rd, %lo(sym)
2338 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002339 unsigned TmpReg = DstReg;
2340 if (UseSrcReg && (DstReg == SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002341 // If $rs is the same as $rd, we need to use AT.
2342 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002343 unsigned ATReg = getATReg(IDLoc);
2344 if (!ATReg)
2345 return true;
2346 TmpReg = ATReg;
2347 }
2348
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002349 emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions);
2350 emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc,
2351 Instructions);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002352
Toma Tabacufb9d1252015-06-22 12:08:39 +00002353 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002354 emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2355 else
2356 assert(DstReg == TmpReg);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002357
Toma Tabacu674825c2015-06-16 12:16:24 +00002358 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002359}
2360
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002361bool MipsAsmParser::expandUncondBranchMMPseudo(
2362 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002363 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2364 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002365
2366 MCOperand Offset = Inst.getOperand(0);
2367 if (Offset.isExpr()) {
2368 Inst.clear();
2369 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002370 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2371 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2372 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002373 } else {
2374 assert(Offset.isImm() && "expected immediate operand kind");
2375 if (isIntN(11, Offset.getImm())) {
2376 // If offset fits into 11 bits then this instruction becomes microMIPS
2377 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002378 if (inMicroMipsMode())
2379 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002380 } else {
2381 if (!isIntN(17, Offset.getImm()))
2382 Error(IDLoc, "branch target out of range");
2383 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2384 Error(IDLoc, "branch to misaligned address");
2385 Inst.clear();
2386 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002387 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2388 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2389 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002390 }
2391 }
2392 Instructions.push_back(Inst);
2393
Zoran Jovanovicada70912015-09-07 11:56:37 +00002394 // If .set reorder is active and branch instruction has a delay slot,
2395 // emit a NOP after it.
2396 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2397 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Toma Tabacu234482a2015-03-16 12:03:39 +00002398 createNop(true, IDLoc, Instructions);
2399
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002400 return false;
2401}
2402
Toma Tabacue1e460d2015-06-11 10:36:10 +00002403bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2404 SmallVectorImpl<MCInst> &Instructions) {
2405 const MCOperand &DstRegOp = Inst.getOperand(0);
2406 assert(DstRegOp.isReg() && "expected register operand kind");
2407
2408 const MCOperand &ImmOp = Inst.getOperand(1);
2409 assert(ImmOp.isImm() && "expected immediate operand kind");
2410
2411 const MCOperand &MemOffsetOp = Inst.getOperand(2);
2412 assert(MemOffsetOp.isImm() && "expected immediate operand kind");
2413
2414 unsigned OpCode = 0;
2415 switch(Inst.getOpcode()) {
2416 case Mips::BneImm:
2417 OpCode = Mips::BNE;
2418 break;
2419 case Mips::BeqImm:
2420 OpCode = Mips::BEQ;
2421 break;
2422 default:
2423 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2424 break;
2425 }
2426
2427 int64_t ImmValue = ImmOp.getImm();
2428 if (ImmValue == 0) {
2429 MCInst BranchInst;
2430 BranchInst.setOpcode(OpCode);
2431 BranchInst.addOperand(DstRegOp);
2432 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2433 BranchInst.addOperand(MemOffsetOp);
2434 Instructions.push_back(BranchInst);
2435 } else {
2436 warnIfNoMacro(IDLoc);
2437
2438 unsigned ATReg = getATReg(IDLoc);
2439 if (!ATReg)
2440 return true;
2441
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002442 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
2443 IDLoc, Instructions))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002444 return true;
2445
2446 MCInst BranchInst;
2447 BranchInst.setOpcode(OpCode);
2448 BranchInst.addOperand(DstRegOp);
2449 BranchInst.addOperand(MCOperand::createReg(ATReg));
2450 BranchInst.addOperand(MemOffsetOp);
2451 Instructions.push_back(BranchInst);
2452 }
2453 return false;
2454}
2455
Jack Carter9e65aa32013-03-22 00:05:30 +00002456void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002457 SmallVectorImpl<MCInst> &Instructions,
2458 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002459 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00002460 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002461 const MCExpr *ExprOffset;
2462 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002463 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002464 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2465 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002466 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002467 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2468 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002469 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002470 if (isImmOpnd) {
2471 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2472 ImmOffset = Inst.getOperand(2).getImm();
2473 LoOffset = ImmOffset & 0x0000ffff;
2474 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002475 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002476 if (LoOffset & 0x8000)
2477 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002478 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002479 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002480 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002481 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002482 // These are some of the types of expansions we perform here:
2483 // 1) lw $8, sym => lui $8, %hi(sym)
2484 // lw $8, %lo(sym)($8)
2485 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2486 // add $8, $8, $9
2487 // lw $8, %lo(offset)($9)
2488 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2489 // add $at, $at, $8
2490 // lw $8, %lo(offset)($at)
2491 // 4) sw $8, sym => lui $at, %hi(sym)
2492 // sw $8, %lo(sym)($at)
2493 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2494 // add $at, $at, $8
2495 // sw $8, %lo(offset)($at)
2496 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2497 // ldc1 $f0, %lo(sym)($at)
2498 //
2499 // For load instructions we can use the destination register as a temporary
2500 // if base and dst are different (examples 1 and 2) and if the base register
2501 // is general purpose otherwise we must use $at (example 6) and error if it's
2502 // not available. For stores we must use $at (examples 4 and 5) because we
2503 // must not clobber the source register setting up the offset.
2504 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2505 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2506 unsigned RegClassIDOp0 =
2507 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2508 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2509 (RegClassIDOp0 == Mips::GPR64RegClassID);
2510 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002511 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002512 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002513 // At this point we need AT to perform the expansions and we exit if it is
2514 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002515 TmpRegNum = getATReg(IDLoc);
2516 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002517 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002518 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002519
Jack Carter9e65aa32013-03-22 00:05:30 +00002520 TempInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00002521 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002522 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002523 TempInst.addOperand(MCOperand::createImm(HiOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002524 else {
Toma Tabacu07c97b32015-06-17 10:43:45 +00002525 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
2526 TempInst.addOperand(MCOperand::createExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002527 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002528 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002529 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002530 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002531 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002532 // Add temp register to base.
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002533 if (BaseRegNum != Mips::ZERO) {
2534 TempInst.setOpcode(Mips::ADDu);
Jim Grosbache9119e42015-05-13 18:37:00 +00002535 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2536 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2537 TempInst.addOperand(MCOperand::createReg(BaseRegNum));
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002538 Instructions.push_back(TempInst);
2539 TempInst.clear();
2540 }
Alp Tokercb402912014-01-24 17:20:08 +00002541 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002542 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002543 TempInst.setOpcode(Inst.getOpcode());
Jim Grosbache9119e42015-05-13 18:37:00 +00002544 TempInst.addOperand(MCOperand::createReg(RegOpNum));
2545 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002546 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002547 TempInst.addOperand(MCOperand::createImm(LoOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002548 else {
Toma Tabacu07c97b32015-06-17 10:43:45 +00002549 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
2550 TempInst.addOperand(MCOperand::createExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002551 }
2552 Instructions.push_back(TempInst);
2553 TempInst.clear();
2554}
2555
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002556bool
2557MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2558 SmallVectorImpl<MCInst> &Instructions) {
2559 unsigned OpNum = Inst.getNumOperands();
2560 unsigned Opcode = Inst.getOpcode();
2561 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2562
2563 assert (Inst.getOperand(OpNum - 1).isImm() &&
2564 Inst.getOperand(OpNum - 2).isReg() &&
2565 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2566
2567 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2568 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2569 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2570 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2571 // It can be implemented as SWM16 or LWM16 instruction.
2572 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2573
2574 Inst.setOpcode(NewOpcode);
2575 Instructions.push_back(Inst);
2576 return false;
2577}
2578
Toma Tabacu1a108322015-06-17 13:20:24 +00002579bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2580 SmallVectorImpl<MCInst> &Instructions) {
2581 unsigned PseudoOpcode = Inst.getOpcode();
2582 unsigned SrcReg = Inst.getOperand(0).getReg();
2583 unsigned TrgReg = Inst.getOperand(1).getReg();
2584 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2585
2586 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002587 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002588
2589 switch (PseudoOpcode) {
2590 case Mips::BLT:
2591 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002592 case Mips::BLTL:
2593 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002594 AcceptsEquality = false;
2595 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002596 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2597 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002598 ZeroSrcOpcode = Mips::BGTZ;
2599 ZeroTrgOpcode = Mips::BLTZ;
2600 break;
2601 case Mips::BLE:
2602 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002603 case Mips::BLEL:
2604 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002605 AcceptsEquality = true;
2606 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002607 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2608 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002609 ZeroSrcOpcode = Mips::BGEZ;
2610 ZeroTrgOpcode = Mips::BLEZ;
2611 break;
2612 case Mips::BGE:
2613 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002614 case Mips::BGEL:
2615 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002616 AcceptsEquality = true;
2617 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002618 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2619 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002620 ZeroSrcOpcode = Mips::BLEZ;
2621 ZeroTrgOpcode = Mips::BGEZ;
2622 break;
2623 case Mips::BGT:
2624 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002625 case Mips::BGTL:
2626 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002627 AcceptsEquality = false;
2628 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002629 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2630 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002631 ZeroSrcOpcode = Mips::BLTZ;
2632 ZeroTrgOpcode = Mips::BGTZ;
2633 break;
2634 default:
2635 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2636 }
2637
2638 MCInst BranchInst;
2639 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2640 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2641 if (IsSrcRegZero && IsTrgRegZero) {
2642 // FIXME: All of these Opcode-specific if's are needed for compatibility
2643 // with GAS' behaviour. However, they may not generate the most efficient
2644 // code in some circumstances.
2645 if (PseudoOpcode == Mips::BLT) {
2646 BranchInst.setOpcode(Mips::BLTZ);
2647 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2648 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2649 Instructions.push_back(BranchInst);
2650 return false;
2651 }
2652 if (PseudoOpcode == Mips::BLE) {
2653 BranchInst.setOpcode(Mips::BLEZ);
2654 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2655 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2656 Instructions.push_back(BranchInst);
2657 Warning(IDLoc, "branch is always taken");
2658 return false;
2659 }
2660 if (PseudoOpcode == Mips::BGE) {
2661 BranchInst.setOpcode(Mips::BGEZ);
2662 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2663 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2664 Instructions.push_back(BranchInst);
2665 Warning(IDLoc, "branch is always taken");
2666 return false;
2667 }
2668 if (PseudoOpcode == Mips::BGT) {
2669 BranchInst.setOpcode(Mips::BGTZ);
2670 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2671 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2672 Instructions.push_back(BranchInst);
2673 return false;
2674 }
2675 if (PseudoOpcode == Mips::BGTU) {
2676 BranchInst.setOpcode(Mips::BNE);
2677 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2678 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2679 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2680 Instructions.push_back(BranchInst);
2681 return false;
2682 }
2683 if (AcceptsEquality) {
2684 // If both registers are $0 and the pseudo-branch accepts equality, it
2685 // will always be taken, so we emit an unconditional branch.
2686 BranchInst.setOpcode(Mips::BEQ);
2687 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2688 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2689 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2690 Instructions.push_back(BranchInst);
2691 Warning(IDLoc, "branch is always taken");
2692 return false;
2693 }
2694 // If both registers are $0 and the pseudo-branch does not accept
2695 // equality, it will never be taken, so we don't have to emit anything.
2696 return false;
2697 }
2698 if (IsSrcRegZero || IsTrgRegZero) {
2699 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2700 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2701 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2702 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2703 // the pseudo-branch will never be taken, so we don't emit anything.
2704 // This only applies to unsigned pseudo-branches.
2705 return false;
2706 }
2707 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2708 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2709 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2710 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2711 // the pseudo-branch will always be taken, so we emit an unconditional
2712 // branch.
2713 // This only applies to unsigned pseudo-branches.
2714 BranchInst.setOpcode(Mips::BEQ);
2715 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2716 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2717 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2718 Instructions.push_back(BranchInst);
2719 Warning(IDLoc, "branch is always taken");
2720 return false;
2721 }
2722 if (IsUnsigned) {
2723 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2724 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2725 // the pseudo-branch will be taken only when the non-zero register is
2726 // different from 0, so we emit a BNEZ.
2727 //
2728 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2729 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2730 // the pseudo-branch will be taken only when the non-zero register is
2731 // equal to 0, so we emit a BEQZ.
2732 //
2733 // Because only BLEU and BGEU branch on equality, we can use the
2734 // AcceptsEquality variable to decide when to emit the BEQZ.
2735 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQ : Mips::BNE);
2736 BranchInst.addOperand(
2737 MCOperand::createReg(IsSrcRegZero ? TrgReg : SrcReg));
2738 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2739 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2740 Instructions.push_back(BranchInst);
2741 return false;
2742 }
2743 // If we have a signed pseudo-branch and one of the registers is $0,
2744 // we can use an appropriate compare-to-zero branch. We select which one
2745 // to use in the switch statement above.
2746 BranchInst.setOpcode(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode);
2747 BranchInst.addOperand(MCOperand::createReg(IsSrcRegZero ? TrgReg : SrcReg));
2748 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2749 Instructions.push_back(BranchInst);
2750 return false;
2751 }
2752
2753 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2754 // expansions. If it is not available, we return.
2755 unsigned ATRegNum = getATReg(IDLoc);
2756 if (!ATRegNum)
2757 return true;
2758
2759 warnIfNoMacro(IDLoc);
2760
2761 // SLT fits well with 2 of our 4 pseudo-branches:
2762 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2763 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2764 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2765 // This is accomplished by using a BNEZ with the result of the SLT.
2766 //
2767 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2768 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2769 // Because only BGE and BLE branch on equality, we can use the
2770 // AcceptsEquality variable to decide when to emit the BEQZ.
2771 // Note that the order of the SLT arguments doesn't change between
2772 // opposites.
2773 //
2774 // The same applies to the unsigned variants, except that SLTu is used
2775 // instead of SLT.
2776 MCInst SetInst;
2777 SetInst.setOpcode(IsUnsigned ? Mips::SLTu : Mips::SLT);
2778 SetInst.addOperand(MCOperand::createReg(ATRegNum));
2779 SetInst.addOperand(MCOperand::createReg(ReverseOrderSLT ? TrgReg : SrcReg));
2780 SetInst.addOperand(MCOperand::createReg(ReverseOrderSLT ? SrcReg : TrgReg));
2781 Instructions.push_back(SetInst);
2782
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002783 if (!IsLikely)
2784 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQ : Mips::BNE);
2785 else
2786 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQL : Mips::BNEL);
Toma Tabacu1a108322015-06-17 13:20:24 +00002787 BranchInst.addOperand(MCOperand::createReg(ATRegNum));
2788 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2789 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2790 Instructions.push_back(BranchInst);
2791 return false;
2792}
2793
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002794bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
2795 SmallVectorImpl<MCInst> &Instructions,
2796 const bool IsMips64, const bool Signed) {
2797 if (hasMips32r6()) {
2798 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2799 return false;
2800 }
2801
2802 warnIfNoMacro(IDLoc);
2803
2804 const MCOperand &RsRegOp = Inst.getOperand(0);
2805 assert(RsRegOp.isReg() && "expected register operand kind");
2806 unsigned RsReg = RsRegOp.getReg();
2807
2808 const MCOperand &RtRegOp = Inst.getOperand(1);
2809 assert(RtRegOp.isReg() && "expected register operand kind");
2810 unsigned RtReg = RtRegOp.getReg();
2811 unsigned DivOp;
2812 unsigned ZeroReg;
2813
2814 if (IsMips64) {
2815 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2816 ZeroReg = Mips::ZERO_64;
2817 } else {
2818 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2819 ZeroReg = Mips::ZERO;
2820 }
2821
2822 bool UseTraps = useTraps();
2823
2824 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2825 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2826 Warning(IDLoc, "dividing zero by zero");
2827 if (IsMips64) {
2828 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2829 if (UseTraps) {
2830 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2831 return false;
2832 }
2833
2834 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2835 return false;
2836 }
2837 } else {
2838 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2839 return false;
2840 }
2841 }
2842
2843 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
2844 Warning(IDLoc, "division by zero");
2845 if (Signed) {
2846 if (UseTraps) {
2847 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2848 return false;
2849 }
2850
2851 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2852 return false;
2853 }
2854 }
2855
2856 // FIXME: The values for these two BranchTarget variables may be different in
2857 // micromips. These magic numbers need to be removed.
2858 unsigned BranchTargetNoTraps;
2859 unsigned BranchTarget;
2860
2861 if (UseTraps) {
2862 BranchTarget = IsMips64 ? 12 : 8;
2863 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2864 } else {
2865 BranchTarget = IsMips64 ? 20 : 16;
2866 BranchTargetNoTraps = 8;
2867 // Branch to the li instruction.
2868 emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc,
2869 Instructions);
2870 }
2871
2872 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2873
2874 if (!UseTraps)
2875 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2876
2877 if (!Signed) {
2878 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
2879 return false;
2880 }
2881
2882 unsigned ATReg = getATReg(IDLoc);
2883 if (!ATReg)
2884 return true;
2885
2886 emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, Instructions);
2887 if (IsMips64) {
2888 // Branch to the mflo instruction.
2889 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
2890 emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, Instructions);
2891 emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, Instructions);
2892 } else {
2893 // Branch to the mflo instruction.
2894 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
2895 emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, Instructions);
2896 }
2897
2898 if (UseTraps)
2899 emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, Instructions);
2900 else {
2901 // Branch to the mflo instruction.
2902 emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, Instructions);
2903 emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, Instructions);
2904 emitII(Mips::BREAK, 0x6, 0, IDLoc, Instructions);
2905 }
2906 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
2907 return false;
2908}
2909
Toma Tabacud88d79c2015-06-23 14:39:42 +00002910bool MipsAsmParser::expandUlhu(MCInst &Inst, SMLoc IDLoc,
2911 SmallVectorImpl<MCInst> &Instructions) {
2912 if (hasMips32r6() || hasMips64r6()) {
2913 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2914 return false;
2915 }
2916
2917 warnIfNoMacro(IDLoc);
2918
2919 const MCOperand &DstRegOp = Inst.getOperand(0);
2920 assert(DstRegOp.isReg() && "expected register operand kind");
2921
2922 const MCOperand &SrcRegOp = Inst.getOperand(1);
2923 assert(SrcRegOp.isReg() && "expected register operand kind");
2924
2925 const MCOperand &OffsetImmOp = Inst.getOperand(2);
2926 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
2927
2928 unsigned DstReg = DstRegOp.getReg();
2929 unsigned SrcReg = SrcRegOp.getReg();
2930 int64_t OffsetValue = OffsetImmOp.getImm();
2931
2932 // NOTE: We always need AT for ULHU, as it is always used as the source
2933 // register for one of the LBu's.
2934 unsigned ATReg = getATReg(IDLoc);
2935 if (!ATReg)
2936 return true;
2937
2938 // When the value of offset+1 does not fit in 16 bits, we have to load the
2939 // offset in AT, (D)ADDu the original source register (if there was one), and
2940 // then use AT as the source register for the 2 generated LBu's.
2941 bool LoadedOffsetInAT = false;
2942 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
2943 LoadedOffsetInAT = true;
2944
2945 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002946 true, IDLoc, Instructions))
Toma Tabacud88d79c2015-06-23 14:39:42 +00002947 return true;
2948
2949 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
2950 // because it will make our output more similar to GAS'. For example,
2951 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
2952 // instead of just an "ori $1, $9, 32768".
2953 // NOTE: If there is no source register specified in the ULHU, the parser
2954 // will interpret it as $0.
2955 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
2956 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
2957 }
2958
2959 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
2960 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
2961 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
2962
2963 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
2964 if (isLittle()) {
2965 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
2966 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
2967 } else {
2968 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
2969 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
2970 }
2971
2972 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
2973
2974 MCInst TmpInst;
2975 TmpInst.setOpcode(Mips::LBu);
2976 TmpInst.addOperand(MCOperand::createReg(FirstLbuDstReg));
2977 TmpInst.addOperand(MCOperand::createReg(LbuSrcReg));
2978 TmpInst.addOperand(MCOperand::createImm(FirstLbuOffset));
2979 Instructions.push_back(TmpInst);
2980
2981 TmpInst.clear();
2982 TmpInst.setOpcode(Mips::LBu);
2983 TmpInst.addOperand(MCOperand::createReg(SecondLbuDstReg));
2984 TmpInst.addOperand(MCOperand::createReg(LbuSrcReg));
2985 TmpInst.addOperand(MCOperand::createImm(SecondLbuOffset));
2986 Instructions.push_back(TmpInst);
2987
2988 TmpInst.clear();
2989 TmpInst.setOpcode(Mips::SLL);
2990 TmpInst.addOperand(MCOperand::createReg(SllReg));
2991 TmpInst.addOperand(MCOperand::createReg(SllReg));
2992 TmpInst.addOperand(MCOperand::createImm(8));
2993 Instructions.push_back(TmpInst);
2994
2995 TmpInst.clear();
2996 TmpInst.setOpcode(Mips::OR);
2997 TmpInst.addOperand(MCOperand::createReg(DstReg));
2998 TmpInst.addOperand(MCOperand::createReg(DstReg));
2999 TmpInst.addOperand(MCOperand::createReg(ATReg));
3000 Instructions.push_back(TmpInst);
3001
3002 return false;
3003}
3004
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003005bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
3006 SmallVectorImpl<MCInst> &Instructions) {
3007 if (hasMips32r6() || hasMips64r6()) {
3008 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3009 return false;
3010 }
3011
3012 const MCOperand &DstRegOp = Inst.getOperand(0);
3013 assert(DstRegOp.isReg() && "expected register operand kind");
3014
3015 const MCOperand &SrcRegOp = Inst.getOperand(1);
3016 assert(SrcRegOp.isReg() && "expected register operand kind");
3017
3018 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3019 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3020
3021 unsigned SrcReg = SrcRegOp.getReg();
3022 int64_t OffsetValue = OffsetImmOp.getImm();
3023 unsigned ATReg = 0;
3024
3025 // When the value of offset+3 does not fit in 16 bits, we have to load the
3026 // offset in AT, (D)ADDu the original source register (if there was one), and
3027 // then use AT as the source register for the generated LWL and LWR.
3028 bool LoadedOffsetInAT = false;
3029 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3030 ATReg = getATReg(IDLoc);
3031 if (!ATReg)
3032 return true;
3033 LoadedOffsetInAT = true;
3034
3035 warnIfNoMacro(IDLoc);
3036
3037 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003038 true, IDLoc, Instructions))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003039 return true;
3040
3041 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3042 // because it will make our output more similar to GAS'. For example,
3043 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3044 // instead of just an "ori $1, $9, 32768".
3045 // NOTE: If there is no source register specified in the ULW, the parser
3046 // will interpret it as $0.
3047 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3048 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3049 }
3050
3051 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3052 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3053 if (isLittle()) {
3054 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3055 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3056 } else {
3057 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3058 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3059 }
3060
3061 MCInst LeftLoadInst;
3062 LeftLoadInst.setOpcode(Mips::LWL);
3063 LeftLoadInst.addOperand(DstRegOp);
3064 LeftLoadInst.addOperand(MCOperand::createReg(FinalSrcReg));
3065 LeftLoadInst.addOperand(MCOperand::createImm(LeftLoadOffset));
3066 Instructions.push_back(LeftLoadInst);
3067
3068 MCInst RightLoadInst;
3069 RightLoadInst.setOpcode(Mips::LWR);
3070 RightLoadInst.addOperand(DstRegOp);
3071 RightLoadInst.addOperand(MCOperand::createReg(FinalSrcReg));
3072 RightLoadInst.addOperand(MCOperand::createImm(RightLoadOffset ));
3073 Instructions.push_back(RightLoadInst);
3074
3075 return false;
3076}
3077
Toma Tabacu234482a2015-03-16 12:03:39 +00003078void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
3079 SmallVectorImpl<MCInst> &Instructions) {
3080 MCInst NopInst;
3081 if (hasShortDelaySlot) {
3082 NopInst.setOpcode(Mips::MOVE16_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003083 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
3084 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
Toma Tabacu234482a2015-03-16 12:03:39 +00003085 } else {
3086 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00003087 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
3088 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
3089 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu234482a2015-03-16 12:03:39 +00003090 }
3091 Instructions.push_back(NopInst);
3092}
3093
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003094void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +00003095 unsigned TrgReg, bool Is64Bit,
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003096 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders03f9c012015-07-14 12:24:22 +00003097 emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
3098 Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003099}
3100
Matheus Almeida595fcab2014-06-11 15:05:56 +00003101unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3102 // As described by the Mips32r2 spec, the registers Rd and Rs for
3103 // jalr.hb must be different.
3104 unsigned Opcode = Inst.getOpcode();
3105
3106 if (Opcode == Mips::JALR_HB &&
3107 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3108 return Match_RequiresDifferentSrcAndDst;
3109
3110 return Match_Success;
3111}
3112
David Blaikie960ea3f2014-06-08 16:18:35 +00003113bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3114 OperandVector &Operands,
3115 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003116 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003117 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003118
Jack Carterb4dbc172012-09-05 23:34:03 +00003119 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00003120 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00003121 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003122 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003123
3124 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003125 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003126 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00003127 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00003128 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00003129 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00003130 return false;
3131 }
3132 case Match_MissingFeature:
3133 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3134 return true;
3135 case Match_InvalidOperand: {
3136 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003137 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003138 if (ErrorInfo >= Operands.size())
3139 return Error(IDLoc, "too few operands for instruction");
3140
David Blaikie960ea3f2014-06-08 16:18:35 +00003141 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003142 if (ErrorLoc == SMLoc())
3143 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003144 }
3145
3146 return Error(ErrorLoc, "invalid operand for instruction");
3147 }
3148 case Match_MnemonicFail:
3149 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003150 case Match_RequiresDifferentSrcAndDst:
3151 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00003152 }
Craig Topper589ceee2015-01-03 08:16:34 +00003153
3154 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003155}
3156
Toma Tabacud9d344b2015-04-27 14:05:04 +00003157void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3158 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3159 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3160 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003161}
3162
Toma Tabacu81496c12015-05-20 08:54:45 +00003163void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3164 if (!AssemblerOptions.back()->isMacro())
3165 Warning(Loc, "macro instruction expanded into multiple instructions");
3166}
3167
Daniel Sandersef638fe2014-10-03 15:37:37 +00003168void
3169MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3170 SMRange Range, bool ShowColors) {
3171 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003172 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003173 ShowColors);
3174}
3175
Jack Carter1ac53222013-02-20 23:11:17 +00003176int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003177 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003178
Vladimir Medic4c299852013-11-06 11:27:05 +00003179 CC = StringSwitch<unsigned>(Name)
3180 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003181 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003182 .Case("a0", 4)
3183 .Case("a1", 5)
3184 .Case("a2", 6)
3185 .Case("a3", 7)
3186 .Case("v0", 2)
3187 .Case("v1", 3)
3188 .Case("s0", 16)
3189 .Case("s1", 17)
3190 .Case("s2", 18)
3191 .Case("s3", 19)
3192 .Case("s4", 20)
3193 .Case("s5", 21)
3194 .Case("s6", 22)
3195 .Case("s7", 23)
3196 .Case("k0", 26)
3197 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003198 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003199 .Case("sp", 29)
3200 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003201 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003202 .Case("ra", 31)
3203 .Case("t0", 8)
3204 .Case("t1", 9)
3205 .Case("t2", 10)
3206 .Case("t3", 11)
3207 .Case("t4", 12)
3208 .Case("t5", 13)
3209 .Case("t6", 14)
3210 .Case("t7", 15)
3211 .Case("t8", 24)
3212 .Case("t9", 25)
3213 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003214
Toma Tabacufda445c2014-09-15 15:33:01 +00003215 if (!(isABI_N32() || isABI_N64()))
3216 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003217
Daniel Sandersef638fe2014-10-03 15:37:37 +00003218 if (12 <= CC && CC <= 15) {
3219 // Name is one of t4-t7
3220 AsmToken RegTok = getLexer().peekTok();
3221 SMRange RegRange = RegTok.getLocRange();
3222
3223 StringRef FixedName = StringSwitch<StringRef>(Name)
3224 .Case("t4", "t0")
3225 .Case("t5", "t1")
3226 .Case("t6", "t2")
3227 .Case("t7", "t3")
3228 .Default("");
3229 assert(FixedName != "" && "Register name is not one of t4-t7.");
3230
3231 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3232 "Did you mean $" + FixedName + "?", RegRange);
3233 }
3234
Toma Tabacufda445c2014-09-15 15:33:01 +00003235 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3236 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3237 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3238 if (8 <= CC && CC <= 11)
3239 CC += 4;
3240
3241 if (CC == -1)
3242 CC = StringSwitch<unsigned>(Name)
3243 .Case("a4", 8)
3244 .Case("a5", 9)
3245 .Case("a6", 10)
3246 .Case("a7", 11)
3247 .Case("kt0", 26)
3248 .Case("kt1", 27)
3249 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003250
3251 return CC;
3252}
Jack Carterd0bd6422013-04-18 00:41:53 +00003253
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003254int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3255 int CC;
3256
3257 CC = StringSwitch<unsigned>(Name)
3258 .Case("hwr_cpunum", 0)
3259 .Case("hwr_synci_step", 1)
3260 .Case("hwr_cc", 2)
3261 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003262 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003263 .Default(-1);
3264
3265 return CC;
3266}
3267
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003268int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003269
Jack Cartera63b16a2012-09-07 00:23:42 +00003270 if (Name[0] == 'f') {
3271 StringRef NumString = Name.substr(1);
3272 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003273 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003274 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003275 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003276 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003277 return IntVal;
3278 }
3279 return -1;
3280}
Jack Cartera63b16a2012-09-07 00:23:42 +00003281
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003282int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3283
3284 if (Name.startswith("fcc")) {
3285 StringRef NumString = Name.substr(3);
3286 unsigned IntVal;
3287 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003288 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003289 if (IntVal > 7) // There are only 8 fcc registers.
3290 return -1;
3291 return IntVal;
3292 }
3293 return -1;
3294}
3295
3296int MipsAsmParser::matchACRegisterName(StringRef Name) {
3297
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003298 if (Name.startswith("ac")) {
3299 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003300 unsigned IntVal;
3301 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003302 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003303 if (IntVal > 3) // There are only 3 acc registers.
3304 return -1;
3305 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003306 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003307 return -1;
3308}
Jack Carterd0bd6422013-04-18 00:41:53 +00003309
Jack Carter5dc8ac92013-09-25 23:50:44 +00003310int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3311 unsigned IntVal;
3312
3313 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3314 return -1;
3315
3316 if (IntVal > 31)
3317 return -1;
3318
3319 return IntVal;
3320}
3321
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003322int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3323 int CC;
3324
3325 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003326 .Case("msair", 0)
3327 .Case("msacsr", 1)
3328 .Case("msaaccess", 2)
3329 .Case("msasave", 3)
3330 .Case("msamodify", 4)
3331 .Case("msarequest", 5)
3332 .Case("msamap", 6)
3333 .Case("msaunmap", 7)
3334 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003335
3336 return CC;
3337}
3338
Toma Tabacu89a712b2015-04-15 10:48:56 +00003339unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00003340 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00003341 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00003342 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00003343 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00003344 return 0;
3345 }
3346 unsigned AT = getReg(
3347 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00003348 return AT;
3349}
Jack Carter0b744b32012-10-04 02:29:46 +00003350
Jack Carterd0bd6422013-04-18 00:41:53 +00003351unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00003352 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00003353}
3354
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003355unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003356 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00003357 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003358}
3359
Jack Carter873c7242013-01-12 01:03:14 +00003360int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003361 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00003362 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00003363 return -1;
3364
Jack Carter873c7242013-01-12 01:03:14 +00003365 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00003366}
3367
Toma Tabacu13964452014-09-04 13:23:44 +00003368bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003369 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003370 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003371
Jack Carter30a59822012-10-04 04:03:53 +00003372 // Check if the current operand has a custom associated parser, if so, try to
3373 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00003374 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3375 if (ResTy == MatchOperand_Success)
3376 return false;
3377 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3378 // there was a match, but an error occurred, in which case, just return that
3379 // the operand parsing failed.
3380 if (ResTy == MatchOperand_ParseFail)
3381 return true;
3382
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003383 DEBUG(dbgs() << ".. Generic Parser\n");
3384
Jack Carterb4dbc172012-09-05 23:34:03 +00003385 switch (getLexer().getKind()) {
3386 default:
3387 Error(Parser.getTok().getLoc(), "unexpected token in operand");
3388 return true;
3389 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003390 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00003391 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00003392
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003393 // Almost all registers have been parsed by custom parsers. There is only
3394 // one exception to this. $zero (and it's alias $0) will reach this point
3395 // for div, divu, and similar instructions because it is not an operand
3396 // to the instruction definition but an explicit register. Special case
3397 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00003398 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00003399 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003400
Jack Carterd0bd6422013-04-18 00:41:53 +00003401 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00003402 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003403 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00003404 return true;
3405
Jack Carter873c7242013-01-12 01:03:14 +00003406 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00003407 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00003408 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00003409 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003410 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00003411
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003412 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003413 return false;
3414 }
Vladimir Medic4c299852013-11-06 11:27:05 +00003415 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00003416 case AsmToken::LParen:
3417 case AsmToken::Minus:
3418 case AsmToken::Plus:
3419 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003420 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00003421 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003422 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003423 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003424 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00003425 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00003426 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003427 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003428 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003429 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00003430 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00003431 return true;
3432
Jack Carter873c7242013-01-12 01:03:14 +00003433 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3434
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003435 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00003436 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003437 } // case AsmToken::Percent
3438 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00003439 return true;
3440}
3441
Vladimir Medic4c299852013-11-06 11:27:05 +00003442const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00003443 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003444 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00003445 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003446 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00003447 // It's a constant, evaluate reloc value.
3448 int16_t Val;
3449 switch (getVariantKind(RelocStr)) {
3450 case MCSymbolRefExpr::VK_Mips_ABS_LO:
3451 // Get the 1st 16-bits.
3452 Val = MCE->getValue() & 0xffff;
3453 break;
3454 case MCSymbolRefExpr::VK_Mips_ABS_HI:
3455 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
3456 // 16 bits being negative.
3457 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
3458 break;
3459 case MCSymbolRefExpr::VK_Mips_HIGHER:
3460 // Get the 3rd 16-bits.
3461 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
3462 break;
3463 case MCSymbolRefExpr::VK_Mips_HIGHEST:
3464 // Get the 4th 16-bits.
3465 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
3466 break;
3467 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00003468 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00003469 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00003470 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003471 }
3472
Jack Carterb5cf5902013-04-17 00:18:04 +00003473 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003474 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00003475 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00003476 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003477 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003478 return Res;
3479 }
3480
3481 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00003482 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
3483
Sasa Stankovic06c47802014-04-03 10:37:45 +00003484 // Try to create target expression.
3485 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00003486 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003487
Jack Carterd0bd6422013-04-18 00:41:53 +00003488 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
3489 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003490 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003491 return Res;
3492 }
3493
3494 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003495 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003496 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00003497 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00003498 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003499 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003500 return Expr;
3501}
3502
3503bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
3504
3505 switch (Expr->getKind()) {
3506 case MCExpr::Constant:
3507 return true;
3508 case MCExpr::SymbolRef:
3509 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
3510 case MCExpr::Binary:
3511 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
3512 if (!isEvaluated(BE->getLHS()))
3513 return false;
3514 return isEvaluated(BE->getRHS());
3515 }
3516 case MCExpr::Unary:
3517 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003518 case MCExpr::Target:
3519 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003520 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003521 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00003522}
Jack Carterd0bd6422013-04-18 00:41:53 +00003523
Jack Carterb5cf5902013-04-17 00:18:04 +00003524bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003525 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003526 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00003527 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00003528 if (Tok.isNot(AsmToken::Identifier))
3529 return true;
3530
Yaron Keren075759a2015-03-30 15:42:36 +00003531 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00003532
Jack Carterd0bd6422013-04-18 00:41:53 +00003533 Parser.Lex(); // Eat the identifier.
3534 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003535 const MCExpr *IdVal;
3536 SMLoc EndLoc;
3537
3538 if (getLexer().getKind() == AsmToken::LParen) {
3539 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003540 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003541 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003542 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003543 const AsmToken &nextTok = Parser.getTok();
3544 if (nextTok.isNot(AsmToken::Identifier))
3545 return true;
3546 Str += "(%";
3547 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00003548 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00003549 if (getLexer().getKind() != AsmToken::LParen)
3550 return true;
3551 } else
3552 break;
3553 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003554 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00003555 return true;
3556
3557 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00003558 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003559
3560 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00003561 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003562
Jack Carterd0bd6422013-04-18 00:41:53 +00003563 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00003564 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003565}
3566
Jack Carterb4dbc172012-09-05 23:34:03 +00003567bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
3568 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003569 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00003570 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003571 if (ResTy == MatchOperand_Success) {
3572 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00003573 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003574 StartLoc = Operand.getStartLoc();
3575 EndLoc = Operand.getEndLoc();
3576
3577 // AFAIK, we only support numeric registers and named GPR's in CFI
3578 // directives.
3579 // Don't worry about eating tokens before failing. Using an unrecognised
3580 // register is a parse error.
3581 if (Operand.isGPRAsmReg()) {
3582 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003583 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003584 }
3585
3586 return (RegNo == (unsigned)-1);
3587 }
3588
3589 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00003590 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00003591}
3592
Jack Carterb5cf5902013-04-17 00:18:04 +00003593bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003594 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00003595 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003596 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003597 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00003598
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003599 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003600 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003601 ++NumOfLParen;
3602 }
Jack Carter873c7242013-01-12 01:03:14 +00003603
Jack Carterd0bd6422013-04-18 00:41:53 +00003604 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003605 default:
3606 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00003607 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00003608 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00003609 case AsmToken::Integer:
3610 case AsmToken::Minus:
3611 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00003612 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003613 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00003614 else
3615 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00003616 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00003617 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003618 break;
Jack Carter873c7242013-01-12 01:03:14 +00003619 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00003620 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003621 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003622 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003623}
3624
David Blaikie960ea3f2014-06-08 16:18:35 +00003625MipsAsmParser::OperandMatchResultTy
3626MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003627 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003628 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00003629 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00003630 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003631 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003632 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00003633 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00003634 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00003635
Jack Carterb5cf5902013-04-17 00:18:04 +00003636 if (getLexer().getKind() == AsmToken::LParen) {
3637 Parser.Lex();
3638 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003639 }
3640
Jack Carterb5cf5902013-04-17 00:18:04 +00003641 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003642 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00003643 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003644
Jack Carterd0bd6422013-04-18 00:41:53 +00003645 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003646 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003647 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003648 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003649 SMLoc E =
3650 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003651 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003652 return MatchOperand_Success;
3653 }
3654 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003655 SMLoc E =
3656 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00003657
Jack Carterd0bd6422013-04-18 00:41:53 +00003658 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003659 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00003660 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003661 S, E, *this);
3662 Operands.push_back(
3663 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003664 return MatchOperand_Success;
3665 }
3666 Error(Parser.getTok().getLoc(), "'(' expected");
3667 return MatchOperand_ParseFail;
3668 }
3669
Jack Carterd0bd6422013-04-18 00:41:53 +00003670 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003671 }
3672
Toma Tabacu13964452014-09-04 13:23:44 +00003673 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003674 if (Res != MatchOperand_Success)
3675 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003676
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003677 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003678 Error(Parser.getTok().getLoc(), "')' expected");
3679 return MatchOperand_ParseFail;
3680 }
3681
Jack Carter873c7242013-01-12 01:03:14 +00003682 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3683
Jack Carterd0bd6422013-04-18 00:41:53 +00003684 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003685
Craig Topper062a2ba2014-04-25 05:30:21 +00003686 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003687 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003688
Jack Carterd0bd6422013-04-18 00:41:53 +00003689 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00003690 std::unique_ptr<MipsOperand> op(
3691 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00003692 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003693 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003694 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00003695 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003696 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
3697 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003698 if (IdVal->evaluateAsAbsolute(Imm))
3699 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003700 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003701 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00003702 getContext());
3703 }
3704
David Blaikie960ea3f2014-06-08 16:18:35 +00003705 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003706 return MatchOperand_Success;
3707}
3708
David Blaikie960ea3f2014-06-08 16:18:35 +00003709bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003710 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00003711 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00003712 if (Sym) {
3713 SMLoc S = Parser.getTok().getLoc();
3714 const MCExpr *Expr;
3715 if (Sym->isVariable())
3716 Expr = Sym->getVariableValue();
3717 else
3718 return false;
3719 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003720 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00003721 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00003722 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003723 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003724 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00003725 if (ResTy == MatchOperand_Success) {
3726 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00003727 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00003728 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003729 llvm_unreachable("Should never ParseFail");
3730 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00003731 }
3732 } else if (Expr->getKind() == MCExpr::Constant) {
3733 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00003734 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00003735 Operands.push_back(
3736 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00003737 return true;
3738 }
3739 }
3740 return false;
3741}
Jack Carterd0bd6422013-04-18 00:41:53 +00003742
Jack Carter873c7242013-01-12 01:03:14 +00003743MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003744MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00003745 StringRef Identifier,
3746 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003747 int Index = matchCPURegisterName(Identifier);
3748 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003749 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003750 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3751 return MatchOperand_Success;
3752 }
3753
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003754 Index = matchHWRegsRegisterName(Identifier);
3755 if (Index != -1) {
3756 Operands.push_back(MipsOperand::createHWRegsReg(
3757 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3758 return MatchOperand_Success;
3759 }
3760
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003761 Index = matchFPURegisterName(Identifier);
3762 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003763 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003764 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3765 return MatchOperand_Success;
3766 }
3767
3768 Index = matchFCCRegisterName(Identifier);
3769 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003770 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003771 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3772 return MatchOperand_Success;
3773 }
3774
3775 Index = matchACRegisterName(Identifier);
3776 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003777 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003778 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3779 return MatchOperand_Success;
3780 }
3781
3782 Index = matchMSA128RegisterName(Identifier);
3783 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003784 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003785 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3786 return MatchOperand_Success;
3787 }
3788
3789 Index = matchMSA128CtrlRegisterName(Identifier);
3790 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003791 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003792 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3793 return MatchOperand_Success;
3794 }
3795
3796 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00003797}
3798
3799MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003800MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003801 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00003802 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003803
3804 if (Token.is(AsmToken::Identifier)) {
3805 DEBUG(dbgs() << ".. identifier\n");
3806 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00003807 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003808 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00003809 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003810 } else if (Token.is(AsmToken::Integer)) {
3811 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003812 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003813 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
3814 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003815 return MatchOperand_Success;
3816 }
3817
3818 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
3819
3820 return MatchOperand_NoMatch;
3821}
3822
David Blaikie960ea3f2014-06-08 16:18:35 +00003823MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003824MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003825 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003826 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003827
3828 auto Token = Parser.getTok();
3829
3830 SMLoc S = Token.getLoc();
3831
3832 if (Token.isNot(AsmToken::Dollar)) {
3833 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
3834 if (Token.is(AsmToken::Identifier)) {
3835 if (searchSymbolAlias(Operands))
3836 return MatchOperand_Success;
3837 }
3838 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
3839 return MatchOperand_NoMatch;
3840 }
3841 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003842
Toma Tabacu13964452014-09-04 13:23:44 +00003843 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00003844 if (ResTy == MatchOperand_Success) {
3845 Parser.Lex(); // $
3846 Parser.Lex(); // identifier
3847 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003848 return ResTy;
3849}
3850
3851MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003852MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003853 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003854 switch (getLexer().getKind()) {
3855 default:
3856 return MatchOperand_NoMatch;
3857 case AsmToken::LParen:
3858 case AsmToken::Minus:
3859 case AsmToken::Plus:
3860 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003861 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003862 case AsmToken::String:
3863 break;
3864 }
3865
3866 const MCExpr *IdVal;
3867 SMLoc S = Parser.getTok().getLoc();
3868 if (getParser().parseExpression(IdVal))
3869 return MatchOperand_ParseFail;
3870
3871 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3872 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
3873 return MatchOperand_Success;
3874}
3875
David Blaikie960ea3f2014-06-08 16:18:35 +00003876MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003877MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003878 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003879 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003880
3881 SMLoc S = getLexer().getLoc();
3882
3883 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00003884 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003885 if (ResTy != MatchOperand_NoMatch)
3886 return ResTy;
3887
Daniel Sanders315386c2014-04-01 10:40:14 +00003888 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00003889 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00003890 if (ResTy != MatchOperand_NoMatch)
3891 return ResTy;
3892
Daniel Sandersffd84362014-04-01 10:41:48 +00003893 const MCExpr *Expr = nullptr;
3894 if (Parser.parseExpression(Expr)) {
3895 // We have no way of knowing if a symbol was consumed so we must ParseFail
3896 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003897 }
Daniel Sandersffd84362014-04-01 10:41:48 +00003898 Operands.push_back(
3899 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003900 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00003901}
3902
Vladimir Medic2b953d02013-10-01 09:48:56 +00003903MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00003904MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003905 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00003906 const MCExpr *IdVal;
3907 // If the first token is '$' we may have register operand.
3908 if (Parser.getTok().is(AsmToken::Dollar))
3909 return MatchOperand_NoMatch;
3910 SMLoc S = Parser.getTok().getLoc();
3911 if (getParser().parseExpression(IdVal))
3912 return MatchOperand_ParseFail;
3913 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00003914 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00003915 int64_t Val = MCE->getValue();
3916 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3917 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003918 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00003919 return MatchOperand_Success;
3920}
3921
Matheus Almeida779c5932013-11-18 12:32:49 +00003922MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003923MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003924 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00003925 switch (getLexer().getKind()) {
3926 default:
3927 return MatchOperand_NoMatch;
3928 case AsmToken::LParen:
3929 case AsmToken::Plus:
3930 case AsmToken::Minus:
3931 case AsmToken::Integer:
3932 break;
3933 }
3934
3935 const MCExpr *Expr;
3936 SMLoc S = Parser.getTok().getLoc();
3937
3938 if (getParser().parseExpression(Expr))
3939 return MatchOperand_ParseFail;
3940
3941 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003942 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00003943 Error(S, "expected immediate value");
3944 return MatchOperand_ParseFail;
3945 }
3946
3947 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
3948 // and because the CPU always adds one to the immediate field, the allowed
3949 // range becomes 1..4. We'll only check the range here and will deal
3950 // with the addition/subtraction when actually decoding/encoding
3951 // the instruction.
3952 if (Val < 1 || Val > 4) {
3953 Error(S, "immediate not in range (1..4)");
3954 return MatchOperand_ParseFail;
3955 }
3956
Jack Carter3b2c96e2014-01-22 23:31:38 +00003957 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003958 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00003959 return MatchOperand_Success;
3960}
3961
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00003962MipsAsmParser::OperandMatchResultTy
3963MipsAsmParser::parseRegisterList(OperandVector &Operands) {
3964 MCAsmParser &Parser = getParser();
3965 SmallVector<unsigned, 10> Regs;
3966 unsigned RegNo;
3967 unsigned PrevReg = Mips::NoRegister;
3968 bool RegRange = false;
3969 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3970
3971 if (Parser.getTok().isNot(AsmToken::Dollar))
3972 return MatchOperand_ParseFail;
3973
3974 SMLoc S = Parser.getTok().getLoc();
3975 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
3976 SMLoc E = getLexer().getLoc();
3977 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
3978 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
3979 if (RegRange) {
3980 // Remove last register operand because registers from register range
3981 // should be inserted first.
3982 if (RegNo == Mips::RA) {
3983 Regs.push_back(RegNo);
3984 } else {
3985 unsigned TmpReg = PrevReg + 1;
3986 while (TmpReg <= RegNo) {
3987 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
3988 Error(E, "invalid register operand");
3989 return MatchOperand_ParseFail;
3990 }
3991
3992 PrevReg = TmpReg;
3993 Regs.push_back(TmpReg++);
3994 }
3995 }
3996
3997 RegRange = false;
3998 } else {
3999 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
4000 (RegNo != Mips::RA)) {
4001 Error(E, "$16 or $31 expected");
4002 return MatchOperand_ParseFail;
4003 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
4004 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
4005 Error(E, "invalid register operand");
4006 return MatchOperand_ParseFail;
4007 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
4008 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
4009 Error(E, "consecutive register numbers expected");
4010 return MatchOperand_ParseFail;
4011 }
4012
4013 Regs.push_back(RegNo);
4014 }
4015
4016 if (Parser.getTok().is(AsmToken::Minus))
4017 RegRange = true;
4018
4019 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4020 !Parser.getTok().isNot(AsmToken::Comma)) {
4021 Error(E, "',' or '-' expected");
4022 return MatchOperand_ParseFail;
4023 }
4024
4025 Lex(); // Consume comma or minus
4026 if (Parser.getTok().isNot(AsmToken::Dollar))
4027 break;
4028
4029 PrevReg = RegNo;
4030 }
4031
4032 SMLoc E = Parser.getTok().getLoc();
4033 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4034 parseMemOperand(Operands);
4035 return MatchOperand_Success;
4036}
4037
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004038MipsAsmParser::OperandMatchResultTy
4039MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4040 MCAsmParser &Parser = getParser();
4041
4042 SMLoc S = Parser.getTok().getLoc();
4043 if (parseAnyRegister(Operands) != MatchOperand_Success)
4044 return MatchOperand_ParseFail;
4045
4046 SMLoc E = Parser.getTok().getLoc();
4047 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
4048 unsigned Reg = Op.getGPR32Reg();
4049 Operands.pop_back();
4050 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
4051 return MatchOperand_Success;
4052}
4053
Zoran Jovanovic41688672015-02-10 16:36:20 +00004054MipsAsmParser::OperandMatchResultTy
4055MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4056 MCAsmParser &Parser = getParser();
4057 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4058 SmallVector<unsigned, 10> Regs;
4059
4060 if (Parser.getTok().isNot(AsmToken::Dollar))
4061 return MatchOperand_ParseFail;
4062
4063 SMLoc S = Parser.getTok().getLoc();
4064
4065 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4066 return MatchOperand_ParseFail;
4067
4068 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4069 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4070 Regs.push_back(RegNo);
4071
4072 SMLoc E = Parser.getTok().getLoc();
4073 if (Parser.getTok().isNot(AsmToken::Comma)) {
4074 Error(E, "',' expected");
4075 return MatchOperand_ParseFail;
4076 }
4077
4078 // Remove comma.
4079 Parser.Lex();
4080
4081 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4082 return MatchOperand_ParseFail;
4083
4084 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4085 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4086 Regs.push_back(RegNo);
4087
4088 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4089
4090 return MatchOperand_Success;
4091}
4092
Jack Carterdc1e35d2012-09-06 20:00:02 +00004093MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
4094
Vladimir Medic4c299852013-11-06 11:27:05 +00004095 MCSymbolRefExpr::VariantKind VK =
4096 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
4097 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
4098 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
4099 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
4100 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
4101 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
4102 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
4103 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
4104 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
4105 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
4106 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
4107 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
4108 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
4109 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
4110 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
4111 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
4112 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
4113 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00004114 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
4115 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
4116 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
4117 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
4118 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
4119 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00004120 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
4121 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00004122 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004123
Matheus Almeida2852af82014-04-22 10:15:54 +00004124 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00004125
Jack Carterdc1e35d2012-09-06 20:00:02 +00004126 return VK;
4127}
Jack Cartera63b16a2012-09-07 00:23:42 +00004128
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004129/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4130/// either this.
4131/// ::= '(', register, ')'
4132/// handle it before we iterate so we don't get tripped up by the lack of
4133/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004134bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004135 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004136 if (getLexer().is(AsmToken::LParen)) {
4137 Operands.push_back(
4138 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4139 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004140 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004141 SMLoc Loc = getLexer().getLoc();
4142 Parser.eatToEndOfStatement();
4143 return Error(Loc, "unexpected token in argument list");
4144 }
4145 if (Parser.getTok().isNot(AsmToken::RParen)) {
4146 SMLoc Loc = getLexer().getLoc();
4147 Parser.eatToEndOfStatement();
4148 return Error(Loc, "unexpected token, expected ')'");
4149 }
4150 Operands.push_back(
4151 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4152 Parser.Lex();
4153 }
4154 return false;
4155}
4156
4157/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4158/// either one of these.
4159/// ::= '[', register, ']'
4160/// ::= '[', integer, ']'
4161/// handle it before we iterate so we don't get tripped up by the lack of
4162/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004163bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004164 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004165 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004166 if (getLexer().is(AsmToken::LBrac)) {
4167 Operands.push_back(
4168 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4169 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004170 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004171 SMLoc Loc = getLexer().getLoc();
4172 Parser.eatToEndOfStatement();
4173 return Error(Loc, "unexpected token in argument list");
4174 }
4175 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4176 SMLoc Loc = getLexer().getLoc();
4177 Parser.eatToEndOfStatement();
4178 return Error(Loc, "unexpected token, expected ']'");
4179 }
4180 Operands.push_back(
4181 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4182 Parser.Lex();
4183 }
4184 return false;
4185}
4186
David Blaikie960ea3f2014-06-08 16:18:35 +00004187bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4188 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004189 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004190 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004191
4192 // We have reached first instruction, module directive are now forbidden.
4193 getTargetStreamer().forbidModuleDirective();
4194
Vladimir Medic74593e62013-07-17 15:00:42 +00004195 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004196 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004197 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004198 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004199 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004200 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004201 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004202
4203 // Read the remaining operands.
4204 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4205 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004206 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004207 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004208 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004209 return Error(Loc, "unexpected token in argument list");
4210 }
Toma Tabacu13964452014-09-04 13:23:44 +00004211 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004212 return true;
4213 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004214
Jack Carterd0bd6422013-04-18 00:41:53 +00004215 while (getLexer().is(AsmToken::Comma)) {
4216 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004217 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004218 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004219 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004220 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004221 return Error(Loc, "unexpected token in argument list");
4222 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004223 // Parse bracket and parenthesis suffixes before we iterate
4224 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004225 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004226 return true;
4227 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004228 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004229 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004230 }
4231 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004232 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4233 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004234 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004235 return Error(Loc, "unexpected token in argument list");
4236 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004237 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004238 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004239}
4240
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004241bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004242 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004243 SMLoc Loc = getLexer().getLoc();
4244 Parser.eatToEndOfStatement();
4245 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004246}
4247
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004248bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004249 return Error(Loc, ErrorMsg);
4250}
4251
Jack Carter0b744b32012-10-04 02:29:46 +00004252bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004253 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004254 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004255
4256 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004257 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004258
4259 Parser.Lex(); // Eat "noat".
4260
Jack Carterd0bd6422013-04-18 00:41:53 +00004261 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004262 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004263 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004264 return false;
4265 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004266
4267 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004268 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004269 return false;
4270}
Jack Carterd0bd6422013-04-18 00:41:53 +00004271
Jack Carter0b744b32012-10-04 02:29:46 +00004272bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004273 // Line can be: ".set at", which sets $at to $1
4274 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004275 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004276 Parser.Lex(); // Eat "at".
4277
Jack Carter0b744b32012-10-04 02:29:46 +00004278 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004279 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004280 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004281
4282 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004283 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004284 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004285 }
4286
4287 if (getLexer().isNot(AsmToken::Equal)) {
4288 reportParseError("unexpected token, expected equals sign");
4289 return false;
4290 }
4291 Parser.Lex(); // Eat "=".
4292
4293 if (getLexer().isNot(AsmToken::Dollar)) {
4294 if (getLexer().is(AsmToken::EndOfStatement)) {
4295 reportParseError("no register specified");
4296 return false;
4297 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004298 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004299 return false;
4300 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004301 }
4302 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004303
Toma Tabacu16a74492015-02-13 10:30:57 +00004304 // Find out what "reg" is.
4305 unsigned AtRegNo;
4306 const AsmToken &Reg = Parser.getTok();
4307 if (Reg.is(AsmToken::Identifier)) {
4308 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4309 } else if (Reg.is(AsmToken::Integer)) {
4310 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004311 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004312 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004313 return false;
4314 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004315
4316 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004317 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004318 reportParseError("invalid register");
4319 return false;
4320 }
4321 Parser.Lex(); // Eat "reg".
4322
4323 // If this is not the end of the statement, report an error.
4324 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4325 reportParseError("unexpected token, expected end of statement");
4326 return false;
4327 }
4328
4329 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4330
4331 Parser.Lex(); // Consume the EndOfStatement.
4332 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004333}
4334
4335bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004336 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004337 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004338 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004339 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004340 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004341 return false;
4342 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004343 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004344 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004345 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004346 return false;
4347}
4348
4349bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004350 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004351 Parser.Lex();
4352 // If this is not the end of the statement, report an error.
4353 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004354 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004355 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00004356 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004357 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00004358 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004359 Parser.Lex(); // Consume the EndOfStatement.
4360 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004361}
4362
4363bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004364 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004365 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004366 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004367 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004368 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004369 return false;
4370 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004371 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004372 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004373 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004374 return false;
4375}
4376
4377bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004378 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004379 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004380 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004381 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004382 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004383 return false;
4384 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004385 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00004386 reportParseError("`noreorder' must be set before `nomacro'");
4387 return false;
4388 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004389 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004390 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004391 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004392 return false;
4393}
Jack Carterd76b2372013-03-21 21:44:16 +00004394
Daniel Sanders44934432014-08-07 12:03:36 +00004395bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004396 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004397 Parser.Lex();
4398
4399 // If this is not the end of the statement, report an error.
4400 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004401 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004402
4403 setFeatureBits(Mips::FeatureMSA, "msa");
4404 getTargetStreamer().emitDirectiveSetMsa();
4405 return false;
4406}
4407
4408bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004409 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004410 Parser.Lex();
4411
4412 // If this is not the end of the statement, report an error.
4413 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004414 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004415
4416 clearFeatureBits(Mips::FeatureMSA, "msa");
4417 getTargetStreamer().emitDirectiveSetNoMsa();
4418 return false;
4419}
4420
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004421bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004422 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004423 Parser.Lex(); // Eat "nodsp".
4424
4425 // If this is not the end of the statement, report an error.
4426 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4427 reportParseError("unexpected token, expected end of statement");
4428 return false;
4429 }
4430
4431 clearFeatureBits(Mips::FeatureDSP, "dsp");
4432 getTargetStreamer().emitDirectiveSetNoDsp();
4433 return false;
4434}
4435
Toma Tabacucc2502d2014-11-04 17:18:07 +00004436bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004437 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004438 Parser.Lex(); // Eat "mips16".
4439
Jack Carter39536722014-01-22 23:08:42 +00004440 // If this is not the end of the statement, report an error.
4441 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004442 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00004443 return false;
4444 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00004445
4446 setFeatureBits(Mips::FeatureMips16, "mips16");
4447 getTargetStreamer().emitDirectiveSetMips16();
4448 Parser.Lex(); // Consume the EndOfStatement.
4449 return false;
4450}
4451
4452bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004453 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004454 Parser.Lex(); // Eat "nomips16".
4455
4456 // If this is not the end of the statement, report an error.
4457 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4458 reportParseError("unexpected token, expected end of statement");
4459 return false;
4460 }
4461
4462 clearFeatureBits(Mips::FeatureMips16, "mips16");
4463 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00004464 Parser.Lex(); // Consume the EndOfStatement.
4465 return false;
4466}
4467
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004468bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004469 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004470 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004471 // Line can be: .set fp=32
4472 // .set fp=xx
4473 // .set fp=64
4474 Parser.Lex(); // Eat fp token
4475 AsmToken Tok = Parser.getTok();
4476 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004477 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004478 return false;
4479 }
4480 Parser.Lex(); // Eat '=' token.
4481 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004482
4483 if (!parseFpABIValue(FpAbiVal, ".set"))
4484 return false;
4485
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004486 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004487 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004488 return false;
4489 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004490 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004491 Parser.Lex(); // Consume the EndOfStatement.
4492 return false;
4493}
4494
Toma Tabacu32c72aa2015-06-30 09:36:50 +00004495bool MipsAsmParser::parseSetOddSPRegDirective() {
4496 MCAsmParser &Parser = getParser();
4497
4498 Parser.Lex(); // Eat "oddspreg".
4499 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4500 reportParseError("unexpected token, expected end of statement");
4501 return false;
4502 }
4503
4504 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4505 getTargetStreamer().emitDirectiveSetOddSPReg();
4506 return false;
4507}
4508
4509bool MipsAsmParser::parseSetNoOddSPRegDirective() {
4510 MCAsmParser &Parser = getParser();
4511
4512 Parser.Lex(); // Eat "nooddspreg".
4513 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4514 reportParseError("unexpected token, expected end of statement");
4515 return false;
4516 }
4517
4518 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4519 getTargetStreamer().emitDirectiveSetNoOddSPReg();
4520 return false;
4521}
4522
Toma Tabacu9db22db2014-09-09 10:15:38 +00004523bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004524 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004525 SMLoc Loc = getLexer().getLoc();
4526
4527 Parser.Lex();
4528 if (getLexer().isNot(AsmToken::EndOfStatement))
4529 return reportParseError("unexpected token, expected end of statement");
4530
4531 // Always keep an element on the options "stack" to prevent the user
4532 // from changing the initial options. This is how we remember them.
4533 if (AssemblerOptions.size() == 2)
4534 return reportParseError(Loc, ".set pop with no .set push");
4535
4536 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00004537 setAvailableFeatures(
4538 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
4539 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00004540
4541 getTargetStreamer().emitDirectiveSetPop();
4542 return false;
4543}
4544
4545bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004546 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004547 Parser.Lex();
4548 if (getLexer().isNot(AsmToken::EndOfStatement))
4549 return reportParseError("unexpected token, expected end of statement");
4550
4551 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00004552 AssemblerOptions.push_back(
4553 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00004554
4555 getTargetStreamer().emitDirectiveSetPush();
4556 return false;
4557}
4558
Toma Tabacu29696502015-06-02 09:48:04 +00004559bool MipsAsmParser::parseSetSoftFloatDirective() {
4560 MCAsmParser &Parser = getParser();
4561 Parser.Lex();
4562 if (getLexer().isNot(AsmToken::EndOfStatement))
4563 return reportParseError("unexpected token, expected end of statement");
4564
4565 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4566 getTargetStreamer().emitDirectiveSetSoftFloat();
4567 return false;
4568}
4569
4570bool MipsAsmParser::parseSetHardFloatDirective() {
4571 MCAsmParser &Parser = getParser();
4572 Parser.Lex();
4573 if (getLexer().isNot(AsmToken::EndOfStatement))
4574 return reportParseError("unexpected token, expected end of statement");
4575
4576 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4577 getTargetStreamer().emitDirectiveSetHardFloat();
4578 return false;
4579}
4580
Jack Carterd76b2372013-03-21 21:44:16 +00004581bool MipsAsmParser::parseSetAssignment() {
4582 StringRef Name;
4583 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00004584 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00004585
4586 if (Parser.parseIdentifier(Name))
4587 reportParseError("expected identifier after .set");
4588
4589 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004590 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00004591 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00004592
Jack Carter3b2c96e2014-01-22 23:31:38 +00004593 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00004594 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00004595
Jim Grosbach6f482002015-05-18 18:43:14 +00004596 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00004597 Sym->setVariableValue(Value);
4598
4599 return false;
4600}
Jack Carterd0bd6422013-04-18 00:41:53 +00004601
Toma Tabacu26647792014-09-09 12:52:14 +00004602bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004603 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00004604 Parser.Lex();
4605 if (getLexer().isNot(AsmToken::EndOfStatement))
4606 return reportParseError("unexpected token, expected end of statement");
4607
4608 // Reset assembler options to their initial values.
Toma Tabacu465acfd2015-06-09 13:33:26 +00004609 setAvailableFeatures(
4610 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
4611 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00004612 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
4613
4614 getTargetStreamer().emitDirectiveSetMips0();
4615 return false;
4616}
4617
Toma Tabacu85618b32014-08-19 14:22:52 +00004618bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004619 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00004620 Parser.Lex();
4621 if (getLexer().isNot(AsmToken::Equal))
4622 return reportParseError("unexpected token, expected equals sign");
4623
4624 Parser.Lex();
4625 StringRef Arch;
4626 if (Parser.parseIdentifier(Arch))
4627 return reportParseError("expected arch identifier");
4628
4629 StringRef ArchFeatureName =
4630 StringSwitch<StringRef>(Arch)
4631 .Case("mips1", "mips1")
4632 .Case("mips2", "mips2")
4633 .Case("mips3", "mips3")
4634 .Case("mips4", "mips4")
4635 .Case("mips5", "mips5")
4636 .Case("mips32", "mips32")
4637 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004638 .Case("mips32r3", "mips32r3")
4639 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004640 .Case("mips32r6", "mips32r6")
4641 .Case("mips64", "mips64")
4642 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004643 .Case("mips64r3", "mips64r3")
4644 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004645 .Case("mips64r6", "mips64r6")
4646 .Case("cnmips", "cnmips")
4647 .Case("r4000", "mips3") // This is an implementation of Mips3.
4648 .Default("");
4649
4650 if (ArchFeatureName.empty())
4651 return reportParseError("unsupported architecture");
4652
4653 selectArch(ArchFeatureName);
4654 getTargetStreamer().emitDirectiveSetArch(Arch);
4655 return false;
4656}
4657
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004658bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004659 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004660 Parser.Lex();
4661 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004662 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004663
Matheus Almeida2852af82014-04-22 10:15:54 +00004664 switch (Feature) {
4665 default:
4666 llvm_unreachable("Unimplemented feature");
4667 case Mips::FeatureDSP:
4668 setFeatureBits(Mips::FeatureDSP, "dsp");
4669 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004670 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004671 case Mips::FeatureMicroMips:
4672 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004673 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004674 case Mips::FeatureMips1:
4675 selectArch("mips1");
4676 getTargetStreamer().emitDirectiveSetMips1();
4677 break;
4678 case Mips::FeatureMips2:
4679 selectArch("mips2");
4680 getTargetStreamer().emitDirectiveSetMips2();
4681 break;
4682 case Mips::FeatureMips3:
4683 selectArch("mips3");
4684 getTargetStreamer().emitDirectiveSetMips3();
4685 break;
4686 case Mips::FeatureMips4:
4687 selectArch("mips4");
4688 getTargetStreamer().emitDirectiveSetMips4();
4689 break;
4690 case Mips::FeatureMips5:
4691 selectArch("mips5");
4692 getTargetStreamer().emitDirectiveSetMips5();
4693 break;
4694 case Mips::FeatureMips32:
4695 selectArch("mips32");
4696 getTargetStreamer().emitDirectiveSetMips32();
4697 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004698 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004699 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004700 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004701 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004702 case Mips::FeatureMips32r3:
4703 selectArch("mips32r3");
4704 getTargetStreamer().emitDirectiveSetMips32R3();
4705 break;
4706 case Mips::FeatureMips32r5:
4707 selectArch("mips32r5");
4708 getTargetStreamer().emitDirectiveSetMips32R5();
4709 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004710 case Mips::FeatureMips32r6:
4711 selectArch("mips32r6");
4712 getTargetStreamer().emitDirectiveSetMips32R6();
4713 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004714 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004715 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00004716 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00004717 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004718 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004719 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004720 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00004721 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004722 case Mips::FeatureMips64r3:
4723 selectArch("mips64r3");
4724 getTargetStreamer().emitDirectiveSetMips64R3();
4725 break;
4726 case Mips::FeatureMips64r5:
4727 selectArch("mips64r5");
4728 getTargetStreamer().emitDirectiveSetMips64R5();
4729 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004730 case Mips::FeatureMips64r6:
4731 selectArch("mips64r6");
4732 getTargetStreamer().emitDirectiveSetMips64R6();
4733 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004734 }
4735 return false;
4736}
4737
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004738bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004739 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004740 if (getLexer().isNot(AsmToken::Comma)) {
4741 SMLoc Loc = getLexer().getLoc();
4742 Parser.eatToEndOfStatement();
4743 return Error(Loc, ErrorStr);
4744 }
4745
Matheus Almeida2852af82014-04-22 10:15:54 +00004746 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004747 return true;
4748}
4749
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004750bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00004751 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00004752 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004753
Toma Tabacudde4c462014-11-06 10:02:45 +00004754 if (inMips16Mode()) {
4755 reportParseError(".cpload is not supported in Mips16 mode");
4756 return false;
4757 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004758
David Blaikie960ea3f2014-06-08 16:18:35 +00004759 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00004760 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004761 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4762 reportParseError("expected register containing function address");
4763 return false;
4764 }
4765
David Blaikie960ea3f2014-06-08 16:18:35 +00004766 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
4767 if (!RegOpnd.isGPRAsmReg()) {
4768 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004769 return false;
4770 }
4771
Toma Tabacudde4c462014-11-06 10:02:45 +00004772 // If this is not the end of the statement, report an error.
4773 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4774 reportParseError("unexpected token, expected end of statement");
4775 return false;
4776 }
4777
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004778 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004779 return false;
4780}
4781
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004782bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004783 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004784 unsigned FuncReg;
4785 unsigned Save;
4786 bool SaveIsReg = true;
4787
Matheus Almeida7e815762014-06-18 13:08:59 +00004788 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004789 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00004790 if (ResTy == MatchOperand_NoMatch) {
4791 reportParseError("expected register containing function address");
4792 Parser.eatToEndOfStatement();
4793 return false;
4794 }
4795
4796 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4797 if (!FuncRegOpnd.isGPRAsmReg()) {
4798 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
4799 Parser.eatToEndOfStatement();
4800 return false;
4801 }
4802
4803 FuncReg = FuncRegOpnd.getGPR32Reg();
4804 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004805
Toma Tabacu65f10572014-09-16 15:00:52 +00004806 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004807 return true;
4808
Toma Tabacu13964452014-09-04 13:23:44 +00004809 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00004810 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004811 const AsmToken &Tok = Parser.getTok();
4812 if (Tok.is(AsmToken::Integer)) {
4813 Save = Tok.getIntVal();
4814 SaveIsReg = false;
4815 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00004816 } else {
4817 reportParseError("expected save register or stack offset");
4818 Parser.eatToEndOfStatement();
4819 return false;
4820 }
4821 } else {
4822 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4823 if (!SaveOpnd.isGPRAsmReg()) {
4824 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
4825 Parser.eatToEndOfStatement();
4826 return false;
4827 }
4828 Save = SaveOpnd.getGPR32Reg();
4829 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004830
Toma Tabacu65f10572014-09-16 15:00:52 +00004831 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004832 return true;
4833
Toma Tabacu8874eac2015-02-18 13:46:53 +00004834 const MCExpr *Expr;
4835 if (Parser.parseExpression(Expr)) {
4836 reportParseError("expected expression");
4837 return false;
4838 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004839
Toma Tabacu8874eac2015-02-18 13:46:53 +00004840 if (Expr->getKind() != MCExpr::SymbolRef) {
4841 reportParseError("expected symbol");
4842 return false;
4843 }
4844 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
4845
4846 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
4847 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004848 return false;
4849}
4850
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004851bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004852 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004853 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4854 const AsmToken &Tok = Parser.getTok();
4855
4856 if (Tok.getString() == "2008") {
4857 Parser.Lex();
4858 getTargetStreamer().emitDirectiveNaN2008();
4859 return false;
4860 } else if (Tok.getString() == "legacy") {
4861 Parser.Lex();
4862 getTargetStreamer().emitDirectiveNaNLegacy();
4863 return false;
4864 }
4865 }
4866 // If we don't recognize the option passed to the .nan
4867 // directive (e.g. no option or unknown option), emit an error.
4868 reportParseError("invalid option in .nan directive");
4869 return false;
4870}
4871
Jack Carter0b744b32012-10-04 02:29:46 +00004872bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004873 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004874 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00004875 const AsmToken &Tok = Parser.getTok();
4876
4877 if (Tok.getString() == "noat") {
4878 return parseSetNoAtDirective();
4879 } else if (Tok.getString() == "at") {
4880 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00004881 } else if (Tok.getString() == "arch") {
4882 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004883 } else if (Tok.getString() == "fp") {
4884 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00004885 } else if (Tok.getString() == "oddspreg") {
4886 return parseSetOddSPRegDirective();
4887 } else if (Tok.getString() == "nooddspreg") {
4888 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004889 } else if (Tok.getString() == "pop") {
4890 return parseSetPopDirective();
4891 } else if (Tok.getString() == "push") {
4892 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00004893 } else if (Tok.getString() == "reorder") {
4894 return parseSetReorderDirective();
4895 } else if (Tok.getString() == "noreorder") {
4896 return parseSetNoReorderDirective();
4897 } else if (Tok.getString() == "macro") {
4898 return parseSetMacroDirective();
4899 } else if (Tok.getString() == "nomacro") {
4900 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00004901 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00004902 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00004903 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00004904 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00004905 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00004906 getTargetStreamer().emitDirectiveSetNoMicroMips();
4907 Parser.eatToEndOfStatement();
4908 return false;
4909 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004910 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00004911 } else if (Tok.getString() == "mips0") {
4912 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00004913 } else if (Tok.getString() == "mips1") {
4914 return parseSetFeature(Mips::FeatureMips1);
4915 } else if (Tok.getString() == "mips2") {
4916 return parseSetFeature(Mips::FeatureMips2);
4917 } else if (Tok.getString() == "mips3") {
4918 return parseSetFeature(Mips::FeatureMips3);
4919 } else if (Tok.getString() == "mips4") {
4920 return parseSetFeature(Mips::FeatureMips4);
4921 } else if (Tok.getString() == "mips5") {
4922 return parseSetFeature(Mips::FeatureMips5);
4923 } else if (Tok.getString() == "mips32") {
4924 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00004925 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004926 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00004927 } else if (Tok.getString() == "mips32r3") {
4928 return parseSetFeature(Mips::FeatureMips32r3);
4929 } else if (Tok.getString() == "mips32r5") {
4930 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00004931 } else if (Tok.getString() == "mips32r6") {
4932 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00004933 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004934 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00004935 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004936 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00004937 } else if (Tok.getString() == "mips64r3") {
4938 return parseSetFeature(Mips::FeatureMips64r3);
4939 } else if (Tok.getString() == "mips64r5") {
4940 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00004941 } else if (Tok.getString() == "mips64r6") {
4942 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00004943 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004944 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004945 } else if (Tok.getString() == "nodsp") {
4946 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00004947 } else if (Tok.getString() == "msa") {
4948 return parseSetMsaDirective();
4949 } else if (Tok.getString() == "nomsa") {
4950 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00004951 } else if (Tok.getString() == "softfloat") {
4952 return parseSetSoftFloatDirective();
4953 } else if (Tok.getString() == "hardfloat") {
4954 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00004955 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00004956 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00004957 parseSetAssignment();
4958 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004959 }
Jack Carter07c818d2013-01-25 01:31:34 +00004960
Jack Carter0b744b32012-10-04 02:29:46 +00004961 return true;
4962}
4963
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004964/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00004965/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004966bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004967 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004968 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4969 for (;;) {
4970 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004971 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00004972 return true;
4973
4974 getParser().getStreamer().EmitValue(Value, Size);
4975
4976 if (getLexer().is(AsmToken::EndOfStatement))
4977 break;
4978
Jack Carter07c818d2013-01-25 01:31:34 +00004979 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004980 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00004981 Parser.Lex();
4982 }
4983 }
4984
4985 Parser.Lex();
4986 return false;
4987}
4988
Vladimir Medic4c299852013-11-06 11:27:05 +00004989/// parseDirectiveGpWord
4990/// ::= .gpword local_sym
4991bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004992 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004993 const MCExpr *Value;
4994 // EmitGPRel32Value requires an expression, so we are using base class
4995 // method to evaluate the expression.
4996 if (getParser().parseExpression(Value))
4997 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00004998 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00004999
Vladimir Medice10c1122013-11-13 13:18:04 +00005000 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005001 return Error(getLexer().getLoc(),
5002 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005003 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005004 return false;
5005}
5006
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005007/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005008/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005009bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005010 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005011 const MCExpr *Value;
5012 // EmitGPRel64Value requires an expression, so we are using base class
5013 // method to evaluate the expression.
5014 if (getParser().parseExpression(Value))
5015 return true;
5016 getParser().getStreamer().EmitGPRel64Value(Value);
5017
5018 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005019 return Error(getLexer().getLoc(),
5020 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005021 Parser.Lex(); // Eat EndOfStatement token.
5022 return false;
5023}
5024
Jack Carter0cd3c192014-01-06 23:27:31 +00005025bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005026 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005027 // Get the option token.
5028 AsmToken Tok = Parser.getTok();
5029 // At the moment only identifiers are supported.
5030 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005031 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005032 Parser.eatToEndOfStatement();
5033 return false;
5034 }
5035
5036 StringRef Option = Tok.getIdentifier();
5037
5038 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005039 // MipsAsmParser needs to know if the current PIC mode changes.
5040 IsPicEnabled = false;
5041
Jack Carter0cd3c192014-01-06 23:27:31 +00005042 getTargetStreamer().emitDirectiveOptionPic0();
5043 Parser.Lex();
5044 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5045 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005046 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005047 Parser.eatToEndOfStatement();
5048 }
5049 return false;
5050 }
5051
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005052 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005053 // MipsAsmParser needs to know if the current PIC mode changes.
5054 IsPicEnabled = true;
5055
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005056 getTargetStreamer().emitDirectiveOptionPic2();
5057 Parser.Lex();
5058 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5059 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005060 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005061 Parser.eatToEndOfStatement();
5062 }
5063 return false;
5064 }
5065
Jack Carter0cd3c192014-01-06 23:27:31 +00005066 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005067 Warning(Parser.getTok().getLoc(),
5068 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005069 Parser.eatToEndOfStatement();
5070 return false;
5071}
5072
Toma Tabacu9ca50962015-04-16 09:53:47 +00005073/// parseInsnDirective
5074/// ::= .insn
5075bool MipsAsmParser::parseInsnDirective() {
5076 // If this is not the end of the statement, report an error.
5077 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5078 reportParseError("unexpected token, expected end of statement");
5079 return false;
5080 }
5081
5082 // The actual label marking happens in
5083 // MipsELFStreamer::createPendingLabelRelocs().
5084 getTargetStreamer().emitDirectiveInsn();
5085
5086 getParser().Lex(); // Eat EndOfStatement token.
5087 return false;
5088}
5089
Daniel Sanders7e527422014-07-10 13:38:23 +00005090/// parseDirectiveModule
5091/// ::= .module oddspreg
5092/// ::= .module nooddspreg
5093/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005094/// ::= .module softfloat
5095/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005096bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005097 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005098 MCAsmLexer &Lexer = getLexer();
5099 SMLoc L = Lexer.getLoc();
5100
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005101 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005102 // TODO : get a better message.
5103 reportParseError(".module directive must appear before any code");
5104 return false;
5105 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005106
Toma Tabacuc405c822015-01-23 10:40:19 +00005107 StringRef Option;
5108 if (Parser.parseIdentifier(Option)) {
5109 reportParseError("expected .module option identifier");
5110 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005111 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005112
Toma Tabacuc405c822015-01-23 10:40:19 +00005113 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005114 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005115
Toma Tabacu3c499582015-06-25 10:56:57 +00005116 // Synchronize the abiflags information with the FeatureBits information we
5117 // changed above.
5118 getTargetStreamer().updateABIInfo(*this);
5119
5120 // If printing assembly, use the recently updated abiflags information.
5121 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5122 // emitted at the end).
5123 getTargetStreamer().emitDirectiveModuleOddSPReg();
5124
Toma Tabacuc405c822015-01-23 10:40:19 +00005125 // If this is not the end of the statement, report an error.
5126 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5127 reportParseError("unexpected token, expected end of statement");
5128 return false;
5129 }
5130
5131 return false; // parseDirectiveModule has finished successfully.
5132 } else if (Option == "nooddspreg") {
5133 if (!isABI_O32()) {
5134 Error(L, "'.module nooddspreg' requires the O32 ABI");
5135 return false;
5136 }
5137
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005138 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005139
Toma Tabacu3c499582015-06-25 10:56:57 +00005140 // Synchronize the abiflags information with the FeatureBits information we
5141 // changed above.
5142 getTargetStreamer().updateABIInfo(*this);
5143
5144 // If printing assembly, use the recently updated abiflags information.
5145 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5146 // emitted at the end).
5147 getTargetStreamer().emitDirectiveModuleOddSPReg();
5148
Toma Tabacuc405c822015-01-23 10:40:19 +00005149 // If this is not the end of the statement, report an error.
5150 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5151 reportParseError("unexpected token, expected end of statement");
5152 return false;
5153 }
5154
5155 return false; // parseDirectiveModule has finished successfully.
5156 } else if (Option == "fp") {
5157 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005158 } else if (Option == "softfloat") {
5159 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5160
5161 // Synchronize the ABI Flags information with the FeatureBits information we
5162 // updated above.
5163 getTargetStreamer().updateABIInfo(*this);
5164
5165 // If printing assembly, use the recently updated ABI Flags information.
5166 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5167 // emitted later).
5168 getTargetStreamer().emitDirectiveModuleSoftFloat();
5169
5170 // If this is not the end of the statement, report an error.
5171 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5172 reportParseError("unexpected token, expected end of statement");
5173 return false;
5174 }
5175
5176 return false; // parseDirectiveModule has finished successfully.
5177 } else if (Option == "hardfloat") {
5178 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5179
5180 // Synchronize the ABI Flags information with the FeatureBits information we
5181 // updated above.
5182 getTargetStreamer().updateABIInfo(*this);
5183
5184 // If printing assembly, use the recently updated ABI Flags information.
5185 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5186 // emitted later).
5187 getTargetStreamer().emitDirectiveModuleHardFloat();
5188
5189 // If this is not the end of the statement, report an error.
5190 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5191 reportParseError("unexpected token, expected end of statement");
5192 return false;
5193 }
5194
5195 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005196 } else {
5197 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5198 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005199}
5200
5201/// parseDirectiveModuleFP
5202/// ::= =32
5203/// ::= =xx
5204/// ::= =64
5205bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005206 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005207 MCAsmLexer &Lexer = getLexer();
5208
5209 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005210 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005211 return false;
5212 }
5213 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005214
Daniel Sanders7e527422014-07-10 13:38:23 +00005215 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005216 if (!parseFpABIValue(FpABI, ".module"))
5217 return false;
5218
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005219 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005220 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005221 return false;
5222 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005223
Toma Tabacua64e5402015-06-25 12:44:38 +00005224 // Synchronize the abiflags information with the FeatureBits information we
5225 // changed above.
5226 getTargetStreamer().updateABIInfo(*this);
5227
5228 // If printing assembly, use the recently updated abiflags information.
5229 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5230 // emitted at the end).
5231 getTargetStreamer().emitDirectiveModuleFP();
5232
Daniel Sanders7e527422014-07-10 13:38:23 +00005233 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005234 return false;
5235}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005236
Daniel Sanders7e527422014-07-10 13:38:23 +00005237bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005238 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005239 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005240 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005241 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005242
5243 if (Lexer.is(AsmToken::Identifier)) {
5244 StringRef Value = Parser.getTok().getString();
5245 Parser.Lex();
5246
5247 if (Value != "xx") {
5248 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5249 return false;
5250 }
5251
5252 if (!isABI_O32()) {
5253 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5254 return false;
5255 }
5256
Daniel Sanders7e527422014-07-10 13:38:23 +00005257 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005258 if (ModuleLevelOptions) {
5259 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5260 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5261 } else {
5262 setFeatureBits(Mips::FeatureFPXX, "fpxx");
5263 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5264 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005265 return true;
5266 }
5267
5268 if (Lexer.is(AsmToken::Integer)) {
5269 unsigned Value = Parser.getTok().getIntVal();
5270 Parser.Lex();
5271
5272 if (Value != 32 && Value != 64) {
5273 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5274 return false;
5275 }
5276
5277 if (Value == 32) {
5278 if (!isABI_O32()) {
5279 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
5280 return false;
5281 }
5282
Daniel Sanders7e527422014-07-10 13:38:23 +00005283 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005284 if (ModuleLevelOptions) {
5285 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5286 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5287 } else {
5288 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5289 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5290 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005291 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00005292 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005293 if (ModuleLevelOptions) {
5294 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5295 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5296 } else {
5297 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5298 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
5299 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005300 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005301
Daniel Sanders7e527422014-07-10 13:38:23 +00005302 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005303 }
5304
5305 return false;
5306}
5307
Jack Carter0b744b32012-10-04 02:29:46 +00005308bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005309 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005310 StringRef IDVal = DirectiveID.getString();
5311
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005312 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005313 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00005314 if (IDVal == ".dword") {
5315 parseDataDirective(8, DirectiveID.getLoc());
5316 return false;
5317 }
Jack Carterd0bd6422013-04-18 00:41:53 +00005318 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005319 StringRef SymbolName;
5320
5321 if (Parser.parseIdentifier(SymbolName)) {
5322 reportParseError("expected identifier after .ent");
5323 return false;
5324 }
5325
5326 // There's an undocumented extension that allows an integer to
5327 // follow the name of the procedure which AFAICS is ignored by GAS.
5328 // Example: .ent foo,2
5329 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5330 if (getLexer().isNot(AsmToken::Comma)) {
5331 // Even though we accept this undocumented extension for compatibility
5332 // reasons, the additional integer argument does not actually change
5333 // the behaviour of the '.ent' directive, so we would like to discourage
5334 // its use. We do this by not referring to the extended version in
5335 // error messages which are not directly related to its use.
5336 reportParseError("unexpected token, expected end of statement");
5337 return false;
5338 }
5339 Parser.Lex(); // Eat the comma.
5340 const MCExpr *DummyNumber;
5341 int64_t DummyNumberVal;
5342 // If the user was explicitly trying to use the extended version,
5343 // we still give helpful extension-related error messages.
5344 if (Parser.parseExpression(DummyNumber)) {
5345 reportParseError("expected number after comma");
5346 return false;
5347 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00005348 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005349 reportParseError("expected an absolute expression after comma");
5350 return false;
5351 }
5352 }
5353
5354 // If this is not the end of the statement, report an error.
5355 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5356 reportParseError("unexpected token, expected end of statement");
5357 return false;
5358 }
5359
Jim Grosbach6f482002015-05-18 18:43:14 +00005360 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005361
5362 getTargetStreamer().emitDirectiveEnt(*Sym);
5363 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00005364 return false;
5365 }
5366
Jack Carter07c818d2013-01-25 01:31:34 +00005367 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005368 StringRef SymbolName;
5369
5370 if (Parser.parseIdentifier(SymbolName)) {
5371 reportParseError("expected identifier after .end");
5372 return false;
5373 }
5374
5375 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5376 reportParseError("unexpected token, expected end of statement");
5377 return false;
5378 }
5379
5380 if (CurrentFn == nullptr) {
5381 reportParseError(".end used without .ent");
5382 return false;
5383 }
5384
5385 if ((SymbolName != CurrentFn->getName())) {
5386 reportParseError(".end symbol does not match .ent symbol");
5387 return false;
5388 }
5389
5390 getTargetStreamer().emitDirectiveEnd(SymbolName);
5391 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00005392 return false;
5393 }
5394
Jack Carter07c818d2013-01-25 01:31:34 +00005395 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005396 // .frame $stack_reg, frame_size_in_bytes, $return_reg
5397 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005398 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005399 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5400 reportParseError("expected stack register");
5401 return false;
5402 }
5403
5404 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5405 if (!StackRegOpnd.isGPRAsmReg()) {
5406 reportParseError(StackRegOpnd.getStartLoc(),
5407 "expected general purpose register");
5408 return false;
5409 }
5410 unsigned StackReg = StackRegOpnd.getGPR32Reg();
5411
5412 if (Parser.getTok().is(AsmToken::Comma))
5413 Parser.Lex();
5414 else {
5415 reportParseError("unexpected token, expected comma");
5416 return false;
5417 }
5418
5419 // Parse the frame size.
5420 const MCExpr *FrameSize;
5421 int64_t FrameSizeVal;
5422
5423 if (Parser.parseExpression(FrameSize)) {
5424 reportParseError("expected frame size value");
5425 return false;
5426 }
5427
Jim Grosbach13760bd2015-05-30 01:25:56 +00005428 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005429 reportParseError("frame size not an absolute expression");
5430 return false;
5431 }
5432
5433 if (Parser.getTok().is(AsmToken::Comma))
5434 Parser.Lex();
5435 else {
5436 reportParseError("unexpected token, expected comma");
5437 return false;
5438 }
5439
5440 // Parse the return register.
5441 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00005442 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005443 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5444 reportParseError("expected return register");
5445 return false;
5446 }
5447
5448 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5449 if (!ReturnRegOpnd.isGPRAsmReg()) {
5450 reportParseError(ReturnRegOpnd.getStartLoc(),
5451 "expected general purpose register");
5452 return false;
5453 }
5454
5455 // If this is not the end of the statement, report an error.
5456 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5457 reportParseError("unexpected token, expected end of statement");
5458 return false;
5459 }
5460
5461 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
5462 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00005463 return false;
5464 }
5465
Jack Carter07c818d2013-01-25 01:31:34 +00005466 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00005467 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00005468 }
5469
Daniel Sandersd97a6342014-08-13 10:07:34 +00005470 if (IDVal == ".mask" || IDVal == ".fmask") {
5471 // .mask bitmask, frame_offset
5472 // bitmask: One bit for each register used.
5473 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
5474 // first register is expected to be saved.
5475 // Examples:
5476 // .mask 0x80000000, -4
5477 // .fmask 0x80000000, -4
5478 //
Jack Carterbe332172012-09-07 00:48:02 +00005479
Daniel Sandersd97a6342014-08-13 10:07:34 +00005480 // Parse the bitmask
5481 const MCExpr *BitMask;
5482 int64_t BitMaskVal;
5483
5484 if (Parser.parseExpression(BitMask)) {
5485 reportParseError("expected bitmask value");
5486 return false;
5487 }
5488
Jim Grosbach13760bd2015-05-30 01:25:56 +00005489 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005490 reportParseError("bitmask not an absolute expression");
5491 return false;
5492 }
5493
5494 if (Parser.getTok().is(AsmToken::Comma))
5495 Parser.Lex();
5496 else {
5497 reportParseError("unexpected token, expected comma");
5498 return false;
5499 }
5500
5501 // Parse the frame_offset
5502 const MCExpr *FrameOffset;
5503 int64_t FrameOffsetVal;
5504
5505 if (Parser.parseExpression(FrameOffset)) {
5506 reportParseError("expected frame offset value");
5507 return false;
5508 }
5509
Jim Grosbach13760bd2015-05-30 01:25:56 +00005510 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005511 reportParseError("frame offset not an absolute expression");
5512 return false;
5513 }
5514
5515 // If this is not the end of the statement, report an error.
5516 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5517 reportParseError("unexpected token, expected end of statement");
5518 return false;
5519 }
5520
5521 if (IDVal == ".mask")
5522 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
5523 else
5524 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00005525 return false;
5526 }
5527
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005528 if (IDVal == ".nan")
5529 return parseDirectiveNaN();
5530
Jack Carter07c818d2013-01-25 01:31:34 +00005531 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005532 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00005533 return false;
5534 }
5535
Rafael Espindolab59fb732014-03-28 18:50:26 +00005536 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005537 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005538 return false;
5539 }
5540
Jack Carter07c818d2013-01-25 01:31:34 +00005541 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005542 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00005543 return false;
5544 }
5545
Jack Carter0cd3c192014-01-06 23:27:31 +00005546 if (IDVal == ".option")
5547 return parseDirectiveOption();
5548
5549 if (IDVal == ".abicalls") {
5550 getTargetStreamer().emitDirectiveAbiCalls();
5551 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005552 Error(Parser.getTok().getLoc(),
5553 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005554 // Clear line
5555 Parser.eatToEndOfStatement();
5556 }
5557 return false;
5558 }
5559
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005560 if (IDVal == ".cpsetup")
5561 return parseDirectiveCPSetup();
5562
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005563 if (IDVal == ".module")
5564 return parseDirectiveModule();
5565
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005566 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
5567 return parseInternalDirectiveReallowModule();
5568
Toma Tabacu9ca50962015-04-16 09:53:47 +00005569 if (IDVal == ".insn")
5570 return parseInsnDirective();
5571
Rafael Espindola870c4e92012-01-11 03:56:41 +00005572 return true;
5573}
5574
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005575bool MipsAsmParser::parseInternalDirectiveReallowModule() {
5576 // If this is not the end of the statement, report an error.
5577 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5578 reportParseError("unexpected token, expected end of statement");
5579 return false;
5580 }
5581
5582 getTargetStreamer().reallowModuleDirective();
5583
5584 getParser().Lex(); // Eat EndOfStatement token.
5585 return false;
5586}
5587
Rafael Espindola870c4e92012-01-11 03:56:41 +00005588extern "C" void LLVMInitializeMipsAsmParser() {
5589 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
5590 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
5591 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
5592 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
5593}
Jack Carterb4dbc172012-09-05 23:34:03 +00005594
5595#define GET_REGISTER_MATCHER
5596#define GET_MATCHER_IMPLEMENTATION
5597#include "MipsGenAsmMatcher.inc"