blob: 77e7e6f186fc6d4e7b2d39dd6e739ba396fd9198 [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
David Blaikie960ea3f2014-06-08 16:18:35 +0000146 MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000147
148 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000149 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000150 StringRef Identifier, SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000151
Jack Carter873c7242013-01-12 01:03:14 +0000152 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000153 matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
Jack Carter873c7242013-01-12 01:03:14 +0000154
Toma Tabacu13964452014-09-04 13:23:44 +0000155 MipsAsmParser::OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000156
Toma Tabacu13964452014-09-04 13:23:44 +0000157 MipsAsmParser::OperandMatchResultTy parseImm(OperandVector &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000158
Toma Tabacu13964452014-09-04 13:23:44 +0000159 MipsAsmParser::OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000160
David Blaikie960ea3f2014-06-08 16:18:35 +0000161 MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000162
Toma Tabacu13964452014-09-04 13:23:44 +0000163 MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000164
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000165 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000166 parseRegisterPair (OperandVector &Operands);
167
168 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +0000169 parseMovePRegPair(OperandVector &Operands);
170
171 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000172 parseRegisterList (OperandVector &Operands);
173
David Blaikie960ea3f2014-06-08 16:18:35 +0000174 bool searchSymbolAlias(OperandVector &Operands);
175
Toma Tabacu13964452014-09-04 13:23:44 +0000176 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000177
Jack Carter30a59822012-10-04 04:03:53 +0000178 bool needsExpansion(MCInst &Inst);
179
Matheus Almeida3813d572014-06-19 14:39:14 +0000180 // Expands assembly pseudo instructions.
181 // Returns false on success, true otherwise.
182 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000183 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000184
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000185 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
186 SmallVectorImpl<MCInst> &Instructions);
187
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000188 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000189 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000190 SmallVectorImpl<MCInst> &Instructions);
191
Toma Tabacuf712ede2015-06-17 14:31:51 +0000192 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
193 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
194 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacu674825c2015-06-16 12:16:24 +0000195
Toma Tabacu00e98672015-05-01 12:19:27 +0000196 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000197 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000198
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000199 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
200 const MCOperand &Offset, bool Is32BitAddress,
201 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000202
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000203 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
204 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000205
Jack Carter9e65aa32013-03-22 00:05:30 +0000206 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000207 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
208 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000209
210 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
211 SmallVectorImpl<MCInst> &Instructions);
212
Toma Tabacue1e460d2015-06-11 10:36:10 +0000213 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc,
214 SmallVectorImpl<MCInst> &Instructions);
215
Toma Tabacu1a108322015-06-17 13:20:24 +0000216 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc,
217 SmallVectorImpl<MCInst> &Instructions);
218
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000219 bool expandDiv(MCInst &Inst, SMLoc IDLoc,
220 SmallVectorImpl<MCInst> &Instructions, const bool IsMips64,
221 const bool Signed);
222
Toma Tabacud88d79c2015-06-23 14:39:42 +0000223 bool expandUlhu(MCInst &Inst, SMLoc IDLoc,
224 SmallVectorImpl<MCInst> &Instructions);
225
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000226 bool expandUlw(MCInst &Inst, SMLoc IDLoc,
227 SmallVectorImpl<MCInst> &Instructions);
228
Toma Tabacu234482a2015-03-16 12:03:39 +0000229 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
230 SmallVectorImpl<MCInst> &Instructions);
231
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000232 void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +0000233 bool Is64Bit, SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000234
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000235 bool reportParseError(Twine ErrorMsg);
236 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000237
Jack Carterb5cf5902013-04-17 00:18:04 +0000238 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000239 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000240
Vladimir Medic4c299852013-11-06 11:27:05 +0000241 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000242
243 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000244 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000245 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000246 bool parseSetFeature(uint64_t Feature);
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000247 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000248 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000249 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000250 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000251 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000252 bool parseInsnDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000253
254 bool parseSetAtDirective();
255 bool parseSetNoAtDirective();
256 bool parseSetMacroDirective();
257 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000258 bool parseSetMsaDirective();
259 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000260 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000261 bool parseSetReorderDirective();
262 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000263 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000264 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000265 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000266 bool parseSetOddSPRegDirective();
267 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000268 bool parseSetPopDirective();
269 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000270 bool parseSetSoftFloatDirective();
271 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000272
Jack Carterd76b2372013-03-21 21:44:16 +0000273 bool parseSetAssignment();
274
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000275 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000276 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000277 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000278 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000279 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000280 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
281 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000282
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000283 bool parseInternalDirectiveReallowModule();
284
Jack Carterdc1e35d2012-09-06 20:00:02 +0000285 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000286
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000287 bool eatComma(StringRef ErrorStr);
288
Jack Carter1ac53222013-02-20 23:11:17 +0000289 int matchCPURegisterName(StringRef Symbol);
290
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000291 int matchHWRegsRegisterName(StringRef Symbol);
292
Jack Carter873c7242013-01-12 01:03:14 +0000293 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000294
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000295 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000296
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000297 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000298
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000299 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000300
Jack Carter5dc8ac92013-09-25 23:50:44 +0000301 int matchMSA128RegisterName(StringRef Name);
302
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000303 int matchMSA128CtrlRegisterName(StringRef Name);
304
Jack Carterd0bd6422013-04-18 00:41:53 +0000305 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000306
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000307 unsigned getGPR(int RegNo);
308
Toma Tabacu89a712b2015-04-15 10:48:56 +0000309 /// Returns the internal register number for the current AT. Also checks if
310 /// the current AT is unavailable (set to $0) and gives an error if it is.
311 /// This should be used in pseudo-instruction expansions which need AT.
312 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000313
314 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000315 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000316
317 // Helper function that checks if the value of a vector index is within the
318 // boundaries of accepted values for each RegisterKind
319 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
320 bool validateMSAIndex(int Val, int RegKind);
321
Daniel Sandersf0df2212014-08-04 12:20:00 +0000322 // Selects a new architecture by updating the FeatureBits with the necessary
323 // info including implied dependencies.
324 // Internally, it clears all the feature bits related to *any* architecture
325 // and selects the new one using the ToggleFeature functionality of the
326 // MCSubtargetInfo object that handles implied dependencies. The reason we
327 // clear all the arch related bits manually is because ToggleFeature only
328 // clears the features that imply the feature being cleared and not the
329 // features implied by the feature being cleared. This is easier to see
330 // with an example:
331 // --------------------------------------------------
332 // | Feature | Implies |
333 // | -------------------------------------------------|
334 // | FeatureMips1 | None |
335 // | FeatureMips2 | FeatureMips1 |
336 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
337 // | FeatureMips4 | FeatureMips3 |
338 // | ... | |
339 // --------------------------------------------------
340 //
341 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
342 // FeatureMipsGP64 | FeatureMips1)
343 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
344 void selectArch(StringRef ArchFeature) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000345 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000346 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
347 STI.setFeatureBits(FeatureBits);
348 setAvailableFeatures(
349 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000350 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000351 }
352
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000353 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000354 if (!(STI.getFeatureBits()[Feature])) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000355 setAvailableFeatures(
356 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000357 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000358 }
359 }
360
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000361 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000362 if (STI.getFeatureBits()[Feature]) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000363 setAvailableFeatures(
364 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000365 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000366 }
367 }
368
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000369 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
370 setFeatureBits(Feature, FeatureString);
371 AssemblerOptions.front()->setFeatures(STI.getFeatureBits());
372 }
373
374 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
375 clearFeatureBits(Feature, FeatureString);
376 AssemblerOptions.front()->setFeatures(STI.getFeatureBits());
377 }
378
Rafael Espindola870c4e92012-01-11 03:56:41 +0000379public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000380 enum MipsMatchResultTy {
381 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
382#define GET_OPERAND_DIAGNOSTIC_TYPES
383#include "MipsGenAsmMatcher.inc"
384#undef GET_OPERAND_DIAGNOSTIC_TYPES
385
386 };
387
Joey Gouly0e76fa72013-09-12 10:28:05 +0000388 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000389 const MCInstrInfo &MII, const MCTargetOptions &Options)
Colin LeMahieufe2c8b82015-07-27 21:56:53 +0000390 : MCTargetAsmParser(Options), STI(sti),
Eric Christophera5762812015-01-26 17:33:46 +0000391 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
392 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000393 MCAsmParserExtension::Initialize(parser);
394
Toma Tabacu11e14a92015-04-21 11:50:52 +0000395 parser.addAliasForDirective(".asciiz", ".asciz");
396
Jack Carterb4dbc172012-09-05 23:34:03 +0000397 // Initialize the set of available features.
398 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000399
Toma Tabacu9db22db2014-09-09 10:15:38 +0000400 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000401 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000402 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000403
Toma Tabacu9db22db2014-09-09 10:15:38 +0000404 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000405 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000406 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000407
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000408 getTargetStreamer().updateABIInfo(*this);
409
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000410 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000411 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000412
413 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000414
Daniel Sandersa6994442015-08-18 12:33:54 +0000415 IsPicEnabled =
416 (getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_);
417
Toma Tabacud88d79c2015-06-23 14:39:42 +0000418 Triple TheTriple(sti.getTargetTriple());
419 if ((TheTriple.getArch() == Triple::mips) ||
420 (TheTriple.getArch() == Triple::mips64))
421 IsLittleEndian = false;
422 else
423 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000424 }
425
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000426 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
427 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
428
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000429 bool isGP64bit() const { return STI.getFeatureBits()[Mips::FeatureGP64Bit]; }
430 bool isFP64bit() const { return STI.getFeatureBits()[Mips::FeatureFP64Bit]; }
Eric Christophera5762812015-01-26 17:33:46 +0000431 const MipsABIInfo &getABI() const { return ABI; }
432 bool isABI_N32() const { return ABI.IsN32(); }
433 bool isABI_N64() const { return ABI.IsN64(); }
434 bool isABI_O32() const { return ABI.IsO32(); }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000435 bool isABI_FPXX() const { return STI.getFeatureBits()[Mips::FeatureFPXX]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000436
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000437 bool useOddSPReg() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000438 return !(STI.getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000439 }
440
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000441 bool inMicroMipsMode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000442 return STI.getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000443 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000444 bool hasMips1() const { return STI.getFeatureBits()[Mips::FeatureMips1]; }
445 bool hasMips2() const { return STI.getFeatureBits()[Mips::FeatureMips2]; }
446 bool hasMips3() const { return STI.getFeatureBits()[Mips::FeatureMips3]; }
447 bool hasMips4() const { return STI.getFeatureBits()[Mips::FeatureMips4]; }
448 bool hasMips5() const { return STI.getFeatureBits()[Mips::FeatureMips5]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000449 bool hasMips32() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000450 return STI.getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000451 }
452 bool hasMips64() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000453 return STI.getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000454 }
455 bool hasMips32r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000456 return STI.getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000457 }
458 bool hasMips64r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000459 return STI.getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000460 }
Daniel Sanders17793142015-02-18 16:24:50 +0000461 bool hasMips32r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000462 return (STI.getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000463 }
464 bool hasMips64r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000465 return (STI.getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000466 }
467 bool hasMips32r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000468 return (STI.getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000469 }
470 bool hasMips64r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000471 return (STI.getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000472 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000473 bool hasMips32r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000474 return STI.getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000475 }
476 bool hasMips64r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000477 return STI.getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000478 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000479
480 bool hasDSP() const { return STI.getFeatureBits()[Mips::FeatureDSP]; }
481 bool hasDSPR2() const { return STI.getFeatureBits()[Mips::FeatureDSPR2]; }
482 bool hasMSA() const { return STI.getFeatureBits()[Mips::FeatureMSA]; }
Kai Nackee0245392015-01-27 19:11:28 +0000483 bool hasCnMips() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000484 return (STI.getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000485 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000486
Daniel Sandersa6994442015-08-18 12:33:54 +0000487 bool inPicMode() {
488 return IsPicEnabled;
489 }
490
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000491 bool inMips16Mode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000492 return STI.getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000493 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000494
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000495 bool useTraps() const {
496 return STI.getFeatureBits()[Mips::FeatureUseTCCInDIV];
497 }
498
Eric Christophere8ae3e32015-05-07 23:10:21 +0000499 bool useSoftFloat() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000500 return STI.getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000501 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000502
Toma Tabacud9d344b2015-04-27 14:05:04 +0000503 /// Warn if RegIndex is the same as the current AT.
504 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000505
506 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000507
508 bool isLittle() const { return IsLittleEndian; }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000509};
510}
511
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000512namespace {
513
514/// MipsOperand - Instances of this class represent a parsed Mips machine
515/// instruction.
516class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000517public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000518 /// Broad categories of register classes
519 /// The exact class is finalized by the render method.
520 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000521 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000522 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000523 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000524 RegKind_FCC = 4, /// FCC
525 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
526 RegKind_MSACtrl = 16, /// MSA control registers
527 RegKind_COP2 = 32, /// COP2
528 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
529 /// context).
530 RegKind_CCR = 128, /// CCR
531 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000532 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000533 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000534 /// Potentially any (e.g. $1)
535 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
536 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000537 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000538 };
539
540private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000541 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000542 k_Immediate, /// An immediate (possibly involving symbol references)
543 k_Memory, /// Base + Offset Memory Address
544 k_PhysRegister, /// A physical register from the Mips namespace
545 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000546 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000547 k_RegList, /// A physical register list
548 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000549 } Kind;
550
David Blaikie960ea3f2014-06-08 16:18:35 +0000551public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000552 MipsOperand(KindTy K, MipsAsmParser &Parser)
553 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
554
David Blaikie960ea3f2014-06-08 16:18:35 +0000555private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000556 /// For diagnostics, and checking the assembler temporary
557 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000558
Eric Christopher8996c5d2013-03-15 00:42:55 +0000559 struct Token {
560 const char *Data;
561 unsigned Length;
562 };
563
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000564 struct PhysRegOp {
565 unsigned Num; /// Register Number
566 };
567
568 struct RegIdxOp {
569 unsigned Index; /// Index into the register class
570 RegKind Kind; /// Bitfield of the kinds it could possibly be
571 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000572 };
573
574 struct ImmOp {
575 const MCExpr *Val;
576 };
577
578 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000579 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000580 const MCExpr *Off;
581 };
582
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000583 struct RegListOp {
584 SmallVector<unsigned, 10> *List;
585 };
586
Jack Carterb4dbc172012-09-05 23:34:03 +0000587 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000588 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000589 struct PhysRegOp PhysReg;
590 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000591 struct ImmOp Imm;
592 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000593 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000594 };
595
596 SMLoc StartLoc, EndLoc;
597
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000598 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000599 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
600 const MCRegisterInfo *RegInfo,
601 SMLoc S, SMLoc E,
602 MipsAsmParser &Parser) {
603 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000604 Op->RegIdx.Index = Index;
605 Op->RegIdx.RegInfo = RegInfo;
606 Op->RegIdx.Kind = RegKind;
607 Op->StartLoc = S;
608 Op->EndLoc = E;
609 return Op;
610 }
611
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000612public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000613 /// Coerce the register to GPR32 and return the real register for the current
614 /// target.
615 unsigned getGPR32Reg() const {
616 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000617 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000618 unsigned ClassID = Mips::GPR32RegClassID;
619 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000620 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000621
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000622 /// Coerce the register to GPR32 and return the real register for the current
623 /// target.
624 unsigned getGPRMM16Reg() const {
625 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
626 unsigned ClassID = Mips::GPR32RegClassID;
627 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
628 }
629
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000630 /// Coerce the register to GPR64 and return the real register for the current
631 /// target.
632 unsigned getGPR64Reg() const {
633 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
634 unsigned ClassID = Mips::GPR64RegClassID;
635 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000636 }
637
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000638private:
639 /// Coerce the register to AFGR64 and return the real register for the current
640 /// target.
641 unsigned getAFGR64Reg() const {
642 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
643 if (RegIdx.Index % 2 != 0)
644 AsmParser.Warning(StartLoc, "Float register should be even.");
645 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
646 .getRegister(RegIdx.Index / 2);
647 }
648
649 /// Coerce the register to FGR64 and return the real register for the current
650 /// target.
651 unsigned getFGR64Reg() const {
652 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
653 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
654 .getRegister(RegIdx.Index);
655 }
656
657 /// Coerce the register to FGR32 and return the real register for the current
658 /// target.
659 unsigned getFGR32Reg() const {
660 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
661 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
662 .getRegister(RegIdx.Index);
663 }
664
665 /// Coerce the register to FGRH32 and return the real register for the current
666 /// target.
667 unsigned getFGRH32Reg() const {
668 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
669 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
670 .getRegister(RegIdx.Index);
671 }
672
673 /// Coerce the register to FCC and return the real register for the current
674 /// target.
675 unsigned getFCCReg() const {
676 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
677 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
678 .getRegister(RegIdx.Index);
679 }
680
681 /// Coerce the register to MSA128 and return the real register for the current
682 /// target.
683 unsigned getMSA128Reg() const {
684 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
685 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
686 // identical
687 unsigned ClassID = Mips::MSA128BRegClassID;
688 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
689 }
690
691 /// Coerce the register to MSACtrl and return the real register for the
692 /// current target.
693 unsigned getMSACtrlReg() const {
694 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
695 unsigned ClassID = Mips::MSACtrlRegClassID;
696 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
697 }
698
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000699 /// Coerce the register to COP0 and return the real register for the
700 /// current target.
701 unsigned getCOP0Reg() const {
702 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
703 unsigned ClassID = Mips::COP0RegClassID;
704 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
705 }
706
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000707 /// Coerce the register to COP2 and return the real register for the
708 /// current target.
709 unsigned getCOP2Reg() const {
710 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
711 unsigned ClassID = Mips::COP2RegClassID;
712 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
713 }
714
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000715 /// Coerce the register to COP3 and return the real register for the
716 /// current target.
717 unsigned getCOP3Reg() const {
718 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
719 unsigned ClassID = Mips::COP3RegClassID;
720 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
721 }
722
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000723 /// Coerce the register to ACC64DSP and return the real register for the
724 /// current target.
725 unsigned getACC64DSPReg() const {
726 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
727 unsigned ClassID = Mips::ACC64DSPRegClassID;
728 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
729 }
730
731 /// Coerce the register to HI32DSP and return the real register for the
732 /// current target.
733 unsigned getHI32DSPReg() const {
734 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
735 unsigned ClassID = Mips::HI32DSPRegClassID;
736 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
737 }
738
739 /// Coerce the register to LO32DSP and return the real register for the
740 /// current target.
741 unsigned getLO32DSPReg() const {
742 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
743 unsigned ClassID = Mips::LO32DSPRegClassID;
744 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
745 }
746
747 /// Coerce the register to CCR and return the real register for the
748 /// current target.
749 unsigned getCCRReg() const {
750 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
751 unsigned ClassID = Mips::CCRRegClassID;
752 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
753 }
754
755 /// Coerce the register to HWRegs and return the real register for the
756 /// current target.
757 unsigned getHWRegsReg() const {
758 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
759 unsigned ClassID = Mips::HWRegsRegClassID;
760 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
761 }
762
763public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000764 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000765 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000766 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000767 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000768 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000769 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000770 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000771 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000772 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000773
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000774 void addRegOperands(MCInst &Inst, unsigned N) const {
775 llvm_unreachable("Use a custom parser instead");
776 }
777
Daniel Sanders21bce302014-04-01 12:35:23 +0000778 /// Render the operand to an MCInst as a GPR32
779 /// Asserts if the wrong number of operands are requested, or the operand
780 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000781 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
782 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000783 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000784 }
785
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000786 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
787 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000788 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000789 }
790
Jozef Kolek1904fa22014-11-24 14:25:53 +0000791 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
792 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000793 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000794 }
795
Zoran Jovanovic41688672015-02-10 16:36:20 +0000796 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
797 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000798 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000799 }
800
Daniel Sanders21bce302014-04-01 12:35:23 +0000801 /// Render the operand to an MCInst as a GPR64
802 /// Asserts if the wrong number of operands are requested, or the operand
803 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000804 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
805 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000806 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000807 }
808
809 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
810 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000811 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000812 }
813
814 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
815 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000816 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000817 }
818
819 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
820 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000821 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000822 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000823 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000824 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
825 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000826 }
827
828 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
829 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000830 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000831 }
832
833 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
834 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000835 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000836 }
837
838 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
839 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000840 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000841 }
842
843 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
844 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000845 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000846 }
847
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000848 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
849 assert(N == 1 && "Invalid number of operands!");
850 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
851 }
852
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000853 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
854 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000855 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000856 }
857
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000858 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
859 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000860 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000861 }
862
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000863 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
864 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000865 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000866 }
867
868 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
869 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000870 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000871 }
872
873 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
874 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000875 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000876 }
877
878 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
879 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000880 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000881 }
882
883 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
884 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000885 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000886 }
887
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000888 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000889 assert(N == 1 && "Invalid number of operands!");
890 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000891 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000892 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000893
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000894 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000895 assert(N == 2 && "Invalid number of operands!");
896
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000897 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
898 ? getMemBase()->getGPR64Reg()
899 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000900
901 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000902 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000903 }
904
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000905 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
906 assert(N == 2 && "Invalid number of operands!");
907
Jim Grosbache9119e42015-05-13 18:37:00 +0000908 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000909
910 const MCExpr *Expr = getMemOff();
911 addExpr(Inst, Expr);
912 }
913
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000914 void addRegListOperands(MCInst &Inst, unsigned N) const {
915 assert(N == 1 && "Invalid number of operands!");
916
917 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000918 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000919 }
920
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000921 void addRegPairOperands(MCInst &Inst, unsigned N) const {
922 assert(N == 2 && "Invalid number of operands!");
923 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +0000924 Inst.addOperand(MCOperand::createReg(RegNo++));
925 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000926 }
927
Zoran Jovanovic41688672015-02-10 16:36:20 +0000928 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
929 assert(N == 2 && "Invalid number of operands!");
930 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000931 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000932 }
933
Craig Topper56c590a2014-04-29 07:58:02 +0000934 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000935 // As a special case until we sort out the definition of div/divu, pretend
936 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
937 if (isGPRAsmReg() && RegIdx.Index == 0)
938 return true;
939
940 return Kind == k_PhysRegister;
941 }
942 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000943 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000944 bool isConstantImm() const {
945 return isImm() && dyn_cast<MCConstantExpr>(getImm());
946 }
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +0000947 template <unsigned Bits> bool isUImm() const {
948 return isImm() && isConstantImm() && isUInt<Bits>(getConstantImm());
949 }
Craig Topper56c590a2014-04-29 07:58:02 +0000950 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000951 // Note: It's not possible to pretend that other operand kinds are tokens.
952 // The matcher emitter checks tokens first.
953 return Kind == k_Token;
954 }
Craig Topper56c590a2014-04-29 07:58:02 +0000955 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000956 bool isConstantMemOff() const {
957 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
958 }
959 template <unsigned Bits> bool isMemWithSimmOffset() const {
960 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
961 }
Zoran Jovanovica6593ff2015-08-18 12:53:08 +0000962 template <unsigned Bits> bool isMemWithSimmOffsetGPR() const {
963 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
964 && getMemBase()->isGPRAsmReg();
965 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000966 bool isMemWithGRPMM16Base() const {
967 return isMem() && getMemBase()->isMM16AsmReg();
968 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000969 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
970 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
971 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
972 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000973 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
974 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
975 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
976 && (getMemBase()->getGPR32Reg() == Mips::SP);
977 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000978 bool isRegList16() const {
979 if (!isRegList())
980 return false;
981
982 int Size = RegList.List->size();
983 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
984 RegList.List->back() != Mips::RA)
985 return false;
986
987 int PrevReg = *RegList.List->begin();
988 for (int i = 1; i < Size - 1; i++) {
989 int Reg = (*(RegList.List))[i];
990 if ( Reg != PrevReg + 1)
991 return false;
992 PrevReg = Reg;
993 }
994
995 return true;
996 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000997 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000998 bool isLSAImm() const {
999 if (!isConstantImm())
1000 return false;
1001 int64_t Val = getConstantImm();
1002 return 1 <= Val && Val <= 4;
1003 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001004 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001005 bool isMovePRegPair() const {
1006 if (Kind != k_RegList || RegList.List->size() != 2)
1007 return false;
1008
1009 unsigned R0 = RegList.List->front();
1010 unsigned R1 = RegList.List->back();
1011
1012 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1013 (R0 == Mips::A1 && R1 == Mips::A3) ||
1014 (R0 == Mips::A2 && R1 == Mips::A3) ||
1015 (R0 == Mips::A0 && R1 == Mips::S5) ||
1016 (R0 == Mips::A0 && R1 == Mips::S6) ||
1017 (R0 == Mips::A0 && R1 == Mips::A1) ||
1018 (R0 == Mips::A0 && R1 == Mips::A2) ||
1019 (R0 == Mips::A0 && R1 == Mips::A3))
1020 return true;
1021
1022 return false;
1023 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001024
1025 StringRef getToken() const {
1026 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001027 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001028 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001029 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001030
Craig Topper56c590a2014-04-29 07:58:02 +00001031 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001032 // As a special case until we sort out the definition of div/divu, pretend
1033 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1034 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1035 RegIdx.Kind & RegKind_GPR)
1036 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001037
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001038 assert(Kind == k_PhysRegister && "Invalid access!");
1039 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001040 }
1041
Jack Carterb4dbc172012-09-05 23:34:03 +00001042 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001043 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001044 return Imm.Val;
1045 }
1046
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001047 int64_t getConstantImm() const {
1048 const MCExpr *Val = getImm();
1049 return static_cast<const MCConstantExpr *>(Val)->getValue();
1050 }
1051
1052 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001053 assert((Kind == k_Memory) && "Invalid access!");
1054 return Mem.Base;
1055 }
1056
1057 const MCExpr *getMemOff() const {
1058 assert((Kind == k_Memory) && "Invalid access!");
1059 return Mem.Off;
1060 }
1061
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001062 int64_t getConstantMemOff() const {
1063 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1064 }
1065
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001066 const SmallVectorImpl<unsigned> &getRegList() const {
1067 assert((Kind == k_RegList) && "Invalid access!");
1068 return *(RegList.List);
1069 }
1070
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001071 unsigned getRegPair() const {
1072 assert((Kind == k_RegPair) && "Invalid access!");
1073 return RegIdx.Index;
1074 }
1075
David Blaikie960ea3f2014-06-08 16:18:35 +00001076 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1077 MipsAsmParser &Parser) {
1078 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001079 Op->Tok.Data = Str.data();
1080 Op->Tok.Length = Str.size();
1081 Op->StartLoc = S;
1082 Op->EndLoc = S;
1083 return Op;
1084 }
1085
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001086 /// Create a numeric register (e.g. $1). The exact register remains
1087 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001088 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001089 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001090 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001091 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001092 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001093 }
1094
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001095 /// Create a register that is definitely a GPR.
1096 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001097 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001098 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001099 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001100 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001101 }
1102
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001103 /// Create a register that is definitely a FGR.
1104 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001105 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001106 createFGRReg(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_FGR, RegInfo, S, E, Parser);
1109 }
1110
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001111 /// Create a register that is definitely a HWReg.
1112 /// This is typically only used for named registers such as $hwr_cpunum.
1113 static std::unique_ptr<MipsOperand>
1114 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1115 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1116 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1117 }
1118
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001119 /// Create a register that is definitely an FCC.
1120 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001121 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001122 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001123 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001124 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1125 }
1126
1127 /// Create a register that is definitely an ACC.
1128 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001129 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001130 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001131 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001132 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1133 }
1134
1135 /// Create a register that is definitely an MSA128.
1136 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001137 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001138 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001139 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001140 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1141 }
1142
1143 /// Create a register that is definitely an MSACtrl.
1144 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001145 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001146 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001147 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001148 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1149 }
1150
David Blaikie960ea3f2014-06-08 16:18:35 +00001151 static std::unique_ptr<MipsOperand>
1152 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1153 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001154 Op->Imm.Val = Val;
1155 Op->StartLoc = S;
1156 Op->EndLoc = E;
1157 return Op;
1158 }
1159
David Blaikie960ea3f2014-06-08 16:18:35 +00001160 static std::unique_ptr<MipsOperand>
1161 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1162 SMLoc E, MipsAsmParser &Parser) {
1163 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1164 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001165 Op->Mem.Off = Off;
1166 Op->StartLoc = S;
1167 Op->EndLoc = E;
1168 return Op;
1169 }
1170
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001171 static std::unique_ptr<MipsOperand>
1172 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1173 MipsAsmParser &Parser) {
1174 assert (Regs.size() > 0 && "Empty list not allowed");
1175
1176 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001177 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001178 Op->StartLoc = StartLoc;
1179 Op->EndLoc = EndLoc;
1180 return Op;
1181 }
1182
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001183 static std::unique_ptr<MipsOperand>
1184 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1185 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1186 Op->RegIdx.Index = RegNo;
1187 Op->StartLoc = S;
1188 Op->EndLoc = E;
1189 return Op;
1190 }
1191
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001192 bool isGPRAsmReg() const {
1193 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001194 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001195 bool isMM16AsmReg() const {
1196 if (!(isRegIdx() && RegIdx.Kind))
1197 return false;
1198 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1199 || RegIdx.Index == 16 || RegIdx.Index == 17);
1200 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001201 bool isMM16AsmRegZero() const {
1202 if (!(isRegIdx() && RegIdx.Kind))
1203 return false;
1204 return (RegIdx.Index == 0 ||
1205 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1206 RegIdx.Index == 17);
1207 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001208 bool isMM16AsmRegMoveP() const {
1209 if (!(isRegIdx() && RegIdx.Kind))
1210 return false;
1211 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1212 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1213 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001214 bool isFGRAsmReg() const {
1215 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1216 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001217 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001218 bool isHWRegsAsmReg() const {
1219 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001220 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001221 bool isCCRAsmReg() const {
1222 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001223 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001224 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001225 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1226 return false;
1227 if (!AsmParser.hasEightFccRegisters())
1228 return RegIdx.Index == 0;
1229 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001230 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001231 bool isACCAsmReg() const {
1232 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001233 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001234 bool isCOP0AsmReg() const {
1235 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1236 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001237 bool isCOP2AsmReg() const {
1238 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001239 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001240 bool isCOP3AsmReg() const {
1241 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1242 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001243 bool isMSA128AsmReg() const {
1244 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001245 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001246 bool isMSACtrlAsmReg() const {
1247 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001248 }
1249
Jack Carterb4dbc172012-09-05 23:34:03 +00001250 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001251 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001252 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001253 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001254
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001255 virtual ~MipsOperand() {
1256 switch (Kind) {
1257 case k_Immediate:
1258 break;
1259 case k_Memory:
1260 delete Mem.Base;
1261 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001262 case k_RegList:
1263 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001264 case k_PhysRegister:
1265 case k_RegisterIndex:
1266 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001267 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001268 break;
1269 }
1270 }
1271
Craig Topper56c590a2014-04-29 07:58:02 +00001272 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001273 switch (Kind) {
1274 case k_Immediate:
1275 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001276 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001277 OS << ">";
1278 break;
1279 case k_Memory:
1280 OS << "Mem<";
1281 Mem.Base->print(OS);
1282 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001283 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001284 OS << ">";
1285 break;
1286 case k_PhysRegister:
1287 OS << "PhysReg<" << PhysReg.Num << ">";
1288 break;
1289 case k_RegisterIndex:
1290 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1291 break;
1292 case k_Token:
1293 OS << Tok.Data;
1294 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001295 case k_RegList:
1296 OS << "RegList< ";
1297 for (auto Reg : (*RegList.List))
1298 OS << Reg << " ";
1299 OS << ">";
1300 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001301 case k_RegPair:
1302 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1303 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001304 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001305 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001306}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001307} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001308
Jack Carter9e65aa32013-03-22 00:05:30 +00001309namespace llvm {
1310extern const MCInstrDesc MipsInsts[];
1311}
1312static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1313 return MipsInsts[Opcode];
1314}
1315
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001316static bool hasShortDelaySlot(unsigned Opcode) {
1317 switch (Opcode) {
1318 case Mips::JALS_MM:
1319 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001320 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001321 case Mips::BGEZALS_MM:
1322 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001323 return true;
1324 default:
1325 return false;
1326 }
1327}
1328
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001329static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1330 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1331 return &SRExpr->getSymbol();
1332 }
1333
1334 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1335 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1336 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1337
1338 if (LHSSym)
1339 return LHSSym;
1340
1341 if (RHSSym)
1342 return RHSSym;
1343
1344 return nullptr;
1345 }
1346
1347 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1348 return getSingleMCSymbol(UExpr->getSubExpr());
1349
1350 return nullptr;
1351}
1352
1353static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1354 if (isa<MCSymbolRefExpr>(Expr))
1355 return 1;
1356
1357 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1358 return countMCSymbolRefExpr(BExpr->getLHS()) +
1359 countMCSymbolRefExpr(BExpr->getRHS());
1360
1361 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1362 return countMCSymbolRefExpr(UExpr->getSubExpr());
1363
1364 return 0;
1365}
1366
Jack Carter9e65aa32013-03-22 00:05:30 +00001367bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001368 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001369 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001370
Jack Carter9e65aa32013-03-22 00:05:30 +00001371 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001372
1373 if (MCID.isBranch() || MCID.isCall()) {
1374 const unsigned Opcode = Inst.getOpcode();
1375 MCOperand Offset;
1376
1377 switch (Opcode) {
1378 default:
1379 break;
Kai Nackee0245392015-01-27 19:11:28 +00001380 case Mips::BBIT0:
1381 case Mips::BBIT032:
1382 case Mips::BBIT1:
1383 case Mips::BBIT132:
1384 assert(hasCnMips() && "instruction only valid for octeon cpus");
1385 // Fall through
1386
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001387 case Mips::BEQ:
1388 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001389 case Mips::BEQ_MM:
1390 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001391 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001392 Offset = Inst.getOperand(2);
1393 if (!Offset.isImm())
1394 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001395 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001396 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001397 if (OffsetToAlignment(Offset.getImm(),
1398 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001399 return Error(IDLoc, "branch to misaligned address");
1400 break;
1401 case Mips::BGEZ:
1402 case Mips::BGTZ:
1403 case Mips::BLEZ:
1404 case Mips::BLTZ:
1405 case Mips::BGEZAL:
1406 case Mips::BLTZAL:
1407 case Mips::BC1F:
1408 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001409 case Mips::BGEZ_MM:
1410 case Mips::BGTZ_MM:
1411 case Mips::BLEZ_MM:
1412 case Mips::BLTZ_MM:
1413 case Mips::BGEZAL_MM:
1414 case Mips::BLTZAL_MM:
1415 case Mips::BC1F_MM:
1416 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001417 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001418 Offset = Inst.getOperand(1);
1419 if (!Offset.isImm())
1420 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001421 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001422 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001423 if (OffsetToAlignment(Offset.getImm(),
1424 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001425 return Error(IDLoc, "branch to misaligned address");
1426 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001427 case Mips::BEQZ16_MM:
1428 case Mips::BNEZ16_MM:
1429 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1430 Offset = Inst.getOperand(1);
1431 if (!Offset.isImm())
1432 break; // We'll deal with this situation later on when applying fixups.
1433 if (!isIntN(8, Offset.getImm()))
1434 return Error(IDLoc, "branch target out of range");
1435 if (OffsetToAlignment(Offset.getImm(), 2LL))
1436 return Error(IDLoc, "branch to misaligned address");
1437 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001438 }
1439 }
1440
Daniel Sandersa84989a2014-06-16 13:25:35 +00001441 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1442 // We still accept it but it is a normal nop.
1443 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1444 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1445 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1446 "nop instruction");
1447 }
1448
Kai Nackee0245392015-01-27 19:11:28 +00001449 if (hasCnMips()) {
1450 const unsigned Opcode = Inst.getOpcode();
1451 MCOperand Opnd;
1452 int Imm;
1453
1454 switch (Opcode) {
1455 default:
1456 break;
1457
1458 case Mips::BBIT0:
1459 case Mips::BBIT032:
1460 case Mips::BBIT1:
1461 case Mips::BBIT132:
1462 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1463 // The offset is handled above
1464 Opnd = Inst.getOperand(1);
1465 if (!Opnd.isImm())
1466 return Error(IDLoc, "expected immediate operand kind");
1467 Imm = Opnd.getImm();
1468 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1469 Opcode == Mips::BBIT1 ? 63 : 31))
1470 return Error(IDLoc, "immediate operand value out of range");
1471 if (Imm > 31) {
1472 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1473 : Mips::BBIT132);
1474 Inst.getOperand(1).setImm(Imm - 32);
1475 }
1476 break;
1477
1478 case Mips::CINS:
1479 case Mips::CINS32:
1480 case Mips::EXTS:
1481 case Mips::EXTS32:
1482 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1483 // Check length
1484 Opnd = Inst.getOperand(3);
1485 if (!Opnd.isImm())
1486 return Error(IDLoc, "expected immediate operand kind");
1487 Imm = Opnd.getImm();
1488 if (Imm < 0 || Imm > 31)
1489 return Error(IDLoc, "immediate operand value out of range");
1490 // Check position
1491 Opnd = Inst.getOperand(2);
1492 if (!Opnd.isImm())
1493 return Error(IDLoc, "expected immediate operand kind");
1494 Imm = Opnd.getImm();
1495 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1496 Opcode == Mips::EXTS ? 63 : 31))
1497 return Error(IDLoc, "immediate operand value out of range");
1498 if (Imm > 31) {
1499 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1500 Inst.getOperand(2).setImm(Imm - 32);
1501 }
1502 break;
1503
1504 case Mips::SEQi:
1505 case Mips::SNEi:
1506 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1507 Opnd = Inst.getOperand(2);
1508 if (!Opnd.isImm())
1509 return Error(IDLoc, "expected immediate operand kind");
1510 Imm = Opnd.getImm();
1511 if (!isInt<10>(Imm))
1512 return Error(IDLoc, "immediate operand value out of range");
1513 break;
1514 }
1515 }
1516
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001517 // This expansion is not in a function called by expandInstruction() because
1518 // the pseudo-instruction doesn't have a distinct opcode.
1519 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1520 inPicMode()) {
1521 warnIfNoMacro(IDLoc);
1522
1523 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1524
1525 // We can do this expansion if there's only 1 symbol in the argument
1526 // expression.
1527 if (countMCSymbolRefExpr(JalExpr) > 1)
1528 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1529
1530 // FIXME: This is checking the expression can be handled by the later stages
1531 // of the assembler. We ought to leave it to those later stages but
1532 // we can't do that until we stop evaluateRelocExpr() rewriting the
1533 // expressions into non-equivalent forms.
1534 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1535
1536 // FIXME: Add support for label+offset operands (currently causes an error).
1537 // FIXME: Add support for forward-declared local symbols.
1538 // FIXME: Add expansion for when the LargeGOT option is enabled.
1539 if (JalSym->isInSection() || JalSym->isTemporary()) {
1540 if (isABI_O32()) {
1541 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001542 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001543 // R_(MICRO)MIPS_GOT16 label
1544 // addiu $25, $25, 0
1545 // R_(MICRO)MIPS_LO16 label
1546 // jalr $25
1547 const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
1548 const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
1549
1550 MCInst LwInst;
1551 LwInst.setOpcode(Mips::LW);
1552 LwInst.addOperand(MCOperand::createReg(Mips::T9));
1553 LwInst.addOperand(MCOperand::createReg(Mips::GP));
1554 LwInst.addOperand(MCOperand::createExpr(Got16RelocExpr));
1555 Instructions.push_back(LwInst);
1556
1557 MCInst AddiuInst;
1558 AddiuInst.setOpcode(Mips::ADDiu);
1559 AddiuInst.addOperand(MCOperand::createReg(Mips::T9));
1560 AddiuInst.addOperand(MCOperand::createReg(Mips::T9));
1561 AddiuInst.addOperand(MCOperand::createExpr(Lo16RelocExpr));
1562 Instructions.push_back(AddiuInst);
1563 } else if (isABI_N32() || isABI_N64()) {
1564 // If it's a local symbol and the N32/N64 ABIs are being used,
1565 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001566 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001567 // R_(MICRO)MIPS_GOT_DISP label
1568 // jalr $25
1569 const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
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(GotDispRelocExpr));
1576 Instructions.push_back(LoadInst);
1577 }
1578 } else {
1579 // If it's an external/weak symbol, we expand to:
1580 // lw/ld $25, 0($gp)
1581 // R_(MICRO)MIPS_CALL16 label
1582 // jalr $25
1583 const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
1584
1585 MCInst LoadInst;
1586 LoadInst.setOpcode(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW);
1587 LoadInst.addOperand(MCOperand::createReg(Mips::T9));
1588 LoadInst.addOperand(MCOperand::createReg(Mips::GP));
1589 LoadInst.addOperand(MCOperand::createExpr(Call16RelocExpr));
1590 Instructions.push_back(LoadInst);
1591 }
1592
1593 MCInst JalrInst;
1594 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
1595 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1596 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1597
1598 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1599 // This relocation is supposed to be an optimization hint for the linker
1600 // and is not necessary for correctness.
1601
1602 Inst = JalrInst;
1603 }
1604
Jack Carter9e65aa32013-03-22 00:05:30 +00001605 if (MCID.mayLoad() || MCID.mayStore()) {
1606 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001607 // reference or immediate we may have to expand instructions.
1608 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001609 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001610 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1611 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001612 MCOperand &Op = Inst.getOperand(i);
1613 if (Op.isImm()) {
1614 int MemOffset = Op.getImm();
1615 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001616 // Offset can't exceed 16bit value.
1617 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001618 return false;
1619 }
1620 } else if (Op.isExpr()) {
1621 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001622 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001623 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001624 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001625 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001626 // Expand symbol.
1627 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001628 return false;
1629 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001630 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001631 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001632 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001633 }
1634 }
1635 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001636 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001637 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001638
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001639 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001640 if (MCID.mayLoad()) {
1641 // Try to create 16-bit GP relative load instruction.
1642 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1643 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1644 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1645 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1646 MCOperand &Op = Inst.getOperand(i);
1647 if (Op.isImm()) {
1648 int MemOffset = Op.getImm();
1649 MCOperand &DstReg = Inst.getOperand(0);
1650 MCOperand &BaseReg = Inst.getOperand(1);
1651 if (isIntN(9, MemOffset) && (MemOffset % 4 == 0) &&
1652 getContext().getRegisterInfo()->getRegClass(
1653 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
1654 BaseReg.getReg() == Mips::GP) {
1655 MCInst TmpInst;
1656 TmpInst.setLoc(IDLoc);
1657 TmpInst.setOpcode(Mips::LWGP_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00001658 TmpInst.addOperand(MCOperand::createReg(DstReg.getReg()));
1659 TmpInst.addOperand(MCOperand::createReg(Mips::GP));
1660 TmpInst.addOperand(MCOperand::createImm(MemOffset));
Jozef Koleke10a02e2015-01-28 17:27:26 +00001661 Instructions.push_back(TmpInst);
1662 return false;
1663 }
1664 }
1665 }
1666 } // for
1667 } // if load
1668
1669 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1670
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001671 MCOperand Opnd;
1672 int Imm;
1673
1674 switch (Inst.getOpcode()) {
1675 default:
1676 break;
1677 case Mips::ADDIUS5_MM:
1678 Opnd = Inst.getOperand(2);
1679 if (!Opnd.isImm())
1680 return Error(IDLoc, "expected immediate operand kind");
1681 Imm = Opnd.getImm();
1682 if (Imm < -8 || Imm > 7)
1683 return Error(IDLoc, "immediate operand value out of range");
1684 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001685 case Mips::ADDIUSP_MM:
1686 Opnd = Inst.getOperand(0);
1687 if (!Opnd.isImm())
1688 return Error(IDLoc, "expected immediate operand kind");
1689 Imm = Opnd.getImm();
1690 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1691 Imm % 4 != 0)
1692 return Error(IDLoc, "immediate operand value out of range");
1693 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001694 case Mips::SLL16_MM:
1695 case Mips::SRL16_MM:
1696 Opnd = Inst.getOperand(2);
1697 if (!Opnd.isImm())
1698 return Error(IDLoc, "expected immediate operand kind");
1699 Imm = Opnd.getImm();
1700 if (Imm < 1 || Imm > 8)
1701 return Error(IDLoc, "immediate operand value out of range");
1702 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001703 case Mips::LI16_MM:
1704 Opnd = Inst.getOperand(1);
1705 if (!Opnd.isImm())
1706 return Error(IDLoc, "expected immediate operand kind");
1707 Imm = Opnd.getImm();
1708 if (Imm < -1 || Imm > 126)
1709 return Error(IDLoc, "immediate operand value out of range");
1710 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001711 case Mips::ADDIUR2_MM:
1712 Opnd = Inst.getOperand(2);
1713 if (!Opnd.isImm())
1714 return Error(IDLoc, "expected immediate operand kind");
1715 Imm = Opnd.getImm();
1716 if (!(Imm == 1 || Imm == -1 ||
1717 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1718 return Error(IDLoc, "immediate operand value out of range");
1719 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001720 case Mips::ADDIUR1SP_MM:
1721 Opnd = Inst.getOperand(1);
1722 if (!Opnd.isImm())
1723 return Error(IDLoc, "expected immediate operand kind");
1724 Imm = Opnd.getImm();
1725 if (OffsetToAlignment(Imm, 4LL))
1726 return Error(IDLoc, "misaligned immediate operand value");
1727 if (Imm < 0 || Imm > 255)
1728 return Error(IDLoc, "immediate operand value out of range");
1729 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001730 case Mips::ANDI16_MM:
1731 Opnd = Inst.getOperand(2);
1732 if (!Opnd.isImm())
1733 return Error(IDLoc, "expected immediate operand kind");
1734 Imm = Opnd.getImm();
1735 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1736 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1737 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1738 return Error(IDLoc, "immediate operand value out of range");
1739 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001740 case Mips::LBU16_MM:
1741 Opnd = Inst.getOperand(2);
1742 if (!Opnd.isImm())
1743 return Error(IDLoc, "expected immediate operand kind");
1744 Imm = Opnd.getImm();
1745 if (Imm < -1 || Imm > 14)
1746 return Error(IDLoc, "immediate operand value out of range");
1747 break;
1748 case Mips::SB16_MM:
1749 Opnd = Inst.getOperand(2);
1750 if (!Opnd.isImm())
1751 return Error(IDLoc, "expected immediate operand kind");
1752 Imm = Opnd.getImm();
1753 if (Imm < 0 || Imm > 15)
1754 return Error(IDLoc, "immediate operand value out of range");
1755 break;
1756 case Mips::LHU16_MM:
1757 case Mips::SH16_MM:
1758 Opnd = Inst.getOperand(2);
1759 if (!Opnd.isImm())
1760 return Error(IDLoc, "expected immediate operand kind");
1761 Imm = Opnd.getImm();
1762 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1763 return Error(IDLoc, "immediate operand value out of range");
1764 break;
1765 case Mips::LW16_MM:
1766 case Mips::SW16_MM:
1767 Opnd = Inst.getOperand(2);
1768 if (!Opnd.isImm())
1769 return Error(IDLoc, "expected immediate operand kind");
1770 Imm = Opnd.getImm();
1771 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1772 return Error(IDLoc, "immediate operand value out of range");
1773 break;
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001774 case Mips::CACHE:
1775 case Mips::PREF:
1776 Opnd = Inst.getOperand(2);
1777 if (!Opnd.isImm())
1778 return Error(IDLoc, "expected immediate operand kind");
1779 Imm = Opnd.getImm();
1780 if (!isUInt<5>(Imm))
1781 return Error(IDLoc, "immediate operand value out of range");
1782 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001783 case Mips::ADDIUPC_MM:
1784 MCOperand Opnd = Inst.getOperand(1);
1785 if (!Opnd.isImm())
1786 return Error(IDLoc, "expected immediate operand kind");
1787 int Imm = Opnd.getImm();
1788 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1789 return Error(IDLoc, "immediate operand value out of range");
1790 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001791 }
1792 }
1793
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001794 if (needsExpansion(Inst)) {
1795 if (expandInstruction(Inst, IDLoc, Instructions))
1796 return true;
1797 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001798 Instructions.push_back(Inst);
1799
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001800 // If this instruction has a delay slot and .set reorder is active,
1801 // emit a NOP after it.
1802 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1803 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1804
Jack Carter9e65aa32013-03-22 00:05:30 +00001805 return false;
1806}
1807
Jack Carter30a59822012-10-04 04:03:53 +00001808bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1809
Jack Carterd0bd6422013-04-18 00:41:53 +00001810 switch (Inst.getOpcode()) {
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001811 case Mips::LoadImm32:
1812 case Mips::LoadImm64:
1813 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001814 case Mips::LoadAddrImm64:
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001815 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001816 case Mips::LoadAddrReg64:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001817 case Mips::B_MM_Pseudo:
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001818 case Mips::LWM_MM:
1819 case Mips::SWM_MM:
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001820 case Mips::JalOneReg:
1821 case Mips::JalTwoReg:
Toma Tabacue1e460d2015-06-11 10:36:10 +00001822 case Mips::BneImm:
1823 case Mips::BeqImm:
Toma Tabacu1a108322015-06-17 13:20:24 +00001824 case Mips::BLT:
1825 case Mips::BLE:
1826 case Mips::BGE:
1827 case Mips::BGT:
1828 case Mips::BLTU:
1829 case Mips::BLEU:
1830 case Mips::BGEU:
1831 case Mips::BGTU:
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00001832 case Mips::SDivMacro:
1833 case Mips::UDivMacro:
1834 case Mips::DSDivMacro:
1835 case Mips::DUDivMacro:
Toma Tabacud88d79c2015-06-23 14:39:42 +00001836 case Mips::Ulhu:
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00001837 case Mips::Ulw:
Jack Carterd0bd6422013-04-18 00:41:53 +00001838 return true;
1839 default:
1840 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001841 }
1842}
Jack Carter92995f12012-10-06 00:53:28 +00001843
Matheus Almeida3813d572014-06-19 14:39:14 +00001844bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001845 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001846 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001847 default: llvm_unreachable("unimplemented expansion");
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001848 case Mips::LoadImm32:
Toma Tabacu00e98672015-05-01 12:19:27 +00001849 return expandLoadImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001850 case Mips::LoadImm64:
Toma Tabacu00e98672015-05-01 12:19:27 +00001851 return expandLoadImm(Inst, false, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001852 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001853 case Mips::LoadAddrImm64:
1854 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1855 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1856 "expected immediate operand kind");
1857
1858 return expandLoadAddress(
1859 Inst.getOperand(0).getReg(), Mips::NoRegister, Inst.getOperand(1),
1860 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001861 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001862 case Mips::LoadAddrReg64:
1863 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1864 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1865 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
1866 "expected immediate operand kind");
1867
1868 return expandLoadAddress(
1869 Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(), Inst.getOperand(2),
1870 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001871 case Mips::B_MM_Pseudo:
1872 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001873 case Mips::SWM_MM:
1874 case Mips::LWM_MM:
1875 return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001876 case Mips::JalOneReg:
1877 case Mips::JalTwoReg:
1878 return expandJalWithRegs(Inst, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00001879 case Mips::BneImm:
1880 case Mips::BeqImm:
1881 return expandBranchImm(Inst, IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00001882 case Mips::BLT:
1883 case Mips::BLE:
1884 case Mips::BGE:
1885 case Mips::BGT:
1886 case Mips::BLTU:
1887 case Mips::BLEU:
1888 case Mips::BGEU:
1889 case Mips::BGTU:
1890 return expandCondBranches(Inst, IDLoc, Instructions);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00001891 case Mips::SDivMacro:
1892 return expandDiv(Inst, IDLoc, Instructions, false, true);
1893 case Mips::DSDivMacro:
1894 return expandDiv(Inst, IDLoc, Instructions, true, true);
1895 case Mips::UDivMacro:
1896 return expandDiv(Inst, IDLoc, Instructions, false, false);
1897 case Mips::DUDivMacro:
1898 return expandDiv(Inst, IDLoc, Instructions, true, false);
Toma Tabacud88d79c2015-06-23 14:39:42 +00001899 case Mips::Ulhu:
1900 return expandUlhu(Inst, IDLoc, Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00001901 case Mips::Ulw:
1902 return expandUlw(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001903 }
Jack Carter30a59822012-10-04 04:03:53 +00001904}
Jack Carter92995f12012-10-06 00:53:28 +00001905
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001906namespace {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001907void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc,
Daniel Sanders03f9c012015-07-14 12:24:22 +00001908 SmallVectorImpl<MCInst> &Instructions) {
1909 MCInst tmpInst;
1910 tmpInst.setOpcode(Opcode);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001911 tmpInst.addOperand(MCOperand::createReg(Reg0));
1912 tmpInst.addOperand(Op1);
Daniel Sanders03f9c012015-07-14 12:24:22 +00001913 tmpInst.setLoc(IDLoc);
1914 Instructions.push_back(tmpInst);
1915}
1916
Daniel Sandersf1ae3672015-08-18 09:55:57 +00001917void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc,
Daniel Sanders03f9c012015-07-14 12:24:22 +00001918 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001919 emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00001920}
1921
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00001922void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc,
1923 SmallVectorImpl<MCInst> &Instructions) {
1924 emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, Instructions);
1925}
1926
1927void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc,
1928 SmallVectorImpl<MCInst> &Instructions) {
1929 MCInst tmpInst;
1930 tmpInst.setOpcode(Opcode);
1931 tmpInst.addOperand(MCOperand::createImm(Imm1));
1932 tmpInst.addOperand(MCOperand::createImm(Imm2));
1933 tmpInst.setLoc(IDLoc);
1934 Instructions.push_back(tmpInst);
1935}
1936
1937void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
1938 SmallVectorImpl<MCInst> &Instructions) {
1939 MCInst tmpInst;
1940 tmpInst.setOpcode(Opcode);
1941 tmpInst.addOperand(MCOperand::createReg(Reg0));
1942 tmpInst.setLoc(IDLoc);
1943 Instructions.push_back(tmpInst);
1944}
1945
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001946void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2,
Daniel Sanders03f9c012015-07-14 12:24:22 +00001947 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1948 MCInst tmpInst;
1949 tmpInst.setOpcode(Opcode);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001950 tmpInst.addOperand(MCOperand::createReg(Reg0));
1951 tmpInst.addOperand(MCOperand::createReg(Reg1));
1952 tmpInst.addOperand(Op2);
Daniel Sanders03f9c012015-07-14 12:24:22 +00001953 tmpInst.setLoc(IDLoc);
1954 Instructions.push_back(tmpInst);
1955}
1956
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001957void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
Daniel Sanders03f9c012015-07-14 12:24:22 +00001958 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001959 emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc,
Daniel Sanders03f9c012015-07-14 12:24:22 +00001960 Instructions);
1961}
1962
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001963void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
1964 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1965 emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc,
1966 Instructions);
1967}
Daniel Sanders03f9c012015-07-14 12:24:22 +00001968
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001969void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount,
1970 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1971 if (ShiftAmount >= 32) {
1972 emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc,
1973 Instructions);
Toma Tabacu7dea2e32015-04-28 14:06:35 +00001974 return;
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001975 }
Toma Tabacu7dea2e32015-04-28 14:06:35 +00001976
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001977 emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001978}
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001979} // end anonymous namespace.
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001980
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001981bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
1982 SmallVectorImpl<MCInst> &Instructions) {
1983 // Create a JALR instruction which is going to replace the pseudo-JAL.
1984 MCInst JalrInst;
1985 JalrInst.setLoc(IDLoc);
1986 const MCOperand FirstRegOp = Inst.getOperand(0);
1987 const unsigned Opcode = Inst.getOpcode();
1988
1989 if (Opcode == Mips::JalOneReg) {
1990 // jal $rs => jalr $rs
1991 if (inMicroMipsMode()) {
1992 JalrInst.setOpcode(Mips::JALR16_MM);
1993 JalrInst.addOperand(FirstRegOp);
1994 } else {
1995 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00001996 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001997 JalrInst.addOperand(FirstRegOp);
1998 }
1999 } else if (Opcode == Mips::JalTwoReg) {
2000 // jal $rd, $rs => jalr $rd, $rs
2001 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
2002 JalrInst.addOperand(FirstRegOp);
2003 const MCOperand SecondRegOp = Inst.getOperand(1);
2004 JalrInst.addOperand(SecondRegOp);
2005 }
2006 Instructions.push_back(JalrInst);
2007
2008 // If .set reorder is active, emit a NOP after it.
2009 if (AssemblerOptions.back()->isReorder()) {
2010 // This is a 32-bit NOP because these 2 pseudo-instructions
2011 // do not have a short delay slot.
2012 MCInst NopInst;
2013 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00002014 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2015 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2016 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002017 Instructions.push_back(NopInst);
2018 }
2019
2020 return false;
2021}
2022
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002023/// Can the value be represented by a unsigned N-bit value and a shift left?
2024template<unsigned N>
2025bool isShiftedUIntAtAnyPosition(uint64_t x) {
2026 unsigned BitNum = findFirstSet(x);
2027
2028 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2029}
2030
2031/// Load (or add) an immediate into a register.
2032///
2033/// @param ImmValue The immediate to load.
2034/// @param DstReg The register that will hold the immediate.
2035/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2036/// for a simple initialization.
2037/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2038/// @param IsAddress True if the immediate represents an address. False if it
2039/// is an integer.
2040/// @param IDLoc Location of the immediate in the source file.
2041/// @param Instructions The instructions emitted by this expansion.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002042bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002043 unsigned SrcReg, bool Is32BitImm,
2044 bool IsAddress, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00002045 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00002046 if (!Is32BitImm && !isGP64bit()) {
2047 Error(IDLoc, "instruction requires a 64-bit architecture");
2048 return true;
2049 }
2050
Daniel Sanders03f9c012015-07-14 12:24:22 +00002051 if (Is32BitImm) {
2052 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2053 // Sign extend up to 64-bit so that the predicates match the hardware
2054 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2055 // true.
2056 ImmValue = SignExtend64<32>(ImmValue);
2057 } else {
2058 Error(IDLoc, "instruction requires a 32-bit immediate");
2059 return true;
2060 }
2061 }
2062
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002063 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2064 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2065
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002066 bool UseSrcReg = false;
2067 if (SrcReg != Mips::NoRegister)
2068 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002069
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002070 unsigned TmpReg = DstReg;
2071 if (UseSrcReg && (DstReg == SrcReg)) {
2072 // At this point we need AT to perform the expansions and we exit if it is
2073 // not available.
2074 unsigned ATReg = getATReg(IDLoc);
2075 if (!ATReg)
2076 return true;
2077 TmpReg = ATReg;
2078 }
2079
Daniel Sanders03f9c012015-07-14 12:24:22 +00002080 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002081 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002082 SrcReg = ZeroReg;
2083
2084 // This doesn't quite follow the usual ABI expectations for N32 but matches
2085 // traditional assembler behaviour. N32 would normally use addiu for both
2086 // integers and addresses.
2087 if (IsAddress && !Is32BitImm) {
2088 emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2089 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002090 }
2091
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002092 emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2093 return false;
2094 }
2095
2096 if (isUInt<16>(ImmValue)) {
2097 unsigned TmpReg = DstReg;
2098 if (SrcReg == DstReg) {
2099 TmpReg = getATReg(IDLoc);
2100 if (!TmpReg)
2101 return true;
2102 }
2103
2104 emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002105 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002106 emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2107 return false;
2108 }
2109
2110 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002111 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002112
Toma Tabacu79588102015-04-29 10:19:56 +00002113 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2114 uint16_t Bits15To0 = ImmValue & 0xffff;
2115
Toma Tabacua3d056f2015-05-15 09:42:11 +00002116 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002117 // Traditional behaviour seems to special case this particular value. It's
2118 // not clear why other masks are handled differently.
2119 if (ImmValue == 0xffffffff) {
Daniel Sandersf1ae3672015-08-18 09:55:57 +00002120 emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002121 emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, Instructions);
2122 if (UseSrcReg)
2123 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2124 return false;
2125 }
2126
2127 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002128 // upper 32 bits.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002129 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002130 emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002131 if (Bits15To0)
2132 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
2133 if (UseSrcReg)
2134 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2135 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002136 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002137
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002138 emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions);
2139 if (Bits15To0)
2140 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002141 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002142 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2143 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002144 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002145
2146 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2147 if (Is32BitImm) {
2148 Error(IDLoc, "instruction requires a 32-bit immediate");
2149 return true;
2150 }
2151
2152 // Traditionally, these immediates are shifted as little as possible and as
2153 // such we align the most significant bit to bit 15 of our temporary.
2154 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2155 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2156 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2157 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
2158 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, Instructions);
2159 emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, Instructions);
2160
2161 if (UseSrcReg)
2162 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2163
2164 return false;
2165 }
2166
2167 warnIfNoMacro(IDLoc);
2168
2169 // The remaining case is packed with a sequence of dsll and ori with zeros
2170 // being omitted and any neighbouring dsll's being coalesced.
2171 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2172
2173 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2174 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
2175 IDLoc, Instructions))
2176 return false;
2177
2178 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2179 // skip it and defer the shift to the next chunk.
2180 unsigned ShiftCarriedForwards = 16;
2181 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2182 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2183
2184 if (ImmChunk != 0) {
2185 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2186 Instructions);
2187 emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, Instructions);
2188 ShiftCarriedForwards = 0;
2189 }
2190
2191 ShiftCarriedForwards += 16;
2192 }
2193 ShiftCarriedForwards -= 16;
2194
2195 // Finish any remaining shifts left by trailing zeros.
2196 if (ShiftCarriedForwards)
2197 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2198 Instructions);
2199
2200 if (UseSrcReg)
2201 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2202
Matheus Almeida3813d572014-06-19 14:39:14 +00002203 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002204}
Jack Carter92995f12012-10-06 00:53:28 +00002205
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002206bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
2207 SmallVectorImpl<MCInst> &Instructions) {
2208 const MCOperand &ImmOp = Inst.getOperand(1);
2209 assert(ImmOp.isImm() && "expected immediate operand kind");
2210 const MCOperand &DstRegOp = Inst.getOperand(0);
2211 assert(DstRegOp.isReg() && "expected register operand kind");
2212
2213 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002214 Is32BitImm, false, IDLoc, Instructions))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002215 return true;
2216
2217 return false;
2218}
2219
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002220bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2221 const MCOperand &Offset,
2222 bool Is32BitAddress, SMLoc IDLoc,
2223 SmallVectorImpl<MCInst> &Instructions) {
2224 // la can't produce a usable address when addresses are 64-bit.
2225 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2226 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2227 // We currently can't do this because we depend on the equality
2228 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2229 Error(IDLoc, "la used to load 64-bit address");
2230 // Continue as if we had 'dla' instead.
2231 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002232 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002233
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002234 // dla requires 64-bit addresses.
2235 if (!Is32BitAddress && !ABI.ArePtrs64bit()) {
2236 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002237 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002238 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002239
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002240 if (!Offset.isImm())
2241 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
2242 Is32BitAddress, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002243
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002244 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
2245 IDLoc, Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +00002246}
2247
Toma Tabacuf712ede2015-06-17 14:31:51 +00002248bool MipsAsmParser::loadAndAddSymbolAddress(
2249 const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
2250 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002251 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002252
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002253 // FIXME: The way we're handling symbols right now prevents simple expressions
2254 // like foo+8. We'll be able to fix this once our unary operators (%hi
2255 // and similar) are treated as operators rather than as fixup types.
Toma Tabacu674825c2015-06-16 12:16:24 +00002256 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymExpr);
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002257 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::create(
2258 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
2259 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::create(
2260 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
2261
Toma Tabacufb9d1252015-06-22 12:08:39 +00002262 bool UseSrcReg = SrcReg != Mips::NoRegister;
2263
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002264 // This is the 64-bit symbol address expansion.
2265 if (ABI.ArePtrs64bit() && isGP64bit()) {
2266 // We always need AT for the 64-bit expansion.
2267 // If it is not available we exit.
2268 unsigned ATReg = getATReg(IDLoc);
2269 if (!ATReg)
2270 return true;
2271
2272 const MCSymbolRefExpr *HighestExpr = MCSymbolRefExpr::create(
2273 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
2274 const MCSymbolRefExpr *HigherExpr = MCSymbolRefExpr::create(
2275 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
2276
2277 if (UseSrcReg && (DstReg == SrcReg)) {
2278 // If $rs is the same as $rd:
2279 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2280 // daddiu $at, $at, %higher(sym)
2281 // dsll $at, $at, 16
2282 // daddiu $at, $at, %hi(sym)
2283 // dsll $at, $at, 16
2284 // daddiu $at, $at, %lo(sym)
2285 // daddu $rd, $at, $rd
2286 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2287 Instructions);
2288 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr),
2289 IDLoc, Instructions);
2290 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2291 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2292 Instructions);
2293 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2294 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2295 Instructions);
2296 emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions);
2297
2298 return false;
2299 }
2300
2301 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2302 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2303 // lui $at, %hi(sym)
2304 // daddiu $rd, $rd, %higher(sym)
2305 // daddiu $at, $at, %lo(sym)
2306 // dsll32 $rd, $rd, 0
2307 // daddu $rd, $rd, $at
2308 // (daddu $rd, $rd, $rs)
2309 emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2310 Instructions);
2311 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2312 Instructions);
2313 emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr),
2314 IDLoc, Instructions);
2315 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2316 Instructions);
2317 emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions);
2318 emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions);
2319 if (UseSrcReg)
2320 emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions);
2321
2322 return false;
2323 }
2324
2325 // And now, the 32-bit symbol address expansion:
2326 // If $rs is the same as $rd:
2327 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2328 // ori $at, $at, %lo(sym)
2329 // addu $rd, $at, $rd
2330 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2331 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2332 // ori $rd, $rd, %lo(sym)
2333 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002334 unsigned TmpReg = DstReg;
2335 if (UseSrcReg && (DstReg == SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002336 // If $rs is the same as $rd, we need to use AT.
2337 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002338 unsigned ATReg = getATReg(IDLoc);
2339 if (!ATReg)
2340 return true;
2341 TmpReg = ATReg;
2342 }
2343
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002344 emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions);
2345 emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc,
2346 Instructions);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002347
Toma Tabacufb9d1252015-06-22 12:08:39 +00002348 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002349 emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2350 else
2351 assert(DstReg == TmpReg);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002352
Toma Tabacu674825c2015-06-16 12:16:24 +00002353 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002354}
2355
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002356bool MipsAsmParser::expandUncondBranchMMPseudo(
2357 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002358 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2359 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002360
2361 MCOperand Offset = Inst.getOperand(0);
2362 if (Offset.isExpr()) {
2363 Inst.clear();
2364 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002365 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2366 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2367 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002368 } else {
2369 assert(Offset.isImm() && "expected immediate operand kind");
2370 if (isIntN(11, Offset.getImm())) {
2371 // If offset fits into 11 bits then this instruction becomes microMIPS
2372 // 16-bit unconditional branch instruction.
2373 Inst.setOpcode(Mips::B16_MM);
2374 } else {
2375 if (!isIntN(17, Offset.getImm()))
2376 Error(IDLoc, "branch target out of range");
2377 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2378 Error(IDLoc, "branch to misaligned address");
2379 Inst.clear();
2380 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002381 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2382 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2383 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002384 }
2385 }
2386 Instructions.push_back(Inst);
2387
Toma Tabacu234482a2015-03-16 12:03:39 +00002388 // If .set reorder is active, emit a NOP after the branch instruction.
2389 if (AssemblerOptions.back()->isReorder())
2390 createNop(true, IDLoc, Instructions);
2391
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002392 return false;
2393}
2394
Toma Tabacue1e460d2015-06-11 10:36:10 +00002395bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2396 SmallVectorImpl<MCInst> &Instructions) {
2397 const MCOperand &DstRegOp = Inst.getOperand(0);
2398 assert(DstRegOp.isReg() && "expected register operand kind");
2399
2400 const MCOperand &ImmOp = Inst.getOperand(1);
2401 assert(ImmOp.isImm() && "expected immediate operand kind");
2402
2403 const MCOperand &MemOffsetOp = Inst.getOperand(2);
2404 assert(MemOffsetOp.isImm() && "expected immediate operand kind");
2405
2406 unsigned OpCode = 0;
2407 switch(Inst.getOpcode()) {
2408 case Mips::BneImm:
2409 OpCode = Mips::BNE;
2410 break;
2411 case Mips::BeqImm:
2412 OpCode = Mips::BEQ;
2413 break;
2414 default:
2415 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2416 break;
2417 }
2418
2419 int64_t ImmValue = ImmOp.getImm();
2420 if (ImmValue == 0) {
2421 MCInst BranchInst;
2422 BranchInst.setOpcode(OpCode);
2423 BranchInst.addOperand(DstRegOp);
2424 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2425 BranchInst.addOperand(MemOffsetOp);
2426 Instructions.push_back(BranchInst);
2427 } else {
2428 warnIfNoMacro(IDLoc);
2429
2430 unsigned ATReg = getATReg(IDLoc);
2431 if (!ATReg)
2432 return true;
2433
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002434 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
2435 IDLoc, Instructions))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002436 return true;
2437
2438 MCInst BranchInst;
2439 BranchInst.setOpcode(OpCode);
2440 BranchInst.addOperand(DstRegOp);
2441 BranchInst.addOperand(MCOperand::createReg(ATReg));
2442 BranchInst.addOperand(MemOffsetOp);
2443 Instructions.push_back(BranchInst);
2444 }
2445 return false;
2446}
2447
Jack Carter9e65aa32013-03-22 00:05:30 +00002448void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002449 SmallVectorImpl<MCInst> &Instructions,
2450 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002451 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00002452 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002453 const MCExpr *ExprOffset;
2454 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002455 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002456 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2457 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002458 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002459 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2460 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002461 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002462 if (isImmOpnd) {
2463 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2464 ImmOffset = Inst.getOperand(2).getImm();
2465 LoOffset = ImmOffset & 0x0000ffff;
2466 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002467 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002468 if (LoOffset & 0x8000)
2469 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002470 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002471 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002472 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002473 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002474 // These are some of the types of expansions we perform here:
2475 // 1) lw $8, sym => lui $8, %hi(sym)
2476 // lw $8, %lo(sym)($8)
2477 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2478 // add $8, $8, $9
2479 // lw $8, %lo(offset)($9)
2480 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2481 // add $at, $at, $8
2482 // lw $8, %lo(offset)($at)
2483 // 4) sw $8, sym => lui $at, %hi(sym)
2484 // sw $8, %lo(sym)($at)
2485 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2486 // add $at, $at, $8
2487 // sw $8, %lo(offset)($at)
2488 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2489 // ldc1 $f0, %lo(sym)($at)
2490 //
2491 // For load instructions we can use the destination register as a temporary
2492 // if base and dst are different (examples 1 and 2) and if the base register
2493 // is general purpose otherwise we must use $at (example 6) and error if it's
2494 // not available. For stores we must use $at (examples 4 and 5) because we
2495 // must not clobber the source register setting up the offset.
2496 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2497 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2498 unsigned RegClassIDOp0 =
2499 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2500 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2501 (RegClassIDOp0 == Mips::GPR64RegClassID);
2502 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002503 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002504 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002505 // At this point we need AT to perform the expansions and we exit if it is
2506 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002507 TmpRegNum = getATReg(IDLoc);
2508 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002509 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002510 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002511
Jack Carter9e65aa32013-03-22 00:05:30 +00002512 TempInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00002513 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002514 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002515 TempInst.addOperand(MCOperand::createImm(HiOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002516 else {
Toma Tabacu07c97b32015-06-17 10:43:45 +00002517 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
2518 TempInst.addOperand(MCOperand::createExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002519 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002520 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002521 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002522 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002523 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002524 // Add temp register to base.
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002525 if (BaseRegNum != Mips::ZERO) {
2526 TempInst.setOpcode(Mips::ADDu);
Jim Grosbache9119e42015-05-13 18:37:00 +00002527 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2528 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2529 TempInst.addOperand(MCOperand::createReg(BaseRegNum));
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002530 Instructions.push_back(TempInst);
2531 TempInst.clear();
2532 }
Alp Tokercb402912014-01-24 17:20:08 +00002533 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002534 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002535 TempInst.setOpcode(Inst.getOpcode());
Jim Grosbache9119e42015-05-13 18:37:00 +00002536 TempInst.addOperand(MCOperand::createReg(RegOpNum));
2537 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002538 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002539 TempInst.addOperand(MCOperand::createImm(LoOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002540 else {
Toma Tabacu07c97b32015-06-17 10:43:45 +00002541 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
2542 TempInst.addOperand(MCOperand::createExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002543 }
2544 Instructions.push_back(TempInst);
2545 TempInst.clear();
2546}
2547
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002548bool
2549MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2550 SmallVectorImpl<MCInst> &Instructions) {
2551 unsigned OpNum = Inst.getNumOperands();
2552 unsigned Opcode = Inst.getOpcode();
2553 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2554
2555 assert (Inst.getOperand(OpNum - 1).isImm() &&
2556 Inst.getOperand(OpNum - 2).isReg() &&
2557 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2558
2559 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2560 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2561 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2562 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2563 // It can be implemented as SWM16 or LWM16 instruction.
2564 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2565
2566 Inst.setOpcode(NewOpcode);
2567 Instructions.push_back(Inst);
2568 return false;
2569}
2570
Toma Tabacu1a108322015-06-17 13:20:24 +00002571bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2572 SmallVectorImpl<MCInst> &Instructions) {
2573 unsigned PseudoOpcode = Inst.getOpcode();
2574 unsigned SrcReg = Inst.getOperand(0).getReg();
2575 unsigned TrgReg = Inst.getOperand(1).getReg();
2576 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2577
2578 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
2579 bool ReverseOrderSLT, IsUnsigned, AcceptsEquality;
2580
2581 switch (PseudoOpcode) {
2582 case Mips::BLT:
2583 case Mips::BLTU:
2584 AcceptsEquality = false;
2585 ReverseOrderSLT = false;
2586 IsUnsigned = (PseudoOpcode == Mips::BLTU);
2587 ZeroSrcOpcode = Mips::BGTZ;
2588 ZeroTrgOpcode = Mips::BLTZ;
2589 break;
2590 case Mips::BLE:
2591 case Mips::BLEU:
2592 AcceptsEquality = true;
2593 ReverseOrderSLT = true;
2594 IsUnsigned = (PseudoOpcode == Mips::BLEU);
2595 ZeroSrcOpcode = Mips::BGEZ;
2596 ZeroTrgOpcode = Mips::BLEZ;
2597 break;
2598 case Mips::BGE:
2599 case Mips::BGEU:
2600 AcceptsEquality = true;
2601 ReverseOrderSLT = false;
2602 IsUnsigned = (PseudoOpcode == Mips::BGEU);
2603 ZeroSrcOpcode = Mips::BLEZ;
2604 ZeroTrgOpcode = Mips::BGEZ;
2605 break;
2606 case Mips::BGT:
2607 case Mips::BGTU:
2608 AcceptsEquality = false;
2609 ReverseOrderSLT = true;
2610 IsUnsigned = (PseudoOpcode == Mips::BGTU);
2611 ZeroSrcOpcode = Mips::BLTZ;
2612 ZeroTrgOpcode = Mips::BGTZ;
2613 break;
2614 default:
2615 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2616 }
2617
2618 MCInst BranchInst;
2619 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2620 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2621 if (IsSrcRegZero && IsTrgRegZero) {
2622 // FIXME: All of these Opcode-specific if's are needed for compatibility
2623 // with GAS' behaviour. However, they may not generate the most efficient
2624 // code in some circumstances.
2625 if (PseudoOpcode == Mips::BLT) {
2626 BranchInst.setOpcode(Mips::BLTZ);
2627 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2628 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2629 Instructions.push_back(BranchInst);
2630 return false;
2631 }
2632 if (PseudoOpcode == Mips::BLE) {
2633 BranchInst.setOpcode(Mips::BLEZ);
2634 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2635 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2636 Instructions.push_back(BranchInst);
2637 Warning(IDLoc, "branch is always taken");
2638 return false;
2639 }
2640 if (PseudoOpcode == Mips::BGE) {
2641 BranchInst.setOpcode(Mips::BGEZ);
2642 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2643 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2644 Instructions.push_back(BranchInst);
2645 Warning(IDLoc, "branch is always taken");
2646 return false;
2647 }
2648 if (PseudoOpcode == Mips::BGT) {
2649 BranchInst.setOpcode(Mips::BGTZ);
2650 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2651 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2652 Instructions.push_back(BranchInst);
2653 return false;
2654 }
2655 if (PseudoOpcode == Mips::BGTU) {
2656 BranchInst.setOpcode(Mips::BNE);
2657 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2658 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2659 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2660 Instructions.push_back(BranchInst);
2661 return false;
2662 }
2663 if (AcceptsEquality) {
2664 // If both registers are $0 and the pseudo-branch accepts equality, it
2665 // will always be taken, so we emit an unconditional branch.
2666 BranchInst.setOpcode(Mips::BEQ);
2667 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2668 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2669 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2670 Instructions.push_back(BranchInst);
2671 Warning(IDLoc, "branch is always taken");
2672 return false;
2673 }
2674 // If both registers are $0 and the pseudo-branch does not accept
2675 // equality, it will never be taken, so we don't have to emit anything.
2676 return false;
2677 }
2678 if (IsSrcRegZero || IsTrgRegZero) {
2679 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2680 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2681 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2682 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2683 // the pseudo-branch will never be taken, so we don't emit anything.
2684 // This only applies to unsigned pseudo-branches.
2685 return false;
2686 }
2687 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2688 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2689 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2690 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2691 // the pseudo-branch will always be taken, so we emit an unconditional
2692 // branch.
2693 // This only applies to unsigned pseudo-branches.
2694 BranchInst.setOpcode(Mips::BEQ);
2695 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2696 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2697 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2698 Instructions.push_back(BranchInst);
2699 Warning(IDLoc, "branch is always taken");
2700 return false;
2701 }
2702 if (IsUnsigned) {
2703 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2704 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2705 // the pseudo-branch will be taken only when the non-zero register is
2706 // different from 0, so we emit a BNEZ.
2707 //
2708 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2709 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2710 // the pseudo-branch will be taken only when the non-zero register is
2711 // equal to 0, so we emit a BEQZ.
2712 //
2713 // Because only BLEU and BGEU branch on equality, we can use the
2714 // AcceptsEquality variable to decide when to emit the BEQZ.
2715 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQ : Mips::BNE);
2716 BranchInst.addOperand(
2717 MCOperand::createReg(IsSrcRegZero ? TrgReg : SrcReg));
2718 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2719 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2720 Instructions.push_back(BranchInst);
2721 return false;
2722 }
2723 // If we have a signed pseudo-branch and one of the registers is $0,
2724 // we can use an appropriate compare-to-zero branch. We select which one
2725 // to use in the switch statement above.
2726 BranchInst.setOpcode(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode);
2727 BranchInst.addOperand(MCOperand::createReg(IsSrcRegZero ? TrgReg : SrcReg));
2728 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2729 Instructions.push_back(BranchInst);
2730 return false;
2731 }
2732
2733 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2734 // expansions. If it is not available, we return.
2735 unsigned ATRegNum = getATReg(IDLoc);
2736 if (!ATRegNum)
2737 return true;
2738
2739 warnIfNoMacro(IDLoc);
2740
2741 // SLT fits well with 2 of our 4 pseudo-branches:
2742 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2743 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2744 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2745 // This is accomplished by using a BNEZ with the result of the SLT.
2746 //
2747 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2748 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2749 // Because only BGE and BLE branch on equality, we can use the
2750 // AcceptsEquality variable to decide when to emit the BEQZ.
2751 // Note that the order of the SLT arguments doesn't change between
2752 // opposites.
2753 //
2754 // The same applies to the unsigned variants, except that SLTu is used
2755 // instead of SLT.
2756 MCInst SetInst;
2757 SetInst.setOpcode(IsUnsigned ? Mips::SLTu : Mips::SLT);
2758 SetInst.addOperand(MCOperand::createReg(ATRegNum));
2759 SetInst.addOperand(MCOperand::createReg(ReverseOrderSLT ? TrgReg : SrcReg));
2760 SetInst.addOperand(MCOperand::createReg(ReverseOrderSLT ? SrcReg : TrgReg));
2761 Instructions.push_back(SetInst);
2762
2763 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQ : Mips::BNE);
2764 BranchInst.addOperand(MCOperand::createReg(ATRegNum));
2765 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2766 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2767 Instructions.push_back(BranchInst);
2768 return false;
2769}
2770
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002771bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
2772 SmallVectorImpl<MCInst> &Instructions,
2773 const bool IsMips64, const bool Signed) {
2774 if (hasMips32r6()) {
2775 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2776 return false;
2777 }
2778
2779 warnIfNoMacro(IDLoc);
2780
2781 const MCOperand &RsRegOp = Inst.getOperand(0);
2782 assert(RsRegOp.isReg() && "expected register operand kind");
2783 unsigned RsReg = RsRegOp.getReg();
2784
2785 const MCOperand &RtRegOp = Inst.getOperand(1);
2786 assert(RtRegOp.isReg() && "expected register operand kind");
2787 unsigned RtReg = RtRegOp.getReg();
2788 unsigned DivOp;
2789 unsigned ZeroReg;
2790
2791 if (IsMips64) {
2792 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2793 ZeroReg = Mips::ZERO_64;
2794 } else {
2795 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2796 ZeroReg = Mips::ZERO;
2797 }
2798
2799 bool UseTraps = useTraps();
2800
2801 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2802 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2803 Warning(IDLoc, "dividing zero by zero");
2804 if (IsMips64) {
2805 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2806 if (UseTraps) {
2807 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2808 return false;
2809 }
2810
2811 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2812 return false;
2813 }
2814 } else {
2815 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2816 return false;
2817 }
2818 }
2819
2820 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
2821 Warning(IDLoc, "division by zero");
2822 if (Signed) {
2823 if (UseTraps) {
2824 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2825 return false;
2826 }
2827
2828 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2829 return false;
2830 }
2831 }
2832
2833 // FIXME: The values for these two BranchTarget variables may be different in
2834 // micromips. These magic numbers need to be removed.
2835 unsigned BranchTargetNoTraps;
2836 unsigned BranchTarget;
2837
2838 if (UseTraps) {
2839 BranchTarget = IsMips64 ? 12 : 8;
2840 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2841 } else {
2842 BranchTarget = IsMips64 ? 20 : 16;
2843 BranchTargetNoTraps = 8;
2844 // Branch to the li instruction.
2845 emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc,
2846 Instructions);
2847 }
2848
2849 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2850
2851 if (!UseTraps)
2852 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2853
2854 if (!Signed) {
2855 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
2856 return false;
2857 }
2858
2859 unsigned ATReg = getATReg(IDLoc);
2860 if (!ATReg)
2861 return true;
2862
2863 emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, Instructions);
2864 if (IsMips64) {
2865 // Branch to the mflo instruction.
2866 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
2867 emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, Instructions);
2868 emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, Instructions);
2869 } else {
2870 // Branch to the mflo instruction.
2871 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
2872 emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, Instructions);
2873 }
2874
2875 if (UseTraps)
2876 emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, Instructions);
2877 else {
2878 // Branch to the mflo instruction.
2879 emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, Instructions);
2880 emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, Instructions);
2881 emitII(Mips::BREAK, 0x6, 0, IDLoc, Instructions);
2882 }
2883 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
2884 return false;
2885}
2886
Toma Tabacud88d79c2015-06-23 14:39:42 +00002887bool MipsAsmParser::expandUlhu(MCInst &Inst, SMLoc IDLoc,
2888 SmallVectorImpl<MCInst> &Instructions) {
2889 if (hasMips32r6() || hasMips64r6()) {
2890 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2891 return false;
2892 }
2893
2894 warnIfNoMacro(IDLoc);
2895
2896 const MCOperand &DstRegOp = Inst.getOperand(0);
2897 assert(DstRegOp.isReg() && "expected register operand kind");
2898
2899 const MCOperand &SrcRegOp = Inst.getOperand(1);
2900 assert(SrcRegOp.isReg() && "expected register operand kind");
2901
2902 const MCOperand &OffsetImmOp = Inst.getOperand(2);
2903 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
2904
2905 unsigned DstReg = DstRegOp.getReg();
2906 unsigned SrcReg = SrcRegOp.getReg();
2907 int64_t OffsetValue = OffsetImmOp.getImm();
2908
2909 // NOTE: We always need AT for ULHU, as it is always used as the source
2910 // register for one of the LBu's.
2911 unsigned ATReg = getATReg(IDLoc);
2912 if (!ATReg)
2913 return true;
2914
2915 // When the value of offset+1 does not fit in 16 bits, we have to load the
2916 // offset in AT, (D)ADDu the original source register (if there was one), and
2917 // then use AT as the source register for the 2 generated LBu's.
2918 bool LoadedOffsetInAT = false;
2919 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
2920 LoadedOffsetInAT = true;
2921
2922 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002923 true, IDLoc, Instructions))
Toma Tabacud88d79c2015-06-23 14:39:42 +00002924 return true;
2925
2926 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
2927 // because it will make our output more similar to GAS'. For example,
2928 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
2929 // instead of just an "ori $1, $9, 32768".
2930 // NOTE: If there is no source register specified in the ULHU, the parser
2931 // will interpret it as $0.
2932 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
2933 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
2934 }
2935
2936 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
2937 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
2938 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
2939
2940 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
2941 if (isLittle()) {
2942 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
2943 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
2944 } else {
2945 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
2946 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
2947 }
2948
2949 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
2950
2951 MCInst TmpInst;
2952 TmpInst.setOpcode(Mips::LBu);
2953 TmpInst.addOperand(MCOperand::createReg(FirstLbuDstReg));
2954 TmpInst.addOperand(MCOperand::createReg(LbuSrcReg));
2955 TmpInst.addOperand(MCOperand::createImm(FirstLbuOffset));
2956 Instructions.push_back(TmpInst);
2957
2958 TmpInst.clear();
2959 TmpInst.setOpcode(Mips::LBu);
2960 TmpInst.addOperand(MCOperand::createReg(SecondLbuDstReg));
2961 TmpInst.addOperand(MCOperand::createReg(LbuSrcReg));
2962 TmpInst.addOperand(MCOperand::createImm(SecondLbuOffset));
2963 Instructions.push_back(TmpInst);
2964
2965 TmpInst.clear();
2966 TmpInst.setOpcode(Mips::SLL);
2967 TmpInst.addOperand(MCOperand::createReg(SllReg));
2968 TmpInst.addOperand(MCOperand::createReg(SllReg));
2969 TmpInst.addOperand(MCOperand::createImm(8));
2970 Instructions.push_back(TmpInst);
2971
2972 TmpInst.clear();
2973 TmpInst.setOpcode(Mips::OR);
2974 TmpInst.addOperand(MCOperand::createReg(DstReg));
2975 TmpInst.addOperand(MCOperand::createReg(DstReg));
2976 TmpInst.addOperand(MCOperand::createReg(ATReg));
2977 Instructions.push_back(TmpInst);
2978
2979 return false;
2980}
2981
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00002982bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
2983 SmallVectorImpl<MCInst> &Instructions) {
2984 if (hasMips32r6() || hasMips64r6()) {
2985 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2986 return false;
2987 }
2988
2989 const MCOperand &DstRegOp = Inst.getOperand(0);
2990 assert(DstRegOp.isReg() && "expected register operand kind");
2991
2992 const MCOperand &SrcRegOp = Inst.getOperand(1);
2993 assert(SrcRegOp.isReg() && "expected register operand kind");
2994
2995 const MCOperand &OffsetImmOp = Inst.getOperand(2);
2996 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
2997
2998 unsigned SrcReg = SrcRegOp.getReg();
2999 int64_t OffsetValue = OffsetImmOp.getImm();
3000 unsigned ATReg = 0;
3001
3002 // When the value of offset+3 does not fit in 16 bits, we have to load the
3003 // offset in AT, (D)ADDu the original source register (if there was one), and
3004 // then use AT as the source register for the generated LWL and LWR.
3005 bool LoadedOffsetInAT = false;
3006 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3007 ATReg = getATReg(IDLoc);
3008 if (!ATReg)
3009 return true;
3010 LoadedOffsetInAT = true;
3011
3012 warnIfNoMacro(IDLoc);
3013
3014 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003015 true, IDLoc, Instructions))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003016 return true;
3017
3018 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3019 // because it will make our output more similar to GAS'. For example,
3020 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3021 // instead of just an "ori $1, $9, 32768".
3022 // NOTE: If there is no source register specified in the ULW, the parser
3023 // will interpret it as $0.
3024 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3025 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3026 }
3027
3028 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3029 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3030 if (isLittle()) {
3031 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3032 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3033 } else {
3034 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3035 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3036 }
3037
3038 MCInst LeftLoadInst;
3039 LeftLoadInst.setOpcode(Mips::LWL);
3040 LeftLoadInst.addOperand(DstRegOp);
3041 LeftLoadInst.addOperand(MCOperand::createReg(FinalSrcReg));
3042 LeftLoadInst.addOperand(MCOperand::createImm(LeftLoadOffset));
3043 Instructions.push_back(LeftLoadInst);
3044
3045 MCInst RightLoadInst;
3046 RightLoadInst.setOpcode(Mips::LWR);
3047 RightLoadInst.addOperand(DstRegOp);
3048 RightLoadInst.addOperand(MCOperand::createReg(FinalSrcReg));
3049 RightLoadInst.addOperand(MCOperand::createImm(RightLoadOffset ));
3050 Instructions.push_back(RightLoadInst);
3051
3052 return false;
3053}
3054
Toma Tabacu234482a2015-03-16 12:03:39 +00003055void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
3056 SmallVectorImpl<MCInst> &Instructions) {
3057 MCInst NopInst;
3058 if (hasShortDelaySlot) {
3059 NopInst.setOpcode(Mips::MOVE16_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003060 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
3061 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
Toma Tabacu234482a2015-03-16 12:03:39 +00003062 } else {
3063 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00003064 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
3065 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
3066 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu234482a2015-03-16 12:03:39 +00003067 }
3068 Instructions.push_back(NopInst);
3069}
3070
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003071void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +00003072 unsigned TrgReg, bool Is64Bit,
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003073 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders03f9c012015-07-14 12:24:22 +00003074 emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
3075 Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003076}
3077
Matheus Almeida595fcab2014-06-11 15:05:56 +00003078unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3079 // As described by the Mips32r2 spec, the registers Rd and Rs for
3080 // jalr.hb must be different.
3081 unsigned Opcode = Inst.getOpcode();
3082
3083 if (Opcode == Mips::JALR_HB &&
3084 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3085 return Match_RequiresDifferentSrcAndDst;
3086
3087 return Match_Success;
3088}
3089
David Blaikie960ea3f2014-06-08 16:18:35 +00003090bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3091 OperandVector &Operands,
3092 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003093 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003094 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003095
Jack Carterb4dbc172012-09-05 23:34:03 +00003096 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00003097 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00003098 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003099 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003100
3101 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003102 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003103 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00003104 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00003105 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00003106 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00003107 return false;
3108 }
3109 case Match_MissingFeature:
3110 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3111 return true;
3112 case Match_InvalidOperand: {
3113 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003114 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003115 if (ErrorInfo >= Operands.size())
3116 return Error(IDLoc, "too few operands for instruction");
3117
David Blaikie960ea3f2014-06-08 16:18:35 +00003118 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003119 if (ErrorLoc == SMLoc())
3120 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003121 }
3122
3123 return Error(ErrorLoc, "invalid operand for instruction");
3124 }
3125 case Match_MnemonicFail:
3126 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003127 case Match_RequiresDifferentSrcAndDst:
3128 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00003129 }
Craig Topper589ceee2015-01-03 08:16:34 +00003130
3131 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003132}
3133
Toma Tabacud9d344b2015-04-27 14:05:04 +00003134void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3135 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3136 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3137 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003138}
3139
Toma Tabacu81496c12015-05-20 08:54:45 +00003140void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3141 if (!AssemblerOptions.back()->isMacro())
3142 Warning(Loc, "macro instruction expanded into multiple instructions");
3143}
3144
Daniel Sandersef638fe2014-10-03 15:37:37 +00003145void
3146MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3147 SMRange Range, bool ShowColors) {
3148 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003149 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003150 ShowColors);
3151}
3152
Jack Carter1ac53222013-02-20 23:11:17 +00003153int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003154 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003155
Vladimir Medic4c299852013-11-06 11:27:05 +00003156 CC = StringSwitch<unsigned>(Name)
3157 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003158 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003159 .Case("a0", 4)
3160 .Case("a1", 5)
3161 .Case("a2", 6)
3162 .Case("a3", 7)
3163 .Case("v0", 2)
3164 .Case("v1", 3)
3165 .Case("s0", 16)
3166 .Case("s1", 17)
3167 .Case("s2", 18)
3168 .Case("s3", 19)
3169 .Case("s4", 20)
3170 .Case("s5", 21)
3171 .Case("s6", 22)
3172 .Case("s7", 23)
3173 .Case("k0", 26)
3174 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003175 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003176 .Case("sp", 29)
3177 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003178 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003179 .Case("ra", 31)
3180 .Case("t0", 8)
3181 .Case("t1", 9)
3182 .Case("t2", 10)
3183 .Case("t3", 11)
3184 .Case("t4", 12)
3185 .Case("t5", 13)
3186 .Case("t6", 14)
3187 .Case("t7", 15)
3188 .Case("t8", 24)
3189 .Case("t9", 25)
3190 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003191
Toma Tabacufda445c2014-09-15 15:33:01 +00003192 if (!(isABI_N32() || isABI_N64()))
3193 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003194
Daniel Sandersef638fe2014-10-03 15:37:37 +00003195 if (12 <= CC && CC <= 15) {
3196 // Name is one of t4-t7
3197 AsmToken RegTok = getLexer().peekTok();
3198 SMRange RegRange = RegTok.getLocRange();
3199
3200 StringRef FixedName = StringSwitch<StringRef>(Name)
3201 .Case("t4", "t0")
3202 .Case("t5", "t1")
3203 .Case("t6", "t2")
3204 .Case("t7", "t3")
3205 .Default("");
3206 assert(FixedName != "" && "Register name is not one of t4-t7.");
3207
3208 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3209 "Did you mean $" + FixedName + "?", RegRange);
3210 }
3211
Toma Tabacufda445c2014-09-15 15:33:01 +00003212 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3213 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3214 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3215 if (8 <= CC && CC <= 11)
3216 CC += 4;
3217
3218 if (CC == -1)
3219 CC = StringSwitch<unsigned>(Name)
3220 .Case("a4", 8)
3221 .Case("a5", 9)
3222 .Case("a6", 10)
3223 .Case("a7", 11)
3224 .Case("kt0", 26)
3225 .Case("kt1", 27)
3226 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003227
3228 return CC;
3229}
Jack Carterd0bd6422013-04-18 00:41:53 +00003230
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003231int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3232 int CC;
3233
3234 CC = StringSwitch<unsigned>(Name)
3235 .Case("hwr_cpunum", 0)
3236 .Case("hwr_synci_step", 1)
3237 .Case("hwr_cc", 2)
3238 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003239 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003240 .Default(-1);
3241
3242 return CC;
3243}
3244
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003245int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003246
Jack Cartera63b16a2012-09-07 00:23:42 +00003247 if (Name[0] == 'f') {
3248 StringRef NumString = Name.substr(1);
3249 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003250 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003251 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003252 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003253 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003254 return IntVal;
3255 }
3256 return -1;
3257}
Jack Cartera63b16a2012-09-07 00:23:42 +00003258
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003259int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3260
3261 if (Name.startswith("fcc")) {
3262 StringRef NumString = Name.substr(3);
3263 unsigned IntVal;
3264 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003265 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003266 if (IntVal > 7) // There are only 8 fcc registers.
3267 return -1;
3268 return IntVal;
3269 }
3270 return -1;
3271}
3272
3273int MipsAsmParser::matchACRegisterName(StringRef Name) {
3274
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003275 if (Name.startswith("ac")) {
3276 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003277 unsigned IntVal;
3278 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003279 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003280 if (IntVal > 3) // There are only 3 acc registers.
3281 return -1;
3282 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003283 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003284 return -1;
3285}
Jack Carterd0bd6422013-04-18 00:41:53 +00003286
Jack Carter5dc8ac92013-09-25 23:50:44 +00003287int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3288 unsigned IntVal;
3289
3290 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3291 return -1;
3292
3293 if (IntVal > 31)
3294 return -1;
3295
3296 return IntVal;
3297}
3298
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003299int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3300 int CC;
3301
3302 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003303 .Case("msair", 0)
3304 .Case("msacsr", 1)
3305 .Case("msaaccess", 2)
3306 .Case("msasave", 3)
3307 .Case("msamodify", 4)
3308 .Case("msarequest", 5)
3309 .Case("msamap", 6)
3310 .Case("msaunmap", 7)
3311 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003312
3313 return CC;
3314}
3315
Toma Tabacu89a712b2015-04-15 10:48:56 +00003316unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00003317 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00003318 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00003319 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00003320 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00003321 return 0;
3322 }
3323 unsigned AT = getReg(
3324 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00003325 return AT;
3326}
Jack Carter0b744b32012-10-04 02:29:46 +00003327
Jack Carterd0bd6422013-04-18 00:41:53 +00003328unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00003329 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00003330}
3331
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003332unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003333 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00003334 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003335}
3336
Jack Carter873c7242013-01-12 01:03:14 +00003337int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003338 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00003339 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00003340 return -1;
3341
Jack Carter873c7242013-01-12 01:03:14 +00003342 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00003343}
3344
Toma Tabacu13964452014-09-04 13:23:44 +00003345bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003346 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003347 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003348
Jack Carter30a59822012-10-04 04:03:53 +00003349 // Check if the current operand has a custom associated parser, if so, try to
3350 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00003351 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3352 if (ResTy == MatchOperand_Success)
3353 return false;
3354 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3355 // there was a match, but an error occurred, in which case, just return that
3356 // the operand parsing failed.
3357 if (ResTy == MatchOperand_ParseFail)
3358 return true;
3359
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003360 DEBUG(dbgs() << ".. Generic Parser\n");
3361
Jack Carterb4dbc172012-09-05 23:34:03 +00003362 switch (getLexer().getKind()) {
3363 default:
3364 Error(Parser.getTok().getLoc(), "unexpected token in operand");
3365 return true;
3366 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003367 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00003368 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00003369
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003370 // Almost all registers have been parsed by custom parsers. There is only
3371 // one exception to this. $zero (and it's alias $0) will reach this point
3372 // for div, divu, and similar instructions because it is not an operand
3373 // to the instruction definition but an explicit register. Special case
3374 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00003375 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00003376 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003377
Jack Carterd0bd6422013-04-18 00:41:53 +00003378 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00003379 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003380 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00003381 return true;
3382
Jack Carter873c7242013-01-12 01:03:14 +00003383 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00003384 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00003385 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00003386 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003387 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00003388
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003389 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003390 return false;
3391 }
Vladimir Medic4c299852013-11-06 11:27:05 +00003392 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00003393 case AsmToken::LParen:
3394 case AsmToken::Minus:
3395 case AsmToken::Plus:
3396 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003397 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00003398 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003399 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003400 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003401 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00003402 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00003403 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003404 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003405 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003406 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00003407 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00003408 return true;
3409
Jack Carter873c7242013-01-12 01:03:14 +00003410 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3411
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003412 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00003413 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003414 } // case AsmToken::Percent
3415 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00003416 return true;
3417}
3418
Vladimir Medic4c299852013-11-06 11:27:05 +00003419const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00003420 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003421 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00003422 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003423 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00003424 // It's a constant, evaluate reloc value.
3425 int16_t Val;
3426 switch (getVariantKind(RelocStr)) {
3427 case MCSymbolRefExpr::VK_Mips_ABS_LO:
3428 // Get the 1st 16-bits.
3429 Val = MCE->getValue() & 0xffff;
3430 break;
3431 case MCSymbolRefExpr::VK_Mips_ABS_HI:
3432 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
3433 // 16 bits being negative.
3434 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
3435 break;
3436 case MCSymbolRefExpr::VK_Mips_HIGHER:
3437 // Get the 3rd 16-bits.
3438 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
3439 break;
3440 case MCSymbolRefExpr::VK_Mips_HIGHEST:
3441 // Get the 4th 16-bits.
3442 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
3443 break;
3444 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00003445 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00003446 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00003447 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003448 }
3449
Jack Carterb5cf5902013-04-17 00:18:04 +00003450 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003451 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00003452 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00003453 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003454 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003455 return Res;
3456 }
3457
3458 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00003459 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
3460
Sasa Stankovic06c47802014-04-03 10:37:45 +00003461 // Try to create target expression.
3462 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00003463 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003464
Jack Carterd0bd6422013-04-18 00:41:53 +00003465 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
3466 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003467 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003468 return Res;
3469 }
3470
3471 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003472 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003473 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00003474 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00003475 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003476 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003477 return Expr;
3478}
3479
3480bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
3481
3482 switch (Expr->getKind()) {
3483 case MCExpr::Constant:
3484 return true;
3485 case MCExpr::SymbolRef:
3486 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
3487 case MCExpr::Binary:
3488 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
3489 if (!isEvaluated(BE->getLHS()))
3490 return false;
3491 return isEvaluated(BE->getRHS());
3492 }
3493 case MCExpr::Unary:
3494 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003495 case MCExpr::Target:
3496 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003497 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003498 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00003499}
Jack Carterd0bd6422013-04-18 00:41:53 +00003500
Jack Carterb5cf5902013-04-17 00:18:04 +00003501bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003502 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003503 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00003504 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00003505 if (Tok.isNot(AsmToken::Identifier))
3506 return true;
3507
Yaron Keren075759a2015-03-30 15:42:36 +00003508 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00003509
Jack Carterd0bd6422013-04-18 00:41:53 +00003510 Parser.Lex(); // Eat the identifier.
3511 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003512 const MCExpr *IdVal;
3513 SMLoc EndLoc;
3514
3515 if (getLexer().getKind() == AsmToken::LParen) {
3516 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003517 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003518 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003519 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003520 const AsmToken &nextTok = Parser.getTok();
3521 if (nextTok.isNot(AsmToken::Identifier))
3522 return true;
3523 Str += "(%";
3524 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00003525 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00003526 if (getLexer().getKind() != AsmToken::LParen)
3527 return true;
3528 } else
3529 break;
3530 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003531 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00003532 return true;
3533
3534 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00003535 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003536
3537 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00003538 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003539
Jack Carterd0bd6422013-04-18 00:41:53 +00003540 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00003541 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003542}
3543
Jack Carterb4dbc172012-09-05 23:34:03 +00003544bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
3545 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003546 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00003547 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003548 if (ResTy == MatchOperand_Success) {
3549 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00003550 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003551 StartLoc = Operand.getStartLoc();
3552 EndLoc = Operand.getEndLoc();
3553
3554 // AFAIK, we only support numeric registers and named GPR's in CFI
3555 // directives.
3556 // Don't worry about eating tokens before failing. Using an unrecognised
3557 // register is a parse error.
3558 if (Operand.isGPRAsmReg()) {
3559 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003560 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003561 }
3562
3563 return (RegNo == (unsigned)-1);
3564 }
3565
3566 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00003567 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00003568}
3569
Jack Carterb5cf5902013-04-17 00:18:04 +00003570bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003571 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00003572 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003573 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003574 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00003575
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003576 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003577 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003578 ++NumOfLParen;
3579 }
Jack Carter873c7242013-01-12 01:03:14 +00003580
Jack Carterd0bd6422013-04-18 00:41:53 +00003581 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003582 default:
3583 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00003584 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00003585 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00003586 case AsmToken::Integer:
3587 case AsmToken::Minus:
3588 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00003589 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003590 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00003591 else
3592 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00003593 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00003594 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003595 break;
Jack Carter873c7242013-01-12 01:03:14 +00003596 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00003597 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003598 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003599 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003600}
3601
David Blaikie960ea3f2014-06-08 16:18:35 +00003602MipsAsmParser::OperandMatchResultTy
3603MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003604 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003605 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00003606 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00003607 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003608 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003609 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00003610 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00003611 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00003612
Jack Carterb5cf5902013-04-17 00:18:04 +00003613 if (getLexer().getKind() == AsmToken::LParen) {
3614 Parser.Lex();
3615 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003616 }
3617
Jack Carterb5cf5902013-04-17 00:18:04 +00003618 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003619 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00003620 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003621
Jack Carterd0bd6422013-04-18 00:41:53 +00003622 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003623 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003624 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003625 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003626 SMLoc E =
3627 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003628 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003629 return MatchOperand_Success;
3630 }
3631 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003632 SMLoc E =
3633 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00003634
Jack Carterd0bd6422013-04-18 00:41:53 +00003635 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003636 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00003637 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003638 S, E, *this);
3639 Operands.push_back(
3640 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003641 return MatchOperand_Success;
3642 }
3643 Error(Parser.getTok().getLoc(), "'(' expected");
3644 return MatchOperand_ParseFail;
3645 }
3646
Jack Carterd0bd6422013-04-18 00:41:53 +00003647 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003648 }
3649
Toma Tabacu13964452014-09-04 13:23:44 +00003650 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003651 if (Res != MatchOperand_Success)
3652 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003653
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003654 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003655 Error(Parser.getTok().getLoc(), "')' expected");
3656 return MatchOperand_ParseFail;
3657 }
3658
Jack Carter873c7242013-01-12 01:03:14 +00003659 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3660
Jack Carterd0bd6422013-04-18 00:41:53 +00003661 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003662
Craig Topper062a2ba2014-04-25 05:30:21 +00003663 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003664 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003665
Jack Carterd0bd6422013-04-18 00:41:53 +00003666 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00003667 std::unique_ptr<MipsOperand> op(
3668 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00003669 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003670 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003671 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00003672 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003673 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
3674 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003675 if (IdVal->evaluateAsAbsolute(Imm))
3676 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003677 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003678 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00003679 getContext());
3680 }
3681
David Blaikie960ea3f2014-06-08 16:18:35 +00003682 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003683 return MatchOperand_Success;
3684}
3685
David Blaikie960ea3f2014-06-08 16:18:35 +00003686bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003687 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00003688 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00003689 if (Sym) {
3690 SMLoc S = Parser.getTok().getLoc();
3691 const MCExpr *Expr;
3692 if (Sym->isVariable())
3693 Expr = Sym->getVariableValue();
3694 else
3695 return false;
3696 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003697 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00003698 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00003699 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003700 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003701 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00003702 if (ResTy == MatchOperand_Success) {
3703 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00003704 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00003705 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003706 llvm_unreachable("Should never ParseFail");
3707 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00003708 }
3709 } else if (Expr->getKind() == MCExpr::Constant) {
3710 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00003711 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00003712 Operands.push_back(
3713 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00003714 return true;
3715 }
3716 }
3717 return false;
3718}
Jack Carterd0bd6422013-04-18 00:41:53 +00003719
Jack Carter873c7242013-01-12 01:03:14 +00003720MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003721MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00003722 StringRef Identifier,
3723 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003724 int Index = matchCPURegisterName(Identifier);
3725 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003726 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003727 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3728 return MatchOperand_Success;
3729 }
3730
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003731 Index = matchHWRegsRegisterName(Identifier);
3732 if (Index != -1) {
3733 Operands.push_back(MipsOperand::createHWRegsReg(
3734 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3735 return MatchOperand_Success;
3736 }
3737
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003738 Index = matchFPURegisterName(Identifier);
3739 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003740 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003741 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3742 return MatchOperand_Success;
3743 }
3744
3745 Index = matchFCCRegisterName(Identifier);
3746 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003747 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003748 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3749 return MatchOperand_Success;
3750 }
3751
3752 Index = matchACRegisterName(Identifier);
3753 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003754 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003755 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3756 return MatchOperand_Success;
3757 }
3758
3759 Index = matchMSA128RegisterName(Identifier);
3760 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003761 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003762 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3763 return MatchOperand_Success;
3764 }
3765
3766 Index = matchMSA128CtrlRegisterName(Identifier);
3767 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003768 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003769 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3770 return MatchOperand_Success;
3771 }
3772
3773 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00003774}
3775
3776MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003777MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003778 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00003779 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003780
3781 if (Token.is(AsmToken::Identifier)) {
3782 DEBUG(dbgs() << ".. identifier\n");
3783 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00003784 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003785 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00003786 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003787 } else if (Token.is(AsmToken::Integer)) {
3788 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003789 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003790 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
3791 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003792 return MatchOperand_Success;
3793 }
3794
3795 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
3796
3797 return MatchOperand_NoMatch;
3798}
3799
David Blaikie960ea3f2014-06-08 16:18:35 +00003800MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003801MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003802 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003803 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003804
3805 auto Token = Parser.getTok();
3806
3807 SMLoc S = Token.getLoc();
3808
3809 if (Token.isNot(AsmToken::Dollar)) {
3810 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
3811 if (Token.is(AsmToken::Identifier)) {
3812 if (searchSymbolAlias(Operands))
3813 return MatchOperand_Success;
3814 }
3815 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
3816 return MatchOperand_NoMatch;
3817 }
3818 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003819
Toma Tabacu13964452014-09-04 13:23:44 +00003820 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00003821 if (ResTy == MatchOperand_Success) {
3822 Parser.Lex(); // $
3823 Parser.Lex(); // identifier
3824 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003825 return ResTy;
3826}
3827
3828MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003829MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003830 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003831 switch (getLexer().getKind()) {
3832 default:
3833 return MatchOperand_NoMatch;
3834 case AsmToken::LParen:
3835 case AsmToken::Minus:
3836 case AsmToken::Plus:
3837 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003838 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003839 case AsmToken::String:
3840 break;
3841 }
3842
3843 const MCExpr *IdVal;
3844 SMLoc S = Parser.getTok().getLoc();
3845 if (getParser().parseExpression(IdVal))
3846 return MatchOperand_ParseFail;
3847
3848 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3849 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
3850 return MatchOperand_Success;
3851}
3852
David Blaikie960ea3f2014-06-08 16:18:35 +00003853MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003854MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003855 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003856 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003857
3858 SMLoc S = getLexer().getLoc();
3859
3860 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00003861 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003862 if (ResTy != MatchOperand_NoMatch)
3863 return ResTy;
3864
Daniel Sanders315386c2014-04-01 10:40:14 +00003865 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00003866 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00003867 if (ResTy != MatchOperand_NoMatch)
3868 return ResTy;
3869
Daniel Sandersffd84362014-04-01 10:41:48 +00003870 const MCExpr *Expr = nullptr;
3871 if (Parser.parseExpression(Expr)) {
3872 // We have no way of knowing if a symbol was consumed so we must ParseFail
3873 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003874 }
Daniel Sandersffd84362014-04-01 10:41:48 +00003875 Operands.push_back(
3876 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003877 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00003878}
3879
Vladimir Medic2b953d02013-10-01 09:48:56 +00003880MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00003881MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003882 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00003883 const MCExpr *IdVal;
3884 // If the first token is '$' we may have register operand.
3885 if (Parser.getTok().is(AsmToken::Dollar))
3886 return MatchOperand_NoMatch;
3887 SMLoc S = Parser.getTok().getLoc();
3888 if (getParser().parseExpression(IdVal))
3889 return MatchOperand_ParseFail;
3890 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00003891 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00003892 int64_t Val = MCE->getValue();
3893 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3894 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003895 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00003896 return MatchOperand_Success;
3897}
3898
Matheus Almeida779c5932013-11-18 12:32:49 +00003899MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003900MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003901 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00003902 switch (getLexer().getKind()) {
3903 default:
3904 return MatchOperand_NoMatch;
3905 case AsmToken::LParen:
3906 case AsmToken::Plus:
3907 case AsmToken::Minus:
3908 case AsmToken::Integer:
3909 break;
3910 }
3911
3912 const MCExpr *Expr;
3913 SMLoc S = Parser.getTok().getLoc();
3914
3915 if (getParser().parseExpression(Expr))
3916 return MatchOperand_ParseFail;
3917
3918 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003919 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00003920 Error(S, "expected immediate value");
3921 return MatchOperand_ParseFail;
3922 }
3923
3924 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
3925 // and because the CPU always adds one to the immediate field, the allowed
3926 // range becomes 1..4. We'll only check the range here and will deal
3927 // with the addition/subtraction when actually decoding/encoding
3928 // the instruction.
3929 if (Val < 1 || Val > 4) {
3930 Error(S, "immediate not in range (1..4)");
3931 return MatchOperand_ParseFail;
3932 }
3933
Jack Carter3b2c96e2014-01-22 23:31:38 +00003934 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003935 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00003936 return MatchOperand_Success;
3937}
3938
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00003939MipsAsmParser::OperandMatchResultTy
3940MipsAsmParser::parseRegisterList(OperandVector &Operands) {
3941 MCAsmParser &Parser = getParser();
3942 SmallVector<unsigned, 10> Regs;
3943 unsigned RegNo;
3944 unsigned PrevReg = Mips::NoRegister;
3945 bool RegRange = false;
3946 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3947
3948 if (Parser.getTok().isNot(AsmToken::Dollar))
3949 return MatchOperand_ParseFail;
3950
3951 SMLoc S = Parser.getTok().getLoc();
3952 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
3953 SMLoc E = getLexer().getLoc();
3954 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
3955 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
3956 if (RegRange) {
3957 // Remove last register operand because registers from register range
3958 // should be inserted first.
3959 if (RegNo == Mips::RA) {
3960 Regs.push_back(RegNo);
3961 } else {
3962 unsigned TmpReg = PrevReg + 1;
3963 while (TmpReg <= RegNo) {
3964 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
3965 Error(E, "invalid register operand");
3966 return MatchOperand_ParseFail;
3967 }
3968
3969 PrevReg = TmpReg;
3970 Regs.push_back(TmpReg++);
3971 }
3972 }
3973
3974 RegRange = false;
3975 } else {
3976 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
3977 (RegNo != Mips::RA)) {
3978 Error(E, "$16 or $31 expected");
3979 return MatchOperand_ParseFail;
3980 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
3981 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3982 Error(E, "invalid register operand");
3983 return MatchOperand_ParseFail;
3984 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
3985 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3986 Error(E, "consecutive register numbers expected");
3987 return MatchOperand_ParseFail;
3988 }
3989
3990 Regs.push_back(RegNo);
3991 }
3992
3993 if (Parser.getTok().is(AsmToken::Minus))
3994 RegRange = true;
3995
3996 if (!Parser.getTok().isNot(AsmToken::Minus) &&
3997 !Parser.getTok().isNot(AsmToken::Comma)) {
3998 Error(E, "',' or '-' expected");
3999 return MatchOperand_ParseFail;
4000 }
4001
4002 Lex(); // Consume comma or minus
4003 if (Parser.getTok().isNot(AsmToken::Dollar))
4004 break;
4005
4006 PrevReg = RegNo;
4007 }
4008
4009 SMLoc E = Parser.getTok().getLoc();
4010 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4011 parseMemOperand(Operands);
4012 return MatchOperand_Success;
4013}
4014
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004015MipsAsmParser::OperandMatchResultTy
4016MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4017 MCAsmParser &Parser = getParser();
4018
4019 SMLoc S = Parser.getTok().getLoc();
4020 if (parseAnyRegister(Operands) != MatchOperand_Success)
4021 return MatchOperand_ParseFail;
4022
4023 SMLoc E = Parser.getTok().getLoc();
4024 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
4025 unsigned Reg = Op.getGPR32Reg();
4026 Operands.pop_back();
4027 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
4028 return MatchOperand_Success;
4029}
4030
Zoran Jovanovic41688672015-02-10 16:36:20 +00004031MipsAsmParser::OperandMatchResultTy
4032MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4033 MCAsmParser &Parser = getParser();
4034 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4035 SmallVector<unsigned, 10> Regs;
4036
4037 if (Parser.getTok().isNot(AsmToken::Dollar))
4038 return MatchOperand_ParseFail;
4039
4040 SMLoc S = Parser.getTok().getLoc();
4041
4042 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4043 return MatchOperand_ParseFail;
4044
4045 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4046 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4047 Regs.push_back(RegNo);
4048
4049 SMLoc E = Parser.getTok().getLoc();
4050 if (Parser.getTok().isNot(AsmToken::Comma)) {
4051 Error(E, "',' expected");
4052 return MatchOperand_ParseFail;
4053 }
4054
4055 // Remove comma.
4056 Parser.Lex();
4057
4058 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4059 return MatchOperand_ParseFail;
4060
4061 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4062 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4063 Regs.push_back(RegNo);
4064
4065 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4066
4067 return MatchOperand_Success;
4068}
4069
Jack Carterdc1e35d2012-09-06 20:00:02 +00004070MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
4071
Vladimir Medic4c299852013-11-06 11:27:05 +00004072 MCSymbolRefExpr::VariantKind VK =
4073 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
4074 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
4075 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
4076 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
4077 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
4078 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
4079 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
4080 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
4081 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
4082 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
4083 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
4084 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
4085 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
4086 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
4087 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
4088 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
4089 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
4090 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00004091 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
4092 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
4093 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
4094 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
4095 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
4096 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00004097 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
4098 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00004099 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004100
Matheus Almeida2852af82014-04-22 10:15:54 +00004101 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00004102
Jack Carterdc1e35d2012-09-06 20:00:02 +00004103 return VK;
4104}
Jack Cartera63b16a2012-09-07 00:23:42 +00004105
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004106/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4107/// either this.
4108/// ::= '(', register, ')'
4109/// handle it before we iterate so we don't get tripped up by the lack of
4110/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004111bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004112 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004113 if (getLexer().is(AsmToken::LParen)) {
4114 Operands.push_back(
4115 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4116 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004117 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004118 SMLoc Loc = getLexer().getLoc();
4119 Parser.eatToEndOfStatement();
4120 return Error(Loc, "unexpected token in argument list");
4121 }
4122 if (Parser.getTok().isNot(AsmToken::RParen)) {
4123 SMLoc Loc = getLexer().getLoc();
4124 Parser.eatToEndOfStatement();
4125 return Error(Loc, "unexpected token, expected ')'");
4126 }
4127 Operands.push_back(
4128 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4129 Parser.Lex();
4130 }
4131 return false;
4132}
4133
4134/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4135/// either one of these.
4136/// ::= '[', register, ']'
4137/// ::= '[', integer, ']'
4138/// handle it before we iterate so we don't get tripped up by the lack of
4139/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004140bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004141 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004142 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004143 if (getLexer().is(AsmToken::LBrac)) {
4144 Operands.push_back(
4145 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4146 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004147 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004148 SMLoc Loc = getLexer().getLoc();
4149 Parser.eatToEndOfStatement();
4150 return Error(Loc, "unexpected token in argument list");
4151 }
4152 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4153 SMLoc Loc = getLexer().getLoc();
4154 Parser.eatToEndOfStatement();
4155 return Error(Loc, "unexpected token, expected ']'");
4156 }
4157 Operands.push_back(
4158 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4159 Parser.Lex();
4160 }
4161 return false;
4162}
4163
David Blaikie960ea3f2014-06-08 16:18:35 +00004164bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4165 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004166 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004167 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004168
4169 // We have reached first instruction, module directive are now forbidden.
4170 getTargetStreamer().forbidModuleDirective();
4171
Vladimir Medic74593e62013-07-17 15:00:42 +00004172 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004173 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004174 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004175 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004176 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004177 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004178 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004179
4180 // Read the remaining operands.
4181 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4182 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004183 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004184 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004185 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004186 return Error(Loc, "unexpected token in argument list");
4187 }
Toma Tabacu13964452014-09-04 13:23:44 +00004188 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004189 return true;
4190 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004191
Jack Carterd0bd6422013-04-18 00:41:53 +00004192 while (getLexer().is(AsmToken::Comma)) {
4193 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004194 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004195 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004196 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004197 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004198 return Error(Loc, "unexpected token in argument list");
4199 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004200 // Parse bracket and parenthesis suffixes before we iterate
4201 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004202 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004203 return true;
4204 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004205 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004206 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004207 }
4208 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004209 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4210 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004211 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004212 return Error(Loc, "unexpected token in argument list");
4213 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004214 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004215 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004216}
4217
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004218bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004219 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004220 SMLoc Loc = getLexer().getLoc();
4221 Parser.eatToEndOfStatement();
4222 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004223}
4224
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004225bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004226 return Error(Loc, ErrorMsg);
4227}
4228
Jack Carter0b744b32012-10-04 02:29:46 +00004229bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004230 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004231 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004232
4233 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004234 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004235
4236 Parser.Lex(); // Eat "noat".
4237
Jack Carterd0bd6422013-04-18 00:41:53 +00004238 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004239 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004240 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004241 return false;
4242 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004243
4244 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004245 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004246 return false;
4247}
Jack Carterd0bd6422013-04-18 00:41:53 +00004248
Jack Carter0b744b32012-10-04 02:29:46 +00004249bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004250 // Line can be: ".set at", which sets $at to $1
4251 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004252 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004253 Parser.Lex(); // Eat "at".
4254
Jack Carter0b744b32012-10-04 02:29:46 +00004255 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004256 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004257 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004258
4259 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004260 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004261 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004262 }
4263
4264 if (getLexer().isNot(AsmToken::Equal)) {
4265 reportParseError("unexpected token, expected equals sign");
4266 return false;
4267 }
4268 Parser.Lex(); // Eat "=".
4269
4270 if (getLexer().isNot(AsmToken::Dollar)) {
4271 if (getLexer().is(AsmToken::EndOfStatement)) {
4272 reportParseError("no register specified");
4273 return false;
4274 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004275 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004276 return false;
4277 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004278 }
4279 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004280
Toma Tabacu16a74492015-02-13 10:30:57 +00004281 // Find out what "reg" is.
4282 unsigned AtRegNo;
4283 const AsmToken &Reg = Parser.getTok();
4284 if (Reg.is(AsmToken::Identifier)) {
4285 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4286 } else if (Reg.is(AsmToken::Integer)) {
4287 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004288 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004289 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004290 return false;
4291 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004292
4293 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004294 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004295 reportParseError("invalid register");
4296 return false;
4297 }
4298 Parser.Lex(); // Eat "reg".
4299
4300 // If this is not the end of the statement, report an error.
4301 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4302 reportParseError("unexpected token, expected end of statement");
4303 return false;
4304 }
4305
4306 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4307
4308 Parser.Lex(); // Consume the EndOfStatement.
4309 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004310}
4311
4312bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004313 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004314 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004315 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004316 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004317 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004318 return false;
4319 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004320 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004321 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004322 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004323 return false;
4324}
4325
4326bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004327 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004328 Parser.Lex();
4329 // If this is not the end of the statement, report an error.
4330 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004331 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004332 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00004333 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004334 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00004335 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004336 Parser.Lex(); // Consume the EndOfStatement.
4337 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004338}
4339
4340bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004341 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004342 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004343 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004344 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004345 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004346 return false;
4347 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004348 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004349 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004350 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004351 return false;
4352}
4353
4354bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004355 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004356 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004357 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004358 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004359 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004360 return false;
4361 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004362 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00004363 reportParseError("`noreorder' must be set before `nomacro'");
4364 return false;
4365 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004366 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004367 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004368 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004369 return false;
4370}
Jack Carterd76b2372013-03-21 21:44:16 +00004371
Daniel Sanders44934432014-08-07 12:03:36 +00004372bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004373 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004374 Parser.Lex();
4375
4376 // If this is not the end of the statement, report an error.
4377 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004378 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004379
4380 setFeatureBits(Mips::FeatureMSA, "msa");
4381 getTargetStreamer().emitDirectiveSetMsa();
4382 return false;
4383}
4384
4385bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004386 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004387 Parser.Lex();
4388
4389 // If this is not the end of the statement, report an error.
4390 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004391 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004392
4393 clearFeatureBits(Mips::FeatureMSA, "msa");
4394 getTargetStreamer().emitDirectiveSetNoMsa();
4395 return false;
4396}
4397
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004398bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004399 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004400 Parser.Lex(); // Eat "nodsp".
4401
4402 // If this is not the end of the statement, report an error.
4403 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4404 reportParseError("unexpected token, expected end of statement");
4405 return false;
4406 }
4407
4408 clearFeatureBits(Mips::FeatureDSP, "dsp");
4409 getTargetStreamer().emitDirectiveSetNoDsp();
4410 return false;
4411}
4412
Toma Tabacucc2502d2014-11-04 17:18:07 +00004413bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004414 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004415 Parser.Lex(); // Eat "mips16".
4416
Jack Carter39536722014-01-22 23:08:42 +00004417 // If this is not the end of the statement, report an error.
4418 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004419 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00004420 return false;
4421 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00004422
4423 setFeatureBits(Mips::FeatureMips16, "mips16");
4424 getTargetStreamer().emitDirectiveSetMips16();
4425 Parser.Lex(); // Consume the EndOfStatement.
4426 return false;
4427}
4428
4429bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004430 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004431 Parser.Lex(); // Eat "nomips16".
4432
4433 // If this is not the end of the statement, report an error.
4434 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4435 reportParseError("unexpected token, expected end of statement");
4436 return false;
4437 }
4438
4439 clearFeatureBits(Mips::FeatureMips16, "mips16");
4440 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00004441 Parser.Lex(); // Consume the EndOfStatement.
4442 return false;
4443}
4444
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004445bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004446 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004447 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004448 // Line can be: .set fp=32
4449 // .set fp=xx
4450 // .set fp=64
4451 Parser.Lex(); // Eat fp token
4452 AsmToken Tok = Parser.getTok();
4453 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004454 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004455 return false;
4456 }
4457 Parser.Lex(); // Eat '=' token.
4458 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004459
4460 if (!parseFpABIValue(FpAbiVal, ".set"))
4461 return false;
4462
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004463 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004464 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004465 return false;
4466 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004467 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004468 Parser.Lex(); // Consume the EndOfStatement.
4469 return false;
4470}
4471
Toma Tabacu32c72aa2015-06-30 09:36:50 +00004472bool MipsAsmParser::parseSetOddSPRegDirective() {
4473 MCAsmParser &Parser = getParser();
4474
4475 Parser.Lex(); // Eat "oddspreg".
4476 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4477 reportParseError("unexpected token, expected end of statement");
4478 return false;
4479 }
4480
4481 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4482 getTargetStreamer().emitDirectiveSetOddSPReg();
4483 return false;
4484}
4485
4486bool MipsAsmParser::parseSetNoOddSPRegDirective() {
4487 MCAsmParser &Parser = getParser();
4488
4489 Parser.Lex(); // Eat "nooddspreg".
4490 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4491 reportParseError("unexpected token, expected end of statement");
4492 return false;
4493 }
4494
4495 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4496 getTargetStreamer().emitDirectiveSetNoOddSPReg();
4497 return false;
4498}
4499
Toma Tabacu9db22db2014-09-09 10:15:38 +00004500bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004501 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004502 SMLoc Loc = getLexer().getLoc();
4503
4504 Parser.Lex();
4505 if (getLexer().isNot(AsmToken::EndOfStatement))
4506 return reportParseError("unexpected token, expected end of statement");
4507
4508 // Always keep an element on the options "stack" to prevent the user
4509 // from changing the initial options. This is how we remember them.
4510 if (AssemblerOptions.size() == 2)
4511 return reportParseError(Loc, ".set pop with no .set push");
4512
4513 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00004514 setAvailableFeatures(
4515 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
4516 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00004517
4518 getTargetStreamer().emitDirectiveSetPop();
4519 return false;
4520}
4521
4522bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004523 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004524 Parser.Lex();
4525 if (getLexer().isNot(AsmToken::EndOfStatement))
4526 return reportParseError("unexpected token, expected end of statement");
4527
4528 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00004529 AssemblerOptions.push_back(
4530 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00004531
4532 getTargetStreamer().emitDirectiveSetPush();
4533 return false;
4534}
4535
Toma Tabacu29696502015-06-02 09:48:04 +00004536bool MipsAsmParser::parseSetSoftFloatDirective() {
4537 MCAsmParser &Parser = getParser();
4538 Parser.Lex();
4539 if (getLexer().isNot(AsmToken::EndOfStatement))
4540 return reportParseError("unexpected token, expected end of statement");
4541
4542 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4543 getTargetStreamer().emitDirectiveSetSoftFloat();
4544 return false;
4545}
4546
4547bool MipsAsmParser::parseSetHardFloatDirective() {
4548 MCAsmParser &Parser = getParser();
4549 Parser.Lex();
4550 if (getLexer().isNot(AsmToken::EndOfStatement))
4551 return reportParseError("unexpected token, expected end of statement");
4552
4553 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4554 getTargetStreamer().emitDirectiveSetHardFloat();
4555 return false;
4556}
4557
Jack Carterd76b2372013-03-21 21:44:16 +00004558bool MipsAsmParser::parseSetAssignment() {
4559 StringRef Name;
4560 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00004561 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00004562
4563 if (Parser.parseIdentifier(Name))
4564 reportParseError("expected identifier after .set");
4565
4566 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004567 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00004568 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00004569
Jack Carter3b2c96e2014-01-22 23:31:38 +00004570 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00004571 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00004572
Jim Grosbach6f482002015-05-18 18:43:14 +00004573 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00004574 Sym->setVariableValue(Value);
4575
4576 return false;
4577}
Jack Carterd0bd6422013-04-18 00:41:53 +00004578
Toma Tabacu26647792014-09-09 12:52:14 +00004579bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004580 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00004581 Parser.Lex();
4582 if (getLexer().isNot(AsmToken::EndOfStatement))
4583 return reportParseError("unexpected token, expected end of statement");
4584
4585 // Reset assembler options to their initial values.
Toma Tabacu465acfd2015-06-09 13:33:26 +00004586 setAvailableFeatures(
4587 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
4588 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00004589 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
4590
4591 getTargetStreamer().emitDirectiveSetMips0();
4592 return false;
4593}
4594
Toma Tabacu85618b32014-08-19 14:22:52 +00004595bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004596 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00004597 Parser.Lex();
4598 if (getLexer().isNot(AsmToken::Equal))
4599 return reportParseError("unexpected token, expected equals sign");
4600
4601 Parser.Lex();
4602 StringRef Arch;
4603 if (Parser.parseIdentifier(Arch))
4604 return reportParseError("expected arch identifier");
4605
4606 StringRef ArchFeatureName =
4607 StringSwitch<StringRef>(Arch)
4608 .Case("mips1", "mips1")
4609 .Case("mips2", "mips2")
4610 .Case("mips3", "mips3")
4611 .Case("mips4", "mips4")
4612 .Case("mips5", "mips5")
4613 .Case("mips32", "mips32")
4614 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004615 .Case("mips32r3", "mips32r3")
4616 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004617 .Case("mips32r6", "mips32r6")
4618 .Case("mips64", "mips64")
4619 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004620 .Case("mips64r3", "mips64r3")
4621 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004622 .Case("mips64r6", "mips64r6")
4623 .Case("cnmips", "cnmips")
4624 .Case("r4000", "mips3") // This is an implementation of Mips3.
4625 .Default("");
4626
4627 if (ArchFeatureName.empty())
4628 return reportParseError("unsupported architecture");
4629
4630 selectArch(ArchFeatureName);
4631 getTargetStreamer().emitDirectiveSetArch(Arch);
4632 return false;
4633}
4634
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004635bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004636 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004637 Parser.Lex();
4638 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004639 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004640
Matheus Almeida2852af82014-04-22 10:15:54 +00004641 switch (Feature) {
4642 default:
4643 llvm_unreachable("Unimplemented feature");
4644 case Mips::FeatureDSP:
4645 setFeatureBits(Mips::FeatureDSP, "dsp");
4646 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004647 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004648 case Mips::FeatureMicroMips:
4649 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004650 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004651 case Mips::FeatureMips1:
4652 selectArch("mips1");
4653 getTargetStreamer().emitDirectiveSetMips1();
4654 break;
4655 case Mips::FeatureMips2:
4656 selectArch("mips2");
4657 getTargetStreamer().emitDirectiveSetMips2();
4658 break;
4659 case Mips::FeatureMips3:
4660 selectArch("mips3");
4661 getTargetStreamer().emitDirectiveSetMips3();
4662 break;
4663 case Mips::FeatureMips4:
4664 selectArch("mips4");
4665 getTargetStreamer().emitDirectiveSetMips4();
4666 break;
4667 case Mips::FeatureMips5:
4668 selectArch("mips5");
4669 getTargetStreamer().emitDirectiveSetMips5();
4670 break;
4671 case Mips::FeatureMips32:
4672 selectArch("mips32");
4673 getTargetStreamer().emitDirectiveSetMips32();
4674 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004675 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004676 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004677 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004678 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004679 case Mips::FeatureMips32r3:
4680 selectArch("mips32r3");
4681 getTargetStreamer().emitDirectiveSetMips32R3();
4682 break;
4683 case Mips::FeatureMips32r5:
4684 selectArch("mips32r5");
4685 getTargetStreamer().emitDirectiveSetMips32R5();
4686 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004687 case Mips::FeatureMips32r6:
4688 selectArch("mips32r6");
4689 getTargetStreamer().emitDirectiveSetMips32R6();
4690 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004691 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004692 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00004693 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00004694 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004695 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004696 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004697 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00004698 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004699 case Mips::FeatureMips64r3:
4700 selectArch("mips64r3");
4701 getTargetStreamer().emitDirectiveSetMips64R3();
4702 break;
4703 case Mips::FeatureMips64r5:
4704 selectArch("mips64r5");
4705 getTargetStreamer().emitDirectiveSetMips64R5();
4706 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004707 case Mips::FeatureMips64r6:
4708 selectArch("mips64r6");
4709 getTargetStreamer().emitDirectiveSetMips64R6();
4710 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004711 }
4712 return false;
4713}
4714
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004715bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004716 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004717 if (getLexer().isNot(AsmToken::Comma)) {
4718 SMLoc Loc = getLexer().getLoc();
4719 Parser.eatToEndOfStatement();
4720 return Error(Loc, ErrorStr);
4721 }
4722
Matheus Almeida2852af82014-04-22 10:15:54 +00004723 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004724 return true;
4725}
4726
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004727bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00004728 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00004729 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004730
Toma Tabacudde4c462014-11-06 10:02:45 +00004731 if (inMips16Mode()) {
4732 reportParseError(".cpload is not supported in Mips16 mode");
4733 return false;
4734 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004735
David Blaikie960ea3f2014-06-08 16:18:35 +00004736 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00004737 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004738 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4739 reportParseError("expected register containing function address");
4740 return false;
4741 }
4742
David Blaikie960ea3f2014-06-08 16:18:35 +00004743 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
4744 if (!RegOpnd.isGPRAsmReg()) {
4745 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004746 return false;
4747 }
4748
Toma Tabacudde4c462014-11-06 10:02:45 +00004749 // If this is not the end of the statement, report an error.
4750 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4751 reportParseError("unexpected token, expected end of statement");
4752 return false;
4753 }
4754
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004755 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004756 return false;
4757}
4758
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004759bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004760 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004761 unsigned FuncReg;
4762 unsigned Save;
4763 bool SaveIsReg = true;
4764
Matheus Almeida7e815762014-06-18 13:08:59 +00004765 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004766 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00004767 if (ResTy == MatchOperand_NoMatch) {
4768 reportParseError("expected register containing function address");
4769 Parser.eatToEndOfStatement();
4770 return false;
4771 }
4772
4773 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4774 if (!FuncRegOpnd.isGPRAsmReg()) {
4775 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
4776 Parser.eatToEndOfStatement();
4777 return false;
4778 }
4779
4780 FuncReg = FuncRegOpnd.getGPR32Reg();
4781 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004782
Toma Tabacu65f10572014-09-16 15:00:52 +00004783 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004784 return true;
4785
Toma Tabacu13964452014-09-04 13:23:44 +00004786 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00004787 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004788 const AsmToken &Tok = Parser.getTok();
4789 if (Tok.is(AsmToken::Integer)) {
4790 Save = Tok.getIntVal();
4791 SaveIsReg = false;
4792 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00004793 } else {
4794 reportParseError("expected save register or stack offset");
4795 Parser.eatToEndOfStatement();
4796 return false;
4797 }
4798 } else {
4799 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4800 if (!SaveOpnd.isGPRAsmReg()) {
4801 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
4802 Parser.eatToEndOfStatement();
4803 return false;
4804 }
4805 Save = SaveOpnd.getGPR32Reg();
4806 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004807
Toma Tabacu65f10572014-09-16 15:00:52 +00004808 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004809 return true;
4810
Toma Tabacu8874eac2015-02-18 13:46:53 +00004811 const MCExpr *Expr;
4812 if (Parser.parseExpression(Expr)) {
4813 reportParseError("expected expression");
4814 return false;
4815 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004816
Toma Tabacu8874eac2015-02-18 13:46:53 +00004817 if (Expr->getKind() != MCExpr::SymbolRef) {
4818 reportParseError("expected symbol");
4819 return false;
4820 }
4821 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
4822
4823 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
4824 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004825 return false;
4826}
4827
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004828bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004829 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004830 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4831 const AsmToken &Tok = Parser.getTok();
4832
4833 if (Tok.getString() == "2008") {
4834 Parser.Lex();
4835 getTargetStreamer().emitDirectiveNaN2008();
4836 return false;
4837 } else if (Tok.getString() == "legacy") {
4838 Parser.Lex();
4839 getTargetStreamer().emitDirectiveNaNLegacy();
4840 return false;
4841 }
4842 }
4843 // If we don't recognize the option passed to the .nan
4844 // directive (e.g. no option or unknown option), emit an error.
4845 reportParseError("invalid option in .nan directive");
4846 return false;
4847}
4848
Jack Carter0b744b32012-10-04 02:29:46 +00004849bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004850 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004851 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00004852 const AsmToken &Tok = Parser.getTok();
4853
4854 if (Tok.getString() == "noat") {
4855 return parseSetNoAtDirective();
4856 } else if (Tok.getString() == "at") {
4857 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00004858 } else if (Tok.getString() == "arch") {
4859 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004860 } else if (Tok.getString() == "fp") {
4861 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00004862 } else if (Tok.getString() == "oddspreg") {
4863 return parseSetOddSPRegDirective();
4864 } else if (Tok.getString() == "nooddspreg") {
4865 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004866 } else if (Tok.getString() == "pop") {
4867 return parseSetPopDirective();
4868 } else if (Tok.getString() == "push") {
4869 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00004870 } else if (Tok.getString() == "reorder") {
4871 return parseSetReorderDirective();
4872 } else if (Tok.getString() == "noreorder") {
4873 return parseSetNoReorderDirective();
4874 } else if (Tok.getString() == "macro") {
4875 return parseSetMacroDirective();
4876 } else if (Tok.getString() == "nomacro") {
4877 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00004878 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00004879 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00004880 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00004881 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00004882 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00004883 getTargetStreamer().emitDirectiveSetNoMicroMips();
4884 Parser.eatToEndOfStatement();
4885 return false;
4886 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004887 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00004888 } else if (Tok.getString() == "mips0") {
4889 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00004890 } else if (Tok.getString() == "mips1") {
4891 return parseSetFeature(Mips::FeatureMips1);
4892 } else if (Tok.getString() == "mips2") {
4893 return parseSetFeature(Mips::FeatureMips2);
4894 } else if (Tok.getString() == "mips3") {
4895 return parseSetFeature(Mips::FeatureMips3);
4896 } else if (Tok.getString() == "mips4") {
4897 return parseSetFeature(Mips::FeatureMips4);
4898 } else if (Tok.getString() == "mips5") {
4899 return parseSetFeature(Mips::FeatureMips5);
4900 } else if (Tok.getString() == "mips32") {
4901 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00004902 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004903 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00004904 } else if (Tok.getString() == "mips32r3") {
4905 return parseSetFeature(Mips::FeatureMips32r3);
4906 } else if (Tok.getString() == "mips32r5") {
4907 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00004908 } else if (Tok.getString() == "mips32r6") {
4909 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00004910 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004911 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00004912 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004913 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00004914 } else if (Tok.getString() == "mips64r3") {
4915 return parseSetFeature(Mips::FeatureMips64r3);
4916 } else if (Tok.getString() == "mips64r5") {
4917 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00004918 } else if (Tok.getString() == "mips64r6") {
4919 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00004920 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004921 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004922 } else if (Tok.getString() == "nodsp") {
4923 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00004924 } else if (Tok.getString() == "msa") {
4925 return parseSetMsaDirective();
4926 } else if (Tok.getString() == "nomsa") {
4927 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00004928 } else if (Tok.getString() == "softfloat") {
4929 return parseSetSoftFloatDirective();
4930 } else if (Tok.getString() == "hardfloat") {
4931 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00004932 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00004933 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00004934 parseSetAssignment();
4935 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004936 }
Jack Carter07c818d2013-01-25 01:31:34 +00004937
Jack Carter0b744b32012-10-04 02:29:46 +00004938 return true;
4939}
4940
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004941/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00004942/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004943bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004944 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004945 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4946 for (;;) {
4947 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004948 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00004949 return true;
4950
4951 getParser().getStreamer().EmitValue(Value, Size);
4952
4953 if (getLexer().is(AsmToken::EndOfStatement))
4954 break;
4955
Jack Carter07c818d2013-01-25 01:31:34 +00004956 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004957 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00004958 Parser.Lex();
4959 }
4960 }
4961
4962 Parser.Lex();
4963 return false;
4964}
4965
Vladimir Medic4c299852013-11-06 11:27:05 +00004966/// parseDirectiveGpWord
4967/// ::= .gpword local_sym
4968bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004969 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004970 const MCExpr *Value;
4971 // EmitGPRel32Value requires an expression, so we are using base class
4972 // method to evaluate the expression.
4973 if (getParser().parseExpression(Value))
4974 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00004975 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00004976
Vladimir Medice10c1122013-11-13 13:18:04 +00004977 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004978 return Error(getLexer().getLoc(),
4979 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00004980 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00004981 return false;
4982}
4983
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004984/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00004985/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004986bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004987 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004988 const MCExpr *Value;
4989 // EmitGPRel64Value requires an expression, so we are using base class
4990 // method to evaluate the expression.
4991 if (getParser().parseExpression(Value))
4992 return true;
4993 getParser().getStreamer().EmitGPRel64Value(Value);
4994
4995 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004996 return Error(getLexer().getLoc(),
4997 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00004998 Parser.Lex(); // Eat EndOfStatement token.
4999 return false;
5000}
5001
Jack Carter0cd3c192014-01-06 23:27:31 +00005002bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005003 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005004 // Get the option token.
5005 AsmToken Tok = Parser.getTok();
5006 // At the moment only identifiers are supported.
5007 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005008 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005009 Parser.eatToEndOfStatement();
5010 return false;
5011 }
5012
5013 StringRef Option = Tok.getIdentifier();
5014
5015 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005016 // MipsAsmParser needs to know if the current PIC mode changes.
5017 IsPicEnabled = false;
5018
Jack Carter0cd3c192014-01-06 23:27:31 +00005019 getTargetStreamer().emitDirectiveOptionPic0();
5020 Parser.Lex();
5021 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5022 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005023 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005024 Parser.eatToEndOfStatement();
5025 }
5026 return false;
5027 }
5028
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005029 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005030 // MipsAsmParser needs to know if the current PIC mode changes.
5031 IsPicEnabled = true;
5032
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005033 getTargetStreamer().emitDirectiveOptionPic2();
5034 Parser.Lex();
5035 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5036 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005037 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005038 Parser.eatToEndOfStatement();
5039 }
5040 return false;
5041 }
5042
Jack Carter0cd3c192014-01-06 23:27:31 +00005043 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005044 Warning(Parser.getTok().getLoc(),
5045 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005046 Parser.eatToEndOfStatement();
5047 return false;
5048}
5049
Toma Tabacu9ca50962015-04-16 09:53:47 +00005050/// parseInsnDirective
5051/// ::= .insn
5052bool MipsAsmParser::parseInsnDirective() {
5053 // If this is not the end of the statement, report an error.
5054 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5055 reportParseError("unexpected token, expected end of statement");
5056 return false;
5057 }
5058
5059 // The actual label marking happens in
5060 // MipsELFStreamer::createPendingLabelRelocs().
5061 getTargetStreamer().emitDirectiveInsn();
5062
5063 getParser().Lex(); // Eat EndOfStatement token.
5064 return false;
5065}
5066
Daniel Sanders7e527422014-07-10 13:38:23 +00005067/// parseDirectiveModule
5068/// ::= .module oddspreg
5069/// ::= .module nooddspreg
5070/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005071/// ::= .module softfloat
5072/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005073bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005074 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005075 MCAsmLexer &Lexer = getLexer();
5076 SMLoc L = Lexer.getLoc();
5077
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005078 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005079 // TODO : get a better message.
5080 reportParseError(".module directive must appear before any code");
5081 return false;
5082 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005083
Toma Tabacuc405c822015-01-23 10:40:19 +00005084 StringRef Option;
5085 if (Parser.parseIdentifier(Option)) {
5086 reportParseError("expected .module option identifier");
5087 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005088 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005089
Toma Tabacuc405c822015-01-23 10:40:19 +00005090 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005091 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005092
Toma Tabacu3c499582015-06-25 10:56:57 +00005093 // Synchronize the abiflags information with the FeatureBits information we
5094 // changed above.
5095 getTargetStreamer().updateABIInfo(*this);
5096
5097 // If printing assembly, use the recently updated abiflags information.
5098 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5099 // emitted at the end).
5100 getTargetStreamer().emitDirectiveModuleOddSPReg();
5101
Toma Tabacuc405c822015-01-23 10:40:19 +00005102 // If this is not the end of the statement, report an error.
5103 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5104 reportParseError("unexpected token, expected end of statement");
5105 return false;
5106 }
5107
5108 return false; // parseDirectiveModule has finished successfully.
5109 } else if (Option == "nooddspreg") {
5110 if (!isABI_O32()) {
5111 Error(L, "'.module nooddspreg' requires the O32 ABI");
5112 return false;
5113 }
5114
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005115 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005116
Toma Tabacu3c499582015-06-25 10:56:57 +00005117 // Synchronize the abiflags information with the FeatureBits information we
5118 // changed above.
5119 getTargetStreamer().updateABIInfo(*this);
5120
5121 // If printing assembly, use the recently updated abiflags information.
5122 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5123 // emitted at the end).
5124 getTargetStreamer().emitDirectiveModuleOddSPReg();
5125
Toma Tabacuc405c822015-01-23 10:40:19 +00005126 // If this is not the end of the statement, report an error.
5127 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5128 reportParseError("unexpected token, expected end of statement");
5129 return false;
5130 }
5131
5132 return false; // parseDirectiveModule has finished successfully.
5133 } else if (Option == "fp") {
5134 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005135 } else if (Option == "softfloat") {
5136 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5137
5138 // Synchronize the ABI Flags information with the FeatureBits information we
5139 // updated above.
5140 getTargetStreamer().updateABIInfo(*this);
5141
5142 // If printing assembly, use the recently updated ABI Flags information.
5143 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5144 // emitted later).
5145 getTargetStreamer().emitDirectiveModuleSoftFloat();
5146
5147 // If this is not the end of the statement, report an error.
5148 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5149 reportParseError("unexpected token, expected end of statement");
5150 return false;
5151 }
5152
5153 return false; // parseDirectiveModule has finished successfully.
5154 } else if (Option == "hardfloat") {
5155 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5156
5157 // Synchronize the ABI Flags information with the FeatureBits information we
5158 // updated above.
5159 getTargetStreamer().updateABIInfo(*this);
5160
5161 // If printing assembly, use the recently updated ABI Flags information.
5162 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5163 // emitted later).
5164 getTargetStreamer().emitDirectiveModuleHardFloat();
5165
5166 // If this is not the end of the statement, report an error.
5167 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5168 reportParseError("unexpected token, expected end of statement");
5169 return false;
5170 }
5171
5172 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005173 } else {
5174 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5175 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005176}
5177
5178/// parseDirectiveModuleFP
5179/// ::= =32
5180/// ::= =xx
5181/// ::= =64
5182bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005183 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005184 MCAsmLexer &Lexer = getLexer();
5185
5186 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005187 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005188 return false;
5189 }
5190 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005191
Daniel Sanders7e527422014-07-10 13:38:23 +00005192 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005193 if (!parseFpABIValue(FpABI, ".module"))
5194 return false;
5195
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005196 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005197 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005198 return false;
5199 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005200
Toma Tabacua64e5402015-06-25 12:44:38 +00005201 // Synchronize the abiflags information with the FeatureBits information we
5202 // changed above.
5203 getTargetStreamer().updateABIInfo(*this);
5204
5205 // If printing assembly, use the recently updated abiflags information.
5206 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5207 // emitted at the end).
5208 getTargetStreamer().emitDirectiveModuleFP();
5209
Daniel Sanders7e527422014-07-10 13:38:23 +00005210 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005211 return false;
5212}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005213
Daniel Sanders7e527422014-07-10 13:38:23 +00005214bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005215 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005216 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005217 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005218 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005219
5220 if (Lexer.is(AsmToken::Identifier)) {
5221 StringRef Value = Parser.getTok().getString();
5222 Parser.Lex();
5223
5224 if (Value != "xx") {
5225 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5226 return false;
5227 }
5228
5229 if (!isABI_O32()) {
5230 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5231 return false;
5232 }
5233
Daniel Sanders7e527422014-07-10 13:38:23 +00005234 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005235 if (ModuleLevelOptions) {
5236 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5237 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5238 } else {
5239 setFeatureBits(Mips::FeatureFPXX, "fpxx");
5240 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5241 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005242 return true;
5243 }
5244
5245 if (Lexer.is(AsmToken::Integer)) {
5246 unsigned Value = Parser.getTok().getIntVal();
5247 Parser.Lex();
5248
5249 if (Value != 32 && Value != 64) {
5250 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5251 return false;
5252 }
5253
5254 if (Value == 32) {
5255 if (!isABI_O32()) {
5256 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
5257 return false;
5258 }
5259
Daniel Sanders7e527422014-07-10 13:38:23 +00005260 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005261 if (ModuleLevelOptions) {
5262 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5263 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5264 } else {
5265 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5266 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5267 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005268 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00005269 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005270 if (ModuleLevelOptions) {
5271 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5272 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5273 } else {
5274 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5275 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
5276 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005277 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005278
Daniel Sanders7e527422014-07-10 13:38:23 +00005279 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005280 }
5281
5282 return false;
5283}
5284
Jack Carter0b744b32012-10-04 02:29:46 +00005285bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005286 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005287 StringRef IDVal = DirectiveID.getString();
5288
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005289 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005290 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00005291 if (IDVal == ".dword") {
5292 parseDataDirective(8, DirectiveID.getLoc());
5293 return false;
5294 }
Jack Carterd0bd6422013-04-18 00:41:53 +00005295 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005296 StringRef SymbolName;
5297
5298 if (Parser.parseIdentifier(SymbolName)) {
5299 reportParseError("expected identifier after .ent");
5300 return false;
5301 }
5302
5303 // There's an undocumented extension that allows an integer to
5304 // follow the name of the procedure which AFAICS is ignored by GAS.
5305 // Example: .ent foo,2
5306 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5307 if (getLexer().isNot(AsmToken::Comma)) {
5308 // Even though we accept this undocumented extension for compatibility
5309 // reasons, the additional integer argument does not actually change
5310 // the behaviour of the '.ent' directive, so we would like to discourage
5311 // its use. We do this by not referring to the extended version in
5312 // error messages which are not directly related to its use.
5313 reportParseError("unexpected token, expected end of statement");
5314 return false;
5315 }
5316 Parser.Lex(); // Eat the comma.
5317 const MCExpr *DummyNumber;
5318 int64_t DummyNumberVal;
5319 // If the user was explicitly trying to use the extended version,
5320 // we still give helpful extension-related error messages.
5321 if (Parser.parseExpression(DummyNumber)) {
5322 reportParseError("expected number after comma");
5323 return false;
5324 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00005325 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005326 reportParseError("expected an absolute expression after comma");
5327 return false;
5328 }
5329 }
5330
5331 // If this is not the end of the statement, report an error.
5332 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5333 reportParseError("unexpected token, expected end of statement");
5334 return false;
5335 }
5336
Jim Grosbach6f482002015-05-18 18:43:14 +00005337 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005338
5339 getTargetStreamer().emitDirectiveEnt(*Sym);
5340 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00005341 return false;
5342 }
5343
Jack Carter07c818d2013-01-25 01:31:34 +00005344 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005345 StringRef SymbolName;
5346
5347 if (Parser.parseIdentifier(SymbolName)) {
5348 reportParseError("expected identifier after .end");
5349 return false;
5350 }
5351
5352 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5353 reportParseError("unexpected token, expected end of statement");
5354 return false;
5355 }
5356
5357 if (CurrentFn == nullptr) {
5358 reportParseError(".end used without .ent");
5359 return false;
5360 }
5361
5362 if ((SymbolName != CurrentFn->getName())) {
5363 reportParseError(".end symbol does not match .ent symbol");
5364 return false;
5365 }
5366
5367 getTargetStreamer().emitDirectiveEnd(SymbolName);
5368 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00005369 return false;
5370 }
5371
Jack Carter07c818d2013-01-25 01:31:34 +00005372 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005373 // .frame $stack_reg, frame_size_in_bytes, $return_reg
5374 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005375 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005376 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5377 reportParseError("expected stack register");
5378 return false;
5379 }
5380
5381 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5382 if (!StackRegOpnd.isGPRAsmReg()) {
5383 reportParseError(StackRegOpnd.getStartLoc(),
5384 "expected general purpose register");
5385 return false;
5386 }
5387 unsigned StackReg = StackRegOpnd.getGPR32Reg();
5388
5389 if (Parser.getTok().is(AsmToken::Comma))
5390 Parser.Lex();
5391 else {
5392 reportParseError("unexpected token, expected comma");
5393 return false;
5394 }
5395
5396 // Parse the frame size.
5397 const MCExpr *FrameSize;
5398 int64_t FrameSizeVal;
5399
5400 if (Parser.parseExpression(FrameSize)) {
5401 reportParseError("expected frame size value");
5402 return false;
5403 }
5404
Jim Grosbach13760bd2015-05-30 01:25:56 +00005405 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005406 reportParseError("frame size not an absolute expression");
5407 return false;
5408 }
5409
5410 if (Parser.getTok().is(AsmToken::Comma))
5411 Parser.Lex();
5412 else {
5413 reportParseError("unexpected token, expected comma");
5414 return false;
5415 }
5416
5417 // Parse the return register.
5418 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00005419 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005420 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5421 reportParseError("expected return register");
5422 return false;
5423 }
5424
5425 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5426 if (!ReturnRegOpnd.isGPRAsmReg()) {
5427 reportParseError(ReturnRegOpnd.getStartLoc(),
5428 "expected general purpose register");
5429 return false;
5430 }
5431
5432 // If this is not the end of the statement, report an error.
5433 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5434 reportParseError("unexpected token, expected end of statement");
5435 return false;
5436 }
5437
5438 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
5439 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00005440 return false;
5441 }
5442
Jack Carter07c818d2013-01-25 01:31:34 +00005443 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00005444 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00005445 }
5446
Daniel Sandersd97a6342014-08-13 10:07:34 +00005447 if (IDVal == ".mask" || IDVal == ".fmask") {
5448 // .mask bitmask, frame_offset
5449 // bitmask: One bit for each register used.
5450 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
5451 // first register is expected to be saved.
5452 // Examples:
5453 // .mask 0x80000000, -4
5454 // .fmask 0x80000000, -4
5455 //
Jack Carterbe332172012-09-07 00:48:02 +00005456
Daniel Sandersd97a6342014-08-13 10:07:34 +00005457 // Parse the bitmask
5458 const MCExpr *BitMask;
5459 int64_t BitMaskVal;
5460
5461 if (Parser.parseExpression(BitMask)) {
5462 reportParseError("expected bitmask value");
5463 return false;
5464 }
5465
Jim Grosbach13760bd2015-05-30 01:25:56 +00005466 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005467 reportParseError("bitmask not an absolute expression");
5468 return false;
5469 }
5470
5471 if (Parser.getTok().is(AsmToken::Comma))
5472 Parser.Lex();
5473 else {
5474 reportParseError("unexpected token, expected comma");
5475 return false;
5476 }
5477
5478 // Parse the frame_offset
5479 const MCExpr *FrameOffset;
5480 int64_t FrameOffsetVal;
5481
5482 if (Parser.parseExpression(FrameOffset)) {
5483 reportParseError("expected frame offset value");
5484 return false;
5485 }
5486
Jim Grosbach13760bd2015-05-30 01:25:56 +00005487 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005488 reportParseError("frame offset not an absolute expression");
5489 return false;
5490 }
5491
5492 // If this is not the end of the statement, report an error.
5493 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5494 reportParseError("unexpected token, expected end of statement");
5495 return false;
5496 }
5497
5498 if (IDVal == ".mask")
5499 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
5500 else
5501 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00005502 return false;
5503 }
5504
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005505 if (IDVal == ".nan")
5506 return parseDirectiveNaN();
5507
Jack Carter07c818d2013-01-25 01:31:34 +00005508 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005509 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00005510 return false;
5511 }
5512
Rafael Espindolab59fb732014-03-28 18:50:26 +00005513 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005514 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005515 return false;
5516 }
5517
Jack Carter07c818d2013-01-25 01:31:34 +00005518 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005519 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00005520 return false;
5521 }
5522
Jack Carter0cd3c192014-01-06 23:27:31 +00005523 if (IDVal == ".option")
5524 return parseDirectiveOption();
5525
5526 if (IDVal == ".abicalls") {
5527 getTargetStreamer().emitDirectiveAbiCalls();
5528 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005529 Error(Parser.getTok().getLoc(),
5530 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005531 // Clear line
5532 Parser.eatToEndOfStatement();
5533 }
5534 return false;
5535 }
5536
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005537 if (IDVal == ".cpsetup")
5538 return parseDirectiveCPSetup();
5539
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005540 if (IDVal == ".module")
5541 return parseDirectiveModule();
5542
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005543 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
5544 return parseInternalDirectiveReallowModule();
5545
Toma Tabacu9ca50962015-04-16 09:53:47 +00005546 if (IDVal == ".insn")
5547 return parseInsnDirective();
5548
Rafael Espindola870c4e92012-01-11 03:56:41 +00005549 return true;
5550}
5551
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005552bool MipsAsmParser::parseInternalDirectiveReallowModule() {
5553 // If this is not the end of the statement, report an error.
5554 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5555 reportParseError("unexpected token, expected end of statement");
5556 return false;
5557 }
5558
5559 getTargetStreamer().reallowModuleDirective();
5560
5561 getParser().Lex(); // Eat EndOfStatement token.
5562 return false;
5563}
5564
Rafael Espindola870c4e92012-01-11 03:56:41 +00005565extern "C" void LLVMInitializeMipsAsmParser() {
5566 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
5567 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
5568 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
5569 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
5570}
Jack Carterb4dbc172012-09-05 23:34:03 +00005571
5572#define GET_REGISTER_MATCHER
5573#define GET_MATCHER_IMPLEMENTATION
5574#include "MipsGenAsmMatcher.inc"