blob: 8f4a05f634655bde186cd69c780fa8f878dc0b2e [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:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001428 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001429 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001430 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001431 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1432 Offset = Inst.getOperand(1);
1433 if (!Offset.isImm())
1434 break; // We'll deal with this situation later on when applying fixups.
1435 if (!isIntN(8, Offset.getImm()))
1436 return Error(IDLoc, "branch target out of range");
1437 if (OffsetToAlignment(Offset.getImm(), 2LL))
1438 return Error(IDLoc, "branch to misaligned address");
1439 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001440 }
1441 }
1442
Daniel Sandersa84989a2014-06-16 13:25:35 +00001443 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1444 // We still accept it but it is a normal nop.
1445 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1446 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1447 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1448 "nop instruction");
1449 }
1450
Kai Nackee0245392015-01-27 19:11:28 +00001451 if (hasCnMips()) {
1452 const unsigned Opcode = Inst.getOpcode();
1453 MCOperand Opnd;
1454 int Imm;
1455
1456 switch (Opcode) {
1457 default:
1458 break;
1459
1460 case Mips::BBIT0:
1461 case Mips::BBIT032:
1462 case Mips::BBIT1:
1463 case Mips::BBIT132:
1464 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1465 // The offset is handled above
1466 Opnd = Inst.getOperand(1);
1467 if (!Opnd.isImm())
1468 return Error(IDLoc, "expected immediate operand kind");
1469 Imm = Opnd.getImm();
1470 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1471 Opcode == Mips::BBIT1 ? 63 : 31))
1472 return Error(IDLoc, "immediate operand value out of range");
1473 if (Imm > 31) {
1474 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1475 : Mips::BBIT132);
1476 Inst.getOperand(1).setImm(Imm - 32);
1477 }
1478 break;
1479
1480 case Mips::CINS:
1481 case Mips::CINS32:
1482 case Mips::EXTS:
1483 case Mips::EXTS32:
1484 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1485 // Check length
1486 Opnd = Inst.getOperand(3);
1487 if (!Opnd.isImm())
1488 return Error(IDLoc, "expected immediate operand kind");
1489 Imm = Opnd.getImm();
1490 if (Imm < 0 || Imm > 31)
1491 return Error(IDLoc, "immediate operand value out of range");
1492 // Check position
1493 Opnd = Inst.getOperand(2);
1494 if (!Opnd.isImm())
1495 return Error(IDLoc, "expected immediate operand kind");
1496 Imm = Opnd.getImm();
1497 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1498 Opcode == Mips::EXTS ? 63 : 31))
1499 return Error(IDLoc, "immediate operand value out of range");
1500 if (Imm > 31) {
1501 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1502 Inst.getOperand(2).setImm(Imm - 32);
1503 }
1504 break;
1505
1506 case Mips::SEQi:
1507 case Mips::SNEi:
1508 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1509 Opnd = Inst.getOperand(2);
1510 if (!Opnd.isImm())
1511 return Error(IDLoc, "expected immediate operand kind");
1512 Imm = Opnd.getImm();
1513 if (!isInt<10>(Imm))
1514 return Error(IDLoc, "immediate operand value out of range");
1515 break;
1516 }
1517 }
1518
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001519 // This expansion is not in a function called by expandInstruction() because
1520 // the pseudo-instruction doesn't have a distinct opcode.
1521 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1522 inPicMode()) {
1523 warnIfNoMacro(IDLoc);
1524
1525 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1526
1527 // We can do this expansion if there's only 1 symbol in the argument
1528 // expression.
1529 if (countMCSymbolRefExpr(JalExpr) > 1)
1530 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1531
1532 // FIXME: This is checking the expression can be handled by the later stages
1533 // of the assembler. We ought to leave it to those later stages but
1534 // we can't do that until we stop evaluateRelocExpr() rewriting the
1535 // expressions into non-equivalent forms.
1536 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1537
1538 // FIXME: Add support for label+offset operands (currently causes an error).
1539 // FIXME: Add support for forward-declared local symbols.
1540 // FIXME: Add expansion for when the LargeGOT option is enabled.
1541 if (JalSym->isInSection() || JalSym->isTemporary()) {
1542 if (isABI_O32()) {
1543 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001544 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001545 // R_(MICRO)MIPS_GOT16 label
1546 // addiu $25, $25, 0
1547 // R_(MICRO)MIPS_LO16 label
1548 // jalr $25
1549 const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
1550 const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
1551
1552 MCInst LwInst;
1553 LwInst.setOpcode(Mips::LW);
1554 LwInst.addOperand(MCOperand::createReg(Mips::T9));
1555 LwInst.addOperand(MCOperand::createReg(Mips::GP));
1556 LwInst.addOperand(MCOperand::createExpr(Got16RelocExpr));
1557 Instructions.push_back(LwInst);
1558
1559 MCInst AddiuInst;
1560 AddiuInst.setOpcode(Mips::ADDiu);
1561 AddiuInst.addOperand(MCOperand::createReg(Mips::T9));
1562 AddiuInst.addOperand(MCOperand::createReg(Mips::T9));
1563 AddiuInst.addOperand(MCOperand::createExpr(Lo16RelocExpr));
1564 Instructions.push_back(AddiuInst);
1565 } else if (isABI_N32() || isABI_N64()) {
1566 // If it's a local symbol and the N32/N64 ABIs are being used,
1567 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001568 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001569 // R_(MICRO)MIPS_GOT_DISP label
1570 // jalr $25
1571 const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
1572
1573 MCInst LoadInst;
1574 LoadInst.setOpcode(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW);
1575 LoadInst.addOperand(MCOperand::createReg(Mips::T9));
1576 LoadInst.addOperand(MCOperand::createReg(Mips::GP));
1577 LoadInst.addOperand(MCOperand::createExpr(GotDispRelocExpr));
1578 Instructions.push_back(LoadInst);
1579 }
1580 } else {
1581 // If it's an external/weak symbol, we expand to:
1582 // lw/ld $25, 0($gp)
1583 // R_(MICRO)MIPS_CALL16 label
1584 // jalr $25
1585 const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
1586
1587 MCInst LoadInst;
1588 LoadInst.setOpcode(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW);
1589 LoadInst.addOperand(MCOperand::createReg(Mips::T9));
1590 LoadInst.addOperand(MCOperand::createReg(Mips::GP));
1591 LoadInst.addOperand(MCOperand::createExpr(Call16RelocExpr));
1592 Instructions.push_back(LoadInst);
1593 }
1594
1595 MCInst JalrInst;
1596 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
1597 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1598 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1599
1600 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1601 // This relocation is supposed to be an optimization hint for the linker
1602 // and is not necessary for correctness.
1603
1604 Inst = JalrInst;
1605 }
1606
Jack Carter9e65aa32013-03-22 00:05:30 +00001607 if (MCID.mayLoad() || MCID.mayStore()) {
1608 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001609 // reference or immediate we may have to expand instructions.
1610 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001611 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001612 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1613 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001614 MCOperand &Op = Inst.getOperand(i);
1615 if (Op.isImm()) {
1616 int MemOffset = Op.getImm();
1617 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001618 // Offset can't exceed 16bit value.
1619 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001620 return false;
1621 }
1622 } else if (Op.isExpr()) {
1623 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001624 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001625 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001626 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001627 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001628 // Expand symbol.
1629 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001630 return false;
1631 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001632 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001633 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001634 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001635 }
1636 }
1637 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001638 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001639 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001640
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001641 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001642 if (MCID.mayLoad()) {
1643 // Try to create 16-bit GP relative load instruction.
1644 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1645 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1646 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1647 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1648 MCOperand &Op = Inst.getOperand(i);
1649 if (Op.isImm()) {
1650 int MemOffset = Op.getImm();
1651 MCOperand &DstReg = Inst.getOperand(0);
1652 MCOperand &BaseReg = Inst.getOperand(1);
1653 if (isIntN(9, MemOffset) && (MemOffset % 4 == 0) &&
1654 getContext().getRegisterInfo()->getRegClass(
1655 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
1656 BaseReg.getReg() == Mips::GP) {
1657 MCInst TmpInst;
1658 TmpInst.setLoc(IDLoc);
1659 TmpInst.setOpcode(Mips::LWGP_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00001660 TmpInst.addOperand(MCOperand::createReg(DstReg.getReg()));
1661 TmpInst.addOperand(MCOperand::createReg(Mips::GP));
1662 TmpInst.addOperand(MCOperand::createImm(MemOffset));
Jozef Koleke10a02e2015-01-28 17:27:26 +00001663 Instructions.push_back(TmpInst);
1664 return false;
1665 }
1666 }
1667 }
1668 } // for
1669 } // if load
1670
1671 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1672
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001673 MCOperand Opnd;
1674 int Imm;
1675
1676 switch (Inst.getOpcode()) {
1677 default:
1678 break;
1679 case Mips::ADDIUS5_MM:
1680 Opnd = Inst.getOperand(2);
1681 if (!Opnd.isImm())
1682 return Error(IDLoc, "expected immediate operand kind");
1683 Imm = Opnd.getImm();
1684 if (Imm < -8 || Imm > 7)
1685 return Error(IDLoc, "immediate operand value out of range");
1686 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001687 case Mips::ADDIUSP_MM:
1688 Opnd = Inst.getOperand(0);
1689 if (!Opnd.isImm())
1690 return Error(IDLoc, "expected immediate operand kind");
1691 Imm = Opnd.getImm();
1692 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1693 Imm % 4 != 0)
1694 return Error(IDLoc, "immediate operand value out of range");
1695 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001696 case Mips::SLL16_MM:
1697 case Mips::SRL16_MM:
1698 Opnd = Inst.getOperand(2);
1699 if (!Opnd.isImm())
1700 return Error(IDLoc, "expected immediate operand kind");
1701 Imm = Opnd.getImm();
1702 if (Imm < 1 || Imm > 8)
1703 return Error(IDLoc, "immediate operand value out of range");
1704 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001705 case Mips::LI16_MM:
1706 Opnd = Inst.getOperand(1);
1707 if (!Opnd.isImm())
1708 return Error(IDLoc, "expected immediate operand kind");
1709 Imm = Opnd.getImm();
1710 if (Imm < -1 || Imm > 126)
1711 return Error(IDLoc, "immediate operand value out of range");
1712 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001713 case Mips::ADDIUR2_MM:
1714 Opnd = Inst.getOperand(2);
1715 if (!Opnd.isImm())
1716 return Error(IDLoc, "expected immediate operand kind");
1717 Imm = Opnd.getImm();
1718 if (!(Imm == 1 || Imm == -1 ||
1719 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1720 return Error(IDLoc, "immediate operand value out of range");
1721 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001722 case Mips::ADDIUR1SP_MM:
1723 Opnd = Inst.getOperand(1);
1724 if (!Opnd.isImm())
1725 return Error(IDLoc, "expected immediate operand kind");
1726 Imm = Opnd.getImm();
1727 if (OffsetToAlignment(Imm, 4LL))
1728 return Error(IDLoc, "misaligned immediate operand value");
1729 if (Imm < 0 || Imm > 255)
1730 return Error(IDLoc, "immediate operand value out of range");
1731 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001732 case Mips::ANDI16_MM:
1733 Opnd = Inst.getOperand(2);
1734 if (!Opnd.isImm())
1735 return Error(IDLoc, "expected immediate operand kind");
1736 Imm = Opnd.getImm();
1737 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1738 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1739 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1740 return Error(IDLoc, "immediate operand value out of range");
1741 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001742 case Mips::LBU16_MM:
1743 Opnd = Inst.getOperand(2);
1744 if (!Opnd.isImm())
1745 return Error(IDLoc, "expected immediate operand kind");
1746 Imm = Opnd.getImm();
1747 if (Imm < -1 || Imm > 14)
1748 return Error(IDLoc, "immediate operand value out of range");
1749 break;
1750 case Mips::SB16_MM:
1751 Opnd = Inst.getOperand(2);
1752 if (!Opnd.isImm())
1753 return Error(IDLoc, "expected immediate operand kind");
1754 Imm = Opnd.getImm();
1755 if (Imm < 0 || Imm > 15)
1756 return Error(IDLoc, "immediate operand value out of range");
1757 break;
1758 case Mips::LHU16_MM:
1759 case Mips::SH16_MM:
1760 Opnd = Inst.getOperand(2);
1761 if (!Opnd.isImm())
1762 return Error(IDLoc, "expected immediate operand kind");
1763 Imm = Opnd.getImm();
1764 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1765 return Error(IDLoc, "immediate operand value out of range");
1766 break;
1767 case Mips::LW16_MM:
1768 case Mips::SW16_MM:
1769 Opnd = Inst.getOperand(2);
1770 if (!Opnd.isImm())
1771 return Error(IDLoc, "expected immediate operand kind");
1772 Imm = Opnd.getImm();
1773 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1774 return Error(IDLoc, "immediate operand value out of range");
1775 break;
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001776 case Mips::CACHE:
1777 case Mips::PREF:
1778 Opnd = Inst.getOperand(2);
1779 if (!Opnd.isImm())
1780 return Error(IDLoc, "expected immediate operand kind");
1781 Imm = Opnd.getImm();
1782 if (!isUInt<5>(Imm))
1783 return Error(IDLoc, "immediate operand value out of range");
1784 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001785 case Mips::ADDIUPC_MM:
1786 MCOperand Opnd = Inst.getOperand(1);
1787 if (!Opnd.isImm())
1788 return Error(IDLoc, "expected immediate operand kind");
1789 int Imm = Opnd.getImm();
1790 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1791 return Error(IDLoc, "immediate operand value out of range");
1792 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001793 }
1794 }
1795
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001796 if (needsExpansion(Inst)) {
1797 if (expandInstruction(Inst, IDLoc, Instructions))
1798 return true;
1799 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001800 Instructions.push_back(Inst);
1801
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001802 // If this instruction has a delay slot and .set reorder is active,
1803 // emit a NOP after it.
1804 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1805 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1806
Jack Carter9e65aa32013-03-22 00:05:30 +00001807 return false;
1808}
1809
Jack Carter30a59822012-10-04 04:03:53 +00001810bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1811
Jack Carterd0bd6422013-04-18 00:41:53 +00001812 switch (Inst.getOpcode()) {
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001813 case Mips::LoadImm32:
1814 case Mips::LoadImm64:
1815 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001816 case Mips::LoadAddrImm64:
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001817 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001818 case Mips::LoadAddrReg64:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001819 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001820 case Mips::B_MMR6_Pseudo:
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001821 case Mips::LWM_MM:
1822 case Mips::SWM_MM:
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001823 case Mips::JalOneReg:
1824 case Mips::JalTwoReg:
Toma Tabacue1e460d2015-06-11 10:36:10 +00001825 case Mips::BneImm:
1826 case Mips::BeqImm:
Toma Tabacu1a108322015-06-17 13:20:24 +00001827 case Mips::BLT:
1828 case Mips::BLE:
1829 case Mips::BGE:
1830 case Mips::BGT:
1831 case Mips::BLTU:
1832 case Mips::BLEU:
1833 case Mips::BGEU:
1834 case Mips::BGTU:
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00001835 case Mips::SDivMacro:
1836 case Mips::UDivMacro:
1837 case Mips::DSDivMacro:
1838 case Mips::DUDivMacro:
Toma Tabacud88d79c2015-06-23 14:39:42 +00001839 case Mips::Ulhu:
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00001840 case Mips::Ulw:
Jack Carterd0bd6422013-04-18 00:41:53 +00001841 return true;
1842 default:
1843 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001844 }
1845}
Jack Carter92995f12012-10-06 00:53:28 +00001846
Matheus Almeida3813d572014-06-19 14:39:14 +00001847bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001848 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001849 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001850 default: llvm_unreachable("unimplemented expansion");
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001851 case Mips::LoadImm32:
Toma Tabacu00e98672015-05-01 12:19:27 +00001852 return expandLoadImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001853 case Mips::LoadImm64:
Toma Tabacu00e98672015-05-01 12:19:27 +00001854 return expandLoadImm(Inst, false, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001855 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001856 case Mips::LoadAddrImm64:
1857 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1858 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1859 "expected immediate operand kind");
1860
1861 return expandLoadAddress(
1862 Inst.getOperand(0).getReg(), Mips::NoRegister, Inst.getOperand(1),
1863 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001864 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001865 case Mips::LoadAddrReg64:
1866 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1867 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1868 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
1869 "expected immediate operand kind");
1870
1871 return expandLoadAddress(
1872 Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(), Inst.getOperand(2),
1873 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001874 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001875 case Mips::B_MMR6_Pseudo:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001876 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001877 case Mips::SWM_MM:
1878 case Mips::LWM_MM:
1879 return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001880 case Mips::JalOneReg:
1881 case Mips::JalTwoReg:
1882 return expandJalWithRegs(Inst, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00001883 case Mips::BneImm:
1884 case Mips::BeqImm:
1885 return expandBranchImm(Inst, IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00001886 case Mips::BLT:
1887 case Mips::BLE:
1888 case Mips::BGE:
1889 case Mips::BGT:
1890 case Mips::BLTU:
1891 case Mips::BLEU:
1892 case Mips::BGEU:
1893 case Mips::BGTU:
1894 return expandCondBranches(Inst, IDLoc, Instructions);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00001895 case Mips::SDivMacro:
1896 return expandDiv(Inst, IDLoc, Instructions, false, true);
1897 case Mips::DSDivMacro:
1898 return expandDiv(Inst, IDLoc, Instructions, true, true);
1899 case Mips::UDivMacro:
1900 return expandDiv(Inst, IDLoc, Instructions, false, false);
1901 case Mips::DUDivMacro:
1902 return expandDiv(Inst, IDLoc, Instructions, true, false);
Toma Tabacud88d79c2015-06-23 14:39:42 +00001903 case Mips::Ulhu:
1904 return expandUlhu(Inst, IDLoc, Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00001905 case Mips::Ulw:
1906 return expandUlw(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001907 }
Jack Carter30a59822012-10-04 04:03:53 +00001908}
Jack Carter92995f12012-10-06 00:53:28 +00001909
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001910namespace {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001911void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc,
Daniel Sanders03f9c012015-07-14 12:24:22 +00001912 SmallVectorImpl<MCInst> &Instructions) {
1913 MCInst tmpInst;
1914 tmpInst.setOpcode(Opcode);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001915 tmpInst.addOperand(MCOperand::createReg(Reg0));
1916 tmpInst.addOperand(Op1);
Daniel Sanders03f9c012015-07-14 12:24:22 +00001917 tmpInst.setLoc(IDLoc);
1918 Instructions.push_back(tmpInst);
1919}
1920
Daniel Sandersf1ae3672015-08-18 09:55:57 +00001921void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc,
Daniel Sanders03f9c012015-07-14 12:24:22 +00001922 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001923 emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00001924}
1925
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00001926void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc,
1927 SmallVectorImpl<MCInst> &Instructions) {
1928 emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, Instructions);
1929}
1930
1931void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc,
1932 SmallVectorImpl<MCInst> &Instructions) {
1933 MCInst tmpInst;
1934 tmpInst.setOpcode(Opcode);
1935 tmpInst.addOperand(MCOperand::createImm(Imm1));
1936 tmpInst.addOperand(MCOperand::createImm(Imm2));
1937 tmpInst.setLoc(IDLoc);
1938 Instructions.push_back(tmpInst);
1939}
1940
1941void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
1942 SmallVectorImpl<MCInst> &Instructions) {
1943 MCInst tmpInst;
1944 tmpInst.setOpcode(Opcode);
1945 tmpInst.addOperand(MCOperand::createReg(Reg0));
1946 tmpInst.setLoc(IDLoc);
1947 Instructions.push_back(tmpInst);
1948}
1949
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001950void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2,
Daniel Sanders03f9c012015-07-14 12:24:22 +00001951 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1952 MCInst tmpInst;
1953 tmpInst.setOpcode(Opcode);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001954 tmpInst.addOperand(MCOperand::createReg(Reg0));
1955 tmpInst.addOperand(MCOperand::createReg(Reg1));
1956 tmpInst.addOperand(Op2);
Daniel Sanders03f9c012015-07-14 12:24:22 +00001957 tmpInst.setLoc(IDLoc);
1958 Instructions.push_back(tmpInst);
1959}
1960
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001961void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
Daniel Sanders03f9c012015-07-14 12:24:22 +00001962 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001963 emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc,
Daniel Sanders03f9c012015-07-14 12:24:22 +00001964 Instructions);
1965}
1966
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001967void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
1968 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1969 emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc,
1970 Instructions);
1971}
Daniel Sanders03f9c012015-07-14 12:24:22 +00001972
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001973void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount,
1974 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1975 if (ShiftAmount >= 32) {
1976 emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc,
1977 Instructions);
Toma Tabacu7dea2e32015-04-28 14:06:35 +00001978 return;
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001979 }
Toma Tabacu7dea2e32015-04-28 14:06:35 +00001980
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001981 emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001982}
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001983} // end anonymous namespace.
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001984
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001985bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
1986 SmallVectorImpl<MCInst> &Instructions) {
1987 // Create a JALR instruction which is going to replace the pseudo-JAL.
1988 MCInst JalrInst;
1989 JalrInst.setLoc(IDLoc);
1990 const MCOperand FirstRegOp = Inst.getOperand(0);
1991 const unsigned Opcode = Inst.getOpcode();
1992
1993 if (Opcode == Mips::JalOneReg) {
1994 // jal $rs => jalr $rs
1995 if (inMicroMipsMode()) {
1996 JalrInst.setOpcode(Mips::JALR16_MM);
1997 JalrInst.addOperand(FirstRegOp);
1998 } else {
1999 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002000 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002001 JalrInst.addOperand(FirstRegOp);
2002 }
2003 } else if (Opcode == Mips::JalTwoReg) {
2004 // jal $rd, $rs => jalr $rd, $rs
2005 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
2006 JalrInst.addOperand(FirstRegOp);
2007 const MCOperand SecondRegOp = Inst.getOperand(1);
2008 JalrInst.addOperand(SecondRegOp);
2009 }
2010 Instructions.push_back(JalrInst);
2011
2012 // If .set reorder is active, emit a NOP after it.
2013 if (AssemblerOptions.back()->isReorder()) {
2014 // This is a 32-bit NOP because these 2 pseudo-instructions
2015 // do not have a short delay slot.
2016 MCInst NopInst;
2017 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00002018 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2019 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2020 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002021 Instructions.push_back(NopInst);
2022 }
2023
2024 return false;
2025}
2026
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002027/// Can the value be represented by a unsigned N-bit value and a shift left?
2028template<unsigned N>
2029bool isShiftedUIntAtAnyPosition(uint64_t x) {
2030 unsigned BitNum = findFirstSet(x);
2031
2032 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2033}
2034
2035/// Load (or add) an immediate into a register.
2036///
2037/// @param ImmValue The immediate to load.
2038/// @param DstReg The register that will hold the immediate.
2039/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2040/// for a simple initialization.
2041/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2042/// @param IsAddress True if the immediate represents an address. False if it
2043/// is an integer.
2044/// @param IDLoc Location of the immediate in the source file.
2045/// @param Instructions The instructions emitted by this expansion.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002046bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002047 unsigned SrcReg, bool Is32BitImm,
2048 bool IsAddress, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00002049 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00002050 if (!Is32BitImm && !isGP64bit()) {
2051 Error(IDLoc, "instruction requires a 64-bit architecture");
2052 return true;
2053 }
2054
Daniel Sanders03f9c012015-07-14 12:24:22 +00002055 if (Is32BitImm) {
2056 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2057 // Sign extend up to 64-bit so that the predicates match the hardware
2058 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2059 // true.
2060 ImmValue = SignExtend64<32>(ImmValue);
2061 } else {
2062 Error(IDLoc, "instruction requires a 32-bit immediate");
2063 return true;
2064 }
2065 }
2066
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002067 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2068 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2069
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002070 bool UseSrcReg = false;
2071 if (SrcReg != Mips::NoRegister)
2072 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002073
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002074 unsigned TmpReg = DstReg;
2075 if (UseSrcReg && (DstReg == SrcReg)) {
2076 // At this point we need AT to perform the expansions and we exit if it is
2077 // not available.
2078 unsigned ATReg = getATReg(IDLoc);
2079 if (!ATReg)
2080 return true;
2081 TmpReg = ATReg;
2082 }
2083
Daniel Sanders03f9c012015-07-14 12:24:22 +00002084 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002085 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002086 SrcReg = ZeroReg;
2087
2088 // This doesn't quite follow the usual ABI expectations for N32 but matches
2089 // traditional assembler behaviour. N32 would normally use addiu for both
2090 // integers and addresses.
2091 if (IsAddress && !Is32BitImm) {
2092 emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2093 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002094 }
2095
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002096 emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2097 return false;
2098 }
2099
2100 if (isUInt<16>(ImmValue)) {
2101 unsigned TmpReg = DstReg;
2102 if (SrcReg == DstReg) {
2103 TmpReg = getATReg(IDLoc);
2104 if (!TmpReg)
2105 return true;
2106 }
2107
2108 emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002109 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002110 emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2111 return false;
2112 }
2113
2114 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002115 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002116
Toma Tabacu79588102015-04-29 10:19:56 +00002117 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2118 uint16_t Bits15To0 = ImmValue & 0xffff;
2119
Toma Tabacua3d056f2015-05-15 09:42:11 +00002120 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002121 // Traditional behaviour seems to special case this particular value. It's
2122 // not clear why other masks are handled differently.
2123 if (ImmValue == 0xffffffff) {
Daniel Sandersf1ae3672015-08-18 09:55:57 +00002124 emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002125 emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, Instructions);
2126 if (UseSrcReg)
2127 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2128 return false;
2129 }
2130
2131 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002132 // upper 32 bits.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002133 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002134 emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002135 if (Bits15To0)
2136 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
2137 if (UseSrcReg)
2138 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2139 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002140 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002141
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002142 emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions);
2143 if (Bits15To0)
2144 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002145 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002146 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2147 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002148 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002149
2150 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2151 if (Is32BitImm) {
2152 Error(IDLoc, "instruction requires a 32-bit immediate");
2153 return true;
2154 }
2155
2156 // Traditionally, these immediates are shifted as little as possible and as
2157 // such we align the most significant bit to bit 15 of our temporary.
2158 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2159 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2160 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2161 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
2162 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, Instructions);
2163 emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, Instructions);
2164
2165 if (UseSrcReg)
2166 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2167
2168 return false;
2169 }
2170
2171 warnIfNoMacro(IDLoc);
2172
2173 // The remaining case is packed with a sequence of dsll and ori with zeros
2174 // being omitted and any neighbouring dsll's being coalesced.
2175 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2176
2177 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2178 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
2179 IDLoc, Instructions))
2180 return false;
2181
2182 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2183 // skip it and defer the shift to the next chunk.
2184 unsigned ShiftCarriedForwards = 16;
2185 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2186 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2187
2188 if (ImmChunk != 0) {
2189 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2190 Instructions);
2191 emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, Instructions);
2192 ShiftCarriedForwards = 0;
2193 }
2194
2195 ShiftCarriedForwards += 16;
2196 }
2197 ShiftCarriedForwards -= 16;
2198
2199 // Finish any remaining shifts left by trailing zeros.
2200 if (ShiftCarriedForwards)
2201 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2202 Instructions);
2203
2204 if (UseSrcReg)
2205 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2206
Matheus Almeida3813d572014-06-19 14:39:14 +00002207 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002208}
Jack Carter92995f12012-10-06 00:53:28 +00002209
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002210bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
2211 SmallVectorImpl<MCInst> &Instructions) {
2212 const MCOperand &ImmOp = Inst.getOperand(1);
2213 assert(ImmOp.isImm() && "expected immediate operand kind");
2214 const MCOperand &DstRegOp = Inst.getOperand(0);
2215 assert(DstRegOp.isReg() && "expected register operand kind");
2216
2217 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002218 Is32BitImm, false, IDLoc, Instructions))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002219 return true;
2220
2221 return false;
2222}
2223
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002224bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2225 const MCOperand &Offset,
2226 bool Is32BitAddress, SMLoc IDLoc,
2227 SmallVectorImpl<MCInst> &Instructions) {
2228 // la can't produce a usable address when addresses are 64-bit.
2229 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2230 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2231 // We currently can't do this because we depend on the equality
2232 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2233 Error(IDLoc, "la used to load 64-bit address");
2234 // Continue as if we had 'dla' instead.
2235 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002236 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002237
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002238 // dla requires 64-bit addresses.
2239 if (!Is32BitAddress && !ABI.ArePtrs64bit()) {
2240 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002241 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002242 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002243
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002244 if (!Offset.isImm())
2245 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
2246 Is32BitAddress, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002247
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002248 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
2249 IDLoc, Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +00002250}
2251
Toma Tabacuf712ede2015-06-17 14:31:51 +00002252bool MipsAsmParser::loadAndAddSymbolAddress(
2253 const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
2254 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002255 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002256
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002257 // FIXME: The way we're handling symbols right now prevents simple expressions
2258 // like foo+8. We'll be able to fix this once our unary operators (%hi
2259 // and similar) are treated as operators rather than as fixup types.
Toma Tabacu674825c2015-06-16 12:16:24 +00002260 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymExpr);
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002261 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::create(
2262 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
2263 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::create(
2264 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
2265
Toma Tabacufb9d1252015-06-22 12:08:39 +00002266 bool UseSrcReg = SrcReg != Mips::NoRegister;
2267
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002268 // This is the 64-bit symbol address expansion.
2269 if (ABI.ArePtrs64bit() && isGP64bit()) {
2270 // We always need AT for the 64-bit expansion.
2271 // If it is not available we exit.
2272 unsigned ATReg = getATReg(IDLoc);
2273 if (!ATReg)
2274 return true;
2275
2276 const MCSymbolRefExpr *HighestExpr = MCSymbolRefExpr::create(
2277 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
2278 const MCSymbolRefExpr *HigherExpr = MCSymbolRefExpr::create(
2279 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
2280
2281 if (UseSrcReg && (DstReg == SrcReg)) {
2282 // If $rs is the same as $rd:
2283 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2284 // daddiu $at, $at, %higher(sym)
2285 // dsll $at, $at, 16
2286 // daddiu $at, $at, %hi(sym)
2287 // dsll $at, $at, 16
2288 // daddiu $at, $at, %lo(sym)
2289 // daddu $rd, $at, $rd
2290 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2291 Instructions);
2292 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr),
2293 IDLoc, Instructions);
2294 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2295 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2296 Instructions);
2297 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2298 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2299 Instructions);
2300 emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions);
2301
2302 return false;
2303 }
2304
2305 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2306 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2307 // lui $at, %hi(sym)
2308 // daddiu $rd, $rd, %higher(sym)
2309 // daddiu $at, $at, %lo(sym)
2310 // dsll32 $rd, $rd, 0
2311 // daddu $rd, $rd, $at
2312 // (daddu $rd, $rd, $rs)
2313 emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2314 Instructions);
2315 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2316 Instructions);
2317 emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr),
2318 IDLoc, Instructions);
2319 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2320 Instructions);
2321 emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions);
2322 emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions);
2323 if (UseSrcReg)
2324 emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions);
2325
2326 return false;
2327 }
2328
2329 // And now, the 32-bit symbol address expansion:
2330 // If $rs is the same as $rd:
2331 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2332 // ori $at, $at, %lo(sym)
2333 // addu $rd, $at, $rd
2334 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2335 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2336 // ori $rd, $rd, %lo(sym)
2337 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002338 unsigned TmpReg = DstReg;
2339 if (UseSrcReg && (DstReg == SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002340 // If $rs is the same as $rd, we need to use AT.
2341 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002342 unsigned ATReg = getATReg(IDLoc);
2343 if (!ATReg)
2344 return true;
2345 TmpReg = ATReg;
2346 }
2347
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002348 emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions);
2349 emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc,
2350 Instructions);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002351
Toma Tabacufb9d1252015-06-22 12:08:39 +00002352 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002353 emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2354 else
2355 assert(DstReg == TmpReg);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002356
Toma Tabacu674825c2015-06-16 12:16:24 +00002357 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002358}
2359
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002360bool MipsAsmParser::expandUncondBranchMMPseudo(
2361 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002362 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2363 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002364
2365 MCOperand Offset = Inst.getOperand(0);
2366 if (Offset.isExpr()) {
2367 Inst.clear();
2368 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002369 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2370 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2371 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002372 } else {
2373 assert(Offset.isImm() && "expected immediate operand kind");
2374 if (isIntN(11, Offset.getImm())) {
2375 // If offset fits into 11 bits then this instruction becomes microMIPS
2376 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002377 if (inMicroMipsMode())
2378 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002379 } else {
2380 if (!isIntN(17, Offset.getImm()))
2381 Error(IDLoc, "branch target out of range");
2382 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2383 Error(IDLoc, "branch to misaligned address");
2384 Inst.clear();
2385 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002386 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2387 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2388 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002389 }
2390 }
2391 Instructions.push_back(Inst);
2392
Zoran Jovanovicada70912015-09-07 11:56:37 +00002393 // If .set reorder is active and branch instruction has a delay slot,
2394 // emit a NOP after it.
2395 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2396 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Toma Tabacu234482a2015-03-16 12:03:39 +00002397 createNop(true, IDLoc, Instructions);
2398
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002399 return false;
2400}
2401
Toma Tabacue1e460d2015-06-11 10:36:10 +00002402bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2403 SmallVectorImpl<MCInst> &Instructions) {
2404 const MCOperand &DstRegOp = Inst.getOperand(0);
2405 assert(DstRegOp.isReg() && "expected register operand kind");
2406
2407 const MCOperand &ImmOp = Inst.getOperand(1);
2408 assert(ImmOp.isImm() && "expected immediate operand kind");
2409
2410 const MCOperand &MemOffsetOp = Inst.getOperand(2);
2411 assert(MemOffsetOp.isImm() && "expected immediate operand kind");
2412
2413 unsigned OpCode = 0;
2414 switch(Inst.getOpcode()) {
2415 case Mips::BneImm:
2416 OpCode = Mips::BNE;
2417 break;
2418 case Mips::BeqImm:
2419 OpCode = Mips::BEQ;
2420 break;
2421 default:
2422 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2423 break;
2424 }
2425
2426 int64_t ImmValue = ImmOp.getImm();
2427 if (ImmValue == 0) {
2428 MCInst BranchInst;
2429 BranchInst.setOpcode(OpCode);
2430 BranchInst.addOperand(DstRegOp);
2431 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2432 BranchInst.addOperand(MemOffsetOp);
2433 Instructions.push_back(BranchInst);
2434 } else {
2435 warnIfNoMacro(IDLoc);
2436
2437 unsigned ATReg = getATReg(IDLoc);
2438 if (!ATReg)
2439 return true;
2440
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002441 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
2442 IDLoc, Instructions))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002443 return true;
2444
2445 MCInst BranchInst;
2446 BranchInst.setOpcode(OpCode);
2447 BranchInst.addOperand(DstRegOp);
2448 BranchInst.addOperand(MCOperand::createReg(ATReg));
2449 BranchInst.addOperand(MemOffsetOp);
2450 Instructions.push_back(BranchInst);
2451 }
2452 return false;
2453}
2454
Jack Carter9e65aa32013-03-22 00:05:30 +00002455void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002456 SmallVectorImpl<MCInst> &Instructions,
2457 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002458 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00002459 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002460 const MCExpr *ExprOffset;
2461 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002462 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002463 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2464 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002465 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002466 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2467 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002468 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002469 if (isImmOpnd) {
2470 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2471 ImmOffset = Inst.getOperand(2).getImm();
2472 LoOffset = ImmOffset & 0x0000ffff;
2473 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002474 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002475 if (LoOffset & 0x8000)
2476 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002477 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002478 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002479 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002480 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002481 // These are some of the types of expansions we perform here:
2482 // 1) lw $8, sym => lui $8, %hi(sym)
2483 // lw $8, %lo(sym)($8)
2484 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2485 // add $8, $8, $9
2486 // lw $8, %lo(offset)($9)
2487 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2488 // add $at, $at, $8
2489 // lw $8, %lo(offset)($at)
2490 // 4) sw $8, sym => lui $at, %hi(sym)
2491 // sw $8, %lo(sym)($at)
2492 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2493 // add $at, $at, $8
2494 // sw $8, %lo(offset)($at)
2495 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2496 // ldc1 $f0, %lo(sym)($at)
2497 //
2498 // For load instructions we can use the destination register as a temporary
2499 // if base and dst are different (examples 1 and 2) and if the base register
2500 // is general purpose otherwise we must use $at (example 6) and error if it's
2501 // not available. For stores we must use $at (examples 4 and 5) because we
2502 // must not clobber the source register setting up the offset.
2503 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2504 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2505 unsigned RegClassIDOp0 =
2506 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2507 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2508 (RegClassIDOp0 == Mips::GPR64RegClassID);
2509 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002510 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002511 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002512 // At this point we need AT to perform the expansions and we exit if it is
2513 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002514 TmpRegNum = getATReg(IDLoc);
2515 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002516 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002517 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002518
Jack Carter9e65aa32013-03-22 00:05:30 +00002519 TempInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00002520 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002521 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002522 TempInst.addOperand(MCOperand::createImm(HiOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002523 else {
Toma Tabacu07c97b32015-06-17 10:43:45 +00002524 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
2525 TempInst.addOperand(MCOperand::createExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002526 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002527 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002528 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002529 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002530 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002531 // Add temp register to base.
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002532 if (BaseRegNum != Mips::ZERO) {
2533 TempInst.setOpcode(Mips::ADDu);
Jim Grosbache9119e42015-05-13 18:37:00 +00002534 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2535 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2536 TempInst.addOperand(MCOperand::createReg(BaseRegNum));
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002537 Instructions.push_back(TempInst);
2538 TempInst.clear();
2539 }
Alp Tokercb402912014-01-24 17:20:08 +00002540 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002541 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002542 TempInst.setOpcode(Inst.getOpcode());
Jim Grosbache9119e42015-05-13 18:37:00 +00002543 TempInst.addOperand(MCOperand::createReg(RegOpNum));
2544 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002545 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002546 TempInst.addOperand(MCOperand::createImm(LoOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002547 else {
Toma Tabacu07c97b32015-06-17 10:43:45 +00002548 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
2549 TempInst.addOperand(MCOperand::createExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002550 }
2551 Instructions.push_back(TempInst);
2552 TempInst.clear();
2553}
2554
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002555bool
2556MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2557 SmallVectorImpl<MCInst> &Instructions) {
2558 unsigned OpNum = Inst.getNumOperands();
2559 unsigned Opcode = Inst.getOpcode();
2560 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2561
2562 assert (Inst.getOperand(OpNum - 1).isImm() &&
2563 Inst.getOperand(OpNum - 2).isReg() &&
2564 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2565
2566 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2567 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2568 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2569 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2570 // It can be implemented as SWM16 or LWM16 instruction.
2571 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2572
2573 Inst.setOpcode(NewOpcode);
2574 Instructions.push_back(Inst);
2575 return false;
2576}
2577
Toma Tabacu1a108322015-06-17 13:20:24 +00002578bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2579 SmallVectorImpl<MCInst> &Instructions) {
2580 unsigned PseudoOpcode = Inst.getOpcode();
2581 unsigned SrcReg = Inst.getOperand(0).getReg();
2582 unsigned TrgReg = Inst.getOperand(1).getReg();
2583 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2584
2585 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
2586 bool ReverseOrderSLT, IsUnsigned, AcceptsEquality;
2587
2588 switch (PseudoOpcode) {
2589 case Mips::BLT:
2590 case Mips::BLTU:
2591 AcceptsEquality = false;
2592 ReverseOrderSLT = false;
2593 IsUnsigned = (PseudoOpcode == Mips::BLTU);
2594 ZeroSrcOpcode = Mips::BGTZ;
2595 ZeroTrgOpcode = Mips::BLTZ;
2596 break;
2597 case Mips::BLE:
2598 case Mips::BLEU:
2599 AcceptsEquality = true;
2600 ReverseOrderSLT = true;
2601 IsUnsigned = (PseudoOpcode == Mips::BLEU);
2602 ZeroSrcOpcode = Mips::BGEZ;
2603 ZeroTrgOpcode = Mips::BLEZ;
2604 break;
2605 case Mips::BGE:
2606 case Mips::BGEU:
2607 AcceptsEquality = true;
2608 ReverseOrderSLT = false;
2609 IsUnsigned = (PseudoOpcode == Mips::BGEU);
2610 ZeroSrcOpcode = Mips::BLEZ;
2611 ZeroTrgOpcode = Mips::BGEZ;
2612 break;
2613 case Mips::BGT:
2614 case Mips::BGTU:
2615 AcceptsEquality = false;
2616 ReverseOrderSLT = true;
2617 IsUnsigned = (PseudoOpcode == Mips::BGTU);
2618 ZeroSrcOpcode = Mips::BLTZ;
2619 ZeroTrgOpcode = Mips::BGTZ;
2620 break;
2621 default:
2622 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2623 }
2624
2625 MCInst BranchInst;
2626 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2627 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2628 if (IsSrcRegZero && IsTrgRegZero) {
2629 // FIXME: All of these Opcode-specific if's are needed for compatibility
2630 // with GAS' behaviour. However, they may not generate the most efficient
2631 // code in some circumstances.
2632 if (PseudoOpcode == Mips::BLT) {
2633 BranchInst.setOpcode(Mips::BLTZ);
2634 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2635 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2636 Instructions.push_back(BranchInst);
2637 return false;
2638 }
2639 if (PseudoOpcode == Mips::BLE) {
2640 BranchInst.setOpcode(Mips::BLEZ);
2641 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2642 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2643 Instructions.push_back(BranchInst);
2644 Warning(IDLoc, "branch is always taken");
2645 return false;
2646 }
2647 if (PseudoOpcode == Mips::BGE) {
2648 BranchInst.setOpcode(Mips::BGEZ);
2649 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2650 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2651 Instructions.push_back(BranchInst);
2652 Warning(IDLoc, "branch is always taken");
2653 return false;
2654 }
2655 if (PseudoOpcode == Mips::BGT) {
2656 BranchInst.setOpcode(Mips::BGTZ);
2657 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2658 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2659 Instructions.push_back(BranchInst);
2660 return false;
2661 }
2662 if (PseudoOpcode == Mips::BGTU) {
2663 BranchInst.setOpcode(Mips::BNE);
2664 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2665 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2666 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2667 Instructions.push_back(BranchInst);
2668 return false;
2669 }
2670 if (AcceptsEquality) {
2671 // If both registers are $0 and the pseudo-branch accepts equality, it
2672 // will always be taken, so we emit an unconditional branch.
2673 BranchInst.setOpcode(Mips::BEQ);
2674 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2675 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2676 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2677 Instructions.push_back(BranchInst);
2678 Warning(IDLoc, "branch is always taken");
2679 return false;
2680 }
2681 // If both registers are $0 and the pseudo-branch does not accept
2682 // equality, it will never be taken, so we don't have to emit anything.
2683 return false;
2684 }
2685 if (IsSrcRegZero || IsTrgRegZero) {
2686 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2687 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2688 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2689 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2690 // the pseudo-branch will never be taken, so we don't emit anything.
2691 // This only applies to unsigned pseudo-branches.
2692 return false;
2693 }
2694 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2695 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2696 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2697 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2698 // the pseudo-branch will always be taken, so we emit an unconditional
2699 // branch.
2700 // This only applies to unsigned pseudo-branches.
2701 BranchInst.setOpcode(Mips::BEQ);
2702 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2703 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2704 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2705 Instructions.push_back(BranchInst);
2706 Warning(IDLoc, "branch is always taken");
2707 return false;
2708 }
2709 if (IsUnsigned) {
2710 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2711 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2712 // the pseudo-branch will be taken only when the non-zero register is
2713 // different from 0, so we emit a BNEZ.
2714 //
2715 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2716 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2717 // the pseudo-branch will be taken only when the non-zero register is
2718 // equal to 0, so we emit a BEQZ.
2719 //
2720 // Because only BLEU and BGEU branch on equality, we can use the
2721 // AcceptsEquality variable to decide when to emit the BEQZ.
2722 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQ : Mips::BNE);
2723 BranchInst.addOperand(
2724 MCOperand::createReg(IsSrcRegZero ? TrgReg : SrcReg));
2725 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2726 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2727 Instructions.push_back(BranchInst);
2728 return false;
2729 }
2730 // If we have a signed pseudo-branch and one of the registers is $0,
2731 // we can use an appropriate compare-to-zero branch. We select which one
2732 // to use in the switch statement above.
2733 BranchInst.setOpcode(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode);
2734 BranchInst.addOperand(MCOperand::createReg(IsSrcRegZero ? TrgReg : SrcReg));
2735 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2736 Instructions.push_back(BranchInst);
2737 return false;
2738 }
2739
2740 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2741 // expansions. If it is not available, we return.
2742 unsigned ATRegNum = getATReg(IDLoc);
2743 if (!ATRegNum)
2744 return true;
2745
2746 warnIfNoMacro(IDLoc);
2747
2748 // SLT fits well with 2 of our 4 pseudo-branches:
2749 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2750 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2751 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2752 // This is accomplished by using a BNEZ with the result of the SLT.
2753 //
2754 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2755 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2756 // Because only BGE and BLE branch on equality, we can use the
2757 // AcceptsEquality variable to decide when to emit the BEQZ.
2758 // Note that the order of the SLT arguments doesn't change between
2759 // opposites.
2760 //
2761 // The same applies to the unsigned variants, except that SLTu is used
2762 // instead of SLT.
2763 MCInst SetInst;
2764 SetInst.setOpcode(IsUnsigned ? Mips::SLTu : Mips::SLT);
2765 SetInst.addOperand(MCOperand::createReg(ATRegNum));
2766 SetInst.addOperand(MCOperand::createReg(ReverseOrderSLT ? TrgReg : SrcReg));
2767 SetInst.addOperand(MCOperand::createReg(ReverseOrderSLT ? SrcReg : TrgReg));
2768 Instructions.push_back(SetInst);
2769
2770 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQ : Mips::BNE);
2771 BranchInst.addOperand(MCOperand::createReg(ATRegNum));
2772 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2773 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2774 Instructions.push_back(BranchInst);
2775 return false;
2776}
2777
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002778bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
2779 SmallVectorImpl<MCInst> &Instructions,
2780 const bool IsMips64, const bool Signed) {
2781 if (hasMips32r6()) {
2782 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2783 return false;
2784 }
2785
2786 warnIfNoMacro(IDLoc);
2787
2788 const MCOperand &RsRegOp = Inst.getOperand(0);
2789 assert(RsRegOp.isReg() && "expected register operand kind");
2790 unsigned RsReg = RsRegOp.getReg();
2791
2792 const MCOperand &RtRegOp = Inst.getOperand(1);
2793 assert(RtRegOp.isReg() && "expected register operand kind");
2794 unsigned RtReg = RtRegOp.getReg();
2795 unsigned DivOp;
2796 unsigned ZeroReg;
2797
2798 if (IsMips64) {
2799 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2800 ZeroReg = Mips::ZERO_64;
2801 } else {
2802 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2803 ZeroReg = Mips::ZERO;
2804 }
2805
2806 bool UseTraps = useTraps();
2807
2808 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2809 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2810 Warning(IDLoc, "dividing zero by zero");
2811 if (IsMips64) {
2812 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2813 if (UseTraps) {
2814 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2815 return false;
2816 }
2817
2818 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2819 return false;
2820 }
2821 } else {
2822 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2823 return false;
2824 }
2825 }
2826
2827 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
2828 Warning(IDLoc, "division by zero");
2829 if (Signed) {
2830 if (UseTraps) {
2831 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2832 return false;
2833 }
2834
2835 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2836 return false;
2837 }
2838 }
2839
2840 // FIXME: The values for these two BranchTarget variables may be different in
2841 // micromips. These magic numbers need to be removed.
2842 unsigned BranchTargetNoTraps;
2843 unsigned BranchTarget;
2844
2845 if (UseTraps) {
2846 BranchTarget = IsMips64 ? 12 : 8;
2847 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2848 } else {
2849 BranchTarget = IsMips64 ? 20 : 16;
2850 BranchTargetNoTraps = 8;
2851 // Branch to the li instruction.
2852 emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc,
2853 Instructions);
2854 }
2855
2856 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2857
2858 if (!UseTraps)
2859 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2860
2861 if (!Signed) {
2862 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
2863 return false;
2864 }
2865
2866 unsigned ATReg = getATReg(IDLoc);
2867 if (!ATReg)
2868 return true;
2869
2870 emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, Instructions);
2871 if (IsMips64) {
2872 // Branch to the mflo instruction.
2873 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
2874 emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, Instructions);
2875 emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, Instructions);
2876 } else {
2877 // Branch to the mflo instruction.
2878 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
2879 emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, Instructions);
2880 }
2881
2882 if (UseTraps)
2883 emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, Instructions);
2884 else {
2885 // Branch to the mflo instruction.
2886 emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, Instructions);
2887 emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, Instructions);
2888 emitII(Mips::BREAK, 0x6, 0, IDLoc, Instructions);
2889 }
2890 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
2891 return false;
2892}
2893
Toma Tabacud88d79c2015-06-23 14:39:42 +00002894bool MipsAsmParser::expandUlhu(MCInst &Inst, SMLoc IDLoc,
2895 SmallVectorImpl<MCInst> &Instructions) {
2896 if (hasMips32r6() || hasMips64r6()) {
2897 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2898 return false;
2899 }
2900
2901 warnIfNoMacro(IDLoc);
2902
2903 const MCOperand &DstRegOp = Inst.getOperand(0);
2904 assert(DstRegOp.isReg() && "expected register operand kind");
2905
2906 const MCOperand &SrcRegOp = Inst.getOperand(1);
2907 assert(SrcRegOp.isReg() && "expected register operand kind");
2908
2909 const MCOperand &OffsetImmOp = Inst.getOperand(2);
2910 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
2911
2912 unsigned DstReg = DstRegOp.getReg();
2913 unsigned SrcReg = SrcRegOp.getReg();
2914 int64_t OffsetValue = OffsetImmOp.getImm();
2915
2916 // NOTE: We always need AT for ULHU, as it is always used as the source
2917 // register for one of the LBu's.
2918 unsigned ATReg = getATReg(IDLoc);
2919 if (!ATReg)
2920 return true;
2921
2922 // When the value of offset+1 does not fit in 16 bits, we have to load the
2923 // offset in AT, (D)ADDu the original source register (if there was one), and
2924 // then use AT as the source register for the 2 generated LBu's.
2925 bool LoadedOffsetInAT = false;
2926 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
2927 LoadedOffsetInAT = true;
2928
2929 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002930 true, IDLoc, Instructions))
Toma Tabacud88d79c2015-06-23 14:39:42 +00002931 return true;
2932
2933 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
2934 // because it will make our output more similar to GAS'. For example,
2935 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
2936 // instead of just an "ori $1, $9, 32768".
2937 // NOTE: If there is no source register specified in the ULHU, the parser
2938 // will interpret it as $0.
2939 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
2940 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
2941 }
2942
2943 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
2944 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
2945 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
2946
2947 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
2948 if (isLittle()) {
2949 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
2950 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
2951 } else {
2952 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
2953 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
2954 }
2955
2956 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
2957
2958 MCInst TmpInst;
2959 TmpInst.setOpcode(Mips::LBu);
2960 TmpInst.addOperand(MCOperand::createReg(FirstLbuDstReg));
2961 TmpInst.addOperand(MCOperand::createReg(LbuSrcReg));
2962 TmpInst.addOperand(MCOperand::createImm(FirstLbuOffset));
2963 Instructions.push_back(TmpInst);
2964
2965 TmpInst.clear();
2966 TmpInst.setOpcode(Mips::LBu);
2967 TmpInst.addOperand(MCOperand::createReg(SecondLbuDstReg));
2968 TmpInst.addOperand(MCOperand::createReg(LbuSrcReg));
2969 TmpInst.addOperand(MCOperand::createImm(SecondLbuOffset));
2970 Instructions.push_back(TmpInst);
2971
2972 TmpInst.clear();
2973 TmpInst.setOpcode(Mips::SLL);
2974 TmpInst.addOperand(MCOperand::createReg(SllReg));
2975 TmpInst.addOperand(MCOperand::createReg(SllReg));
2976 TmpInst.addOperand(MCOperand::createImm(8));
2977 Instructions.push_back(TmpInst);
2978
2979 TmpInst.clear();
2980 TmpInst.setOpcode(Mips::OR);
2981 TmpInst.addOperand(MCOperand::createReg(DstReg));
2982 TmpInst.addOperand(MCOperand::createReg(DstReg));
2983 TmpInst.addOperand(MCOperand::createReg(ATReg));
2984 Instructions.push_back(TmpInst);
2985
2986 return false;
2987}
2988
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00002989bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
2990 SmallVectorImpl<MCInst> &Instructions) {
2991 if (hasMips32r6() || hasMips64r6()) {
2992 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2993 return false;
2994 }
2995
2996 const MCOperand &DstRegOp = Inst.getOperand(0);
2997 assert(DstRegOp.isReg() && "expected register operand kind");
2998
2999 const MCOperand &SrcRegOp = Inst.getOperand(1);
3000 assert(SrcRegOp.isReg() && "expected register operand kind");
3001
3002 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3003 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3004
3005 unsigned SrcReg = SrcRegOp.getReg();
3006 int64_t OffsetValue = OffsetImmOp.getImm();
3007 unsigned ATReg = 0;
3008
3009 // When the value of offset+3 does not fit in 16 bits, we have to load the
3010 // offset in AT, (D)ADDu the original source register (if there was one), and
3011 // then use AT as the source register for the generated LWL and LWR.
3012 bool LoadedOffsetInAT = false;
3013 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3014 ATReg = getATReg(IDLoc);
3015 if (!ATReg)
3016 return true;
3017 LoadedOffsetInAT = true;
3018
3019 warnIfNoMacro(IDLoc);
3020
3021 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003022 true, IDLoc, Instructions))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003023 return true;
3024
3025 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3026 // because it will make our output more similar to GAS'. For example,
3027 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3028 // instead of just an "ori $1, $9, 32768".
3029 // NOTE: If there is no source register specified in the ULW, the parser
3030 // will interpret it as $0.
3031 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3032 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3033 }
3034
3035 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3036 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3037 if (isLittle()) {
3038 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3039 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3040 } else {
3041 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3042 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3043 }
3044
3045 MCInst LeftLoadInst;
3046 LeftLoadInst.setOpcode(Mips::LWL);
3047 LeftLoadInst.addOperand(DstRegOp);
3048 LeftLoadInst.addOperand(MCOperand::createReg(FinalSrcReg));
3049 LeftLoadInst.addOperand(MCOperand::createImm(LeftLoadOffset));
3050 Instructions.push_back(LeftLoadInst);
3051
3052 MCInst RightLoadInst;
3053 RightLoadInst.setOpcode(Mips::LWR);
3054 RightLoadInst.addOperand(DstRegOp);
3055 RightLoadInst.addOperand(MCOperand::createReg(FinalSrcReg));
3056 RightLoadInst.addOperand(MCOperand::createImm(RightLoadOffset ));
3057 Instructions.push_back(RightLoadInst);
3058
3059 return false;
3060}
3061
Toma Tabacu234482a2015-03-16 12:03:39 +00003062void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
3063 SmallVectorImpl<MCInst> &Instructions) {
3064 MCInst NopInst;
3065 if (hasShortDelaySlot) {
3066 NopInst.setOpcode(Mips::MOVE16_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003067 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
3068 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
Toma Tabacu234482a2015-03-16 12:03:39 +00003069 } else {
3070 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00003071 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
3072 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
3073 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu234482a2015-03-16 12:03:39 +00003074 }
3075 Instructions.push_back(NopInst);
3076}
3077
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003078void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +00003079 unsigned TrgReg, bool Is64Bit,
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003080 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders03f9c012015-07-14 12:24:22 +00003081 emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
3082 Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003083}
3084
Matheus Almeida595fcab2014-06-11 15:05:56 +00003085unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3086 // As described by the Mips32r2 spec, the registers Rd and Rs for
3087 // jalr.hb must be different.
3088 unsigned Opcode = Inst.getOpcode();
3089
3090 if (Opcode == Mips::JALR_HB &&
3091 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3092 return Match_RequiresDifferentSrcAndDst;
3093
3094 return Match_Success;
3095}
3096
David Blaikie960ea3f2014-06-08 16:18:35 +00003097bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3098 OperandVector &Operands,
3099 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003100 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003101 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003102
Jack Carterb4dbc172012-09-05 23:34:03 +00003103 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00003104 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00003105 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003106 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003107
3108 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003109 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003110 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00003111 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00003112 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00003113 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00003114 return false;
3115 }
3116 case Match_MissingFeature:
3117 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3118 return true;
3119 case Match_InvalidOperand: {
3120 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003121 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003122 if (ErrorInfo >= Operands.size())
3123 return Error(IDLoc, "too few operands for instruction");
3124
David Blaikie960ea3f2014-06-08 16:18:35 +00003125 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003126 if (ErrorLoc == SMLoc())
3127 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003128 }
3129
3130 return Error(ErrorLoc, "invalid operand for instruction");
3131 }
3132 case Match_MnemonicFail:
3133 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003134 case Match_RequiresDifferentSrcAndDst:
3135 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00003136 }
Craig Topper589ceee2015-01-03 08:16:34 +00003137
3138 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003139}
3140
Toma Tabacud9d344b2015-04-27 14:05:04 +00003141void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3142 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3143 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3144 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003145}
3146
Toma Tabacu81496c12015-05-20 08:54:45 +00003147void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3148 if (!AssemblerOptions.back()->isMacro())
3149 Warning(Loc, "macro instruction expanded into multiple instructions");
3150}
3151
Daniel Sandersef638fe2014-10-03 15:37:37 +00003152void
3153MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3154 SMRange Range, bool ShowColors) {
3155 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003156 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003157 ShowColors);
3158}
3159
Jack Carter1ac53222013-02-20 23:11:17 +00003160int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003161 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003162
Vladimir Medic4c299852013-11-06 11:27:05 +00003163 CC = StringSwitch<unsigned>(Name)
3164 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003165 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003166 .Case("a0", 4)
3167 .Case("a1", 5)
3168 .Case("a2", 6)
3169 .Case("a3", 7)
3170 .Case("v0", 2)
3171 .Case("v1", 3)
3172 .Case("s0", 16)
3173 .Case("s1", 17)
3174 .Case("s2", 18)
3175 .Case("s3", 19)
3176 .Case("s4", 20)
3177 .Case("s5", 21)
3178 .Case("s6", 22)
3179 .Case("s7", 23)
3180 .Case("k0", 26)
3181 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003182 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003183 .Case("sp", 29)
3184 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003185 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003186 .Case("ra", 31)
3187 .Case("t0", 8)
3188 .Case("t1", 9)
3189 .Case("t2", 10)
3190 .Case("t3", 11)
3191 .Case("t4", 12)
3192 .Case("t5", 13)
3193 .Case("t6", 14)
3194 .Case("t7", 15)
3195 .Case("t8", 24)
3196 .Case("t9", 25)
3197 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003198
Toma Tabacufda445c2014-09-15 15:33:01 +00003199 if (!(isABI_N32() || isABI_N64()))
3200 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003201
Daniel Sandersef638fe2014-10-03 15:37:37 +00003202 if (12 <= CC && CC <= 15) {
3203 // Name is one of t4-t7
3204 AsmToken RegTok = getLexer().peekTok();
3205 SMRange RegRange = RegTok.getLocRange();
3206
3207 StringRef FixedName = StringSwitch<StringRef>(Name)
3208 .Case("t4", "t0")
3209 .Case("t5", "t1")
3210 .Case("t6", "t2")
3211 .Case("t7", "t3")
3212 .Default("");
3213 assert(FixedName != "" && "Register name is not one of t4-t7.");
3214
3215 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3216 "Did you mean $" + FixedName + "?", RegRange);
3217 }
3218
Toma Tabacufda445c2014-09-15 15:33:01 +00003219 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3220 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3221 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3222 if (8 <= CC && CC <= 11)
3223 CC += 4;
3224
3225 if (CC == -1)
3226 CC = StringSwitch<unsigned>(Name)
3227 .Case("a4", 8)
3228 .Case("a5", 9)
3229 .Case("a6", 10)
3230 .Case("a7", 11)
3231 .Case("kt0", 26)
3232 .Case("kt1", 27)
3233 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003234
3235 return CC;
3236}
Jack Carterd0bd6422013-04-18 00:41:53 +00003237
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003238int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3239 int CC;
3240
3241 CC = StringSwitch<unsigned>(Name)
3242 .Case("hwr_cpunum", 0)
3243 .Case("hwr_synci_step", 1)
3244 .Case("hwr_cc", 2)
3245 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003246 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003247 .Default(-1);
3248
3249 return CC;
3250}
3251
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003252int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003253
Jack Cartera63b16a2012-09-07 00:23:42 +00003254 if (Name[0] == 'f') {
3255 StringRef NumString = Name.substr(1);
3256 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003257 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003258 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003259 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003260 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003261 return IntVal;
3262 }
3263 return -1;
3264}
Jack Cartera63b16a2012-09-07 00:23:42 +00003265
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003266int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3267
3268 if (Name.startswith("fcc")) {
3269 StringRef NumString = Name.substr(3);
3270 unsigned IntVal;
3271 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003272 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003273 if (IntVal > 7) // There are only 8 fcc registers.
3274 return -1;
3275 return IntVal;
3276 }
3277 return -1;
3278}
3279
3280int MipsAsmParser::matchACRegisterName(StringRef Name) {
3281
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003282 if (Name.startswith("ac")) {
3283 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003284 unsigned IntVal;
3285 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003286 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003287 if (IntVal > 3) // There are only 3 acc registers.
3288 return -1;
3289 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003290 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003291 return -1;
3292}
Jack Carterd0bd6422013-04-18 00:41:53 +00003293
Jack Carter5dc8ac92013-09-25 23:50:44 +00003294int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3295 unsigned IntVal;
3296
3297 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3298 return -1;
3299
3300 if (IntVal > 31)
3301 return -1;
3302
3303 return IntVal;
3304}
3305
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003306int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3307 int CC;
3308
3309 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003310 .Case("msair", 0)
3311 .Case("msacsr", 1)
3312 .Case("msaaccess", 2)
3313 .Case("msasave", 3)
3314 .Case("msamodify", 4)
3315 .Case("msarequest", 5)
3316 .Case("msamap", 6)
3317 .Case("msaunmap", 7)
3318 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003319
3320 return CC;
3321}
3322
Toma Tabacu89a712b2015-04-15 10:48:56 +00003323unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00003324 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00003325 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00003326 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00003327 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00003328 return 0;
3329 }
3330 unsigned AT = getReg(
3331 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00003332 return AT;
3333}
Jack Carter0b744b32012-10-04 02:29:46 +00003334
Jack Carterd0bd6422013-04-18 00:41:53 +00003335unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00003336 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00003337}
3338
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003339unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003340 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00003341 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003342}
3343
Jack Carter873c7242013-01-12 01:03:14 +00003344int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003345 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00003346 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00003347 return -1;
3348
Jack Carter873c7242013-01-12 01:03:14 +00003349 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00003350}
3351
Toma Tabacu13964452014-09-04 13:23:44 +00003352bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003353 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003354 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003355
Jack Carter30a59822012-10-04 04:03:53 +00003356 // Check if the current operand has a custom associated parser, if so, try to
3357 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00003358 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3359 if (ResTy == MatchOperand_Success)
3360 return false;
3361 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3362 // there was a match, but an error occurred, in which case, just return that
3363 // the operand parsing failed.
3364 if (ResTy == MatchOperand_ParseFail)
3365 return true;
3366
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003367 DEBUG(dbgs() << ".. Generic Parser\n");
3368
Jack Carterb4dbc172012-09-05 23:34:03 +00003369 switch (getLexer().getKind()) {
3370 default:
3371 Error(Parser.getTok().getLoc(), "unexpected token in operand");
3372 return true;
3373 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003374 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00003375 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00003376
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003377 // Almost all registers have been parsed by custom parsers. There is only
3378 // one exception to this. $zero (and it's alias $0) will reach this point
3379 // for div, divu, and similar instructions because it is not an operand
3380 // to the instruction definition but an explicit register. Special case
3381 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00003382 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00003383 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003384
Jack Carterd0bd6422013-04-18 00:41:53 +00003385 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00003386 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003387 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00003388 return true;
3389
Jack Carter873c7242013-01-12 01:03:14 +00003390 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00003391 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00003392 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00003393 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003394 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00003395
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003396 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003397 return false;
3398 }
Vladimir Medic4c299852013-11-06 11:27:05 +00003399 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00003400 case AsmToken::LParen:
3401 case AsmToken::Minus:
3402 case AsmToken::Plus:
3403 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003404 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00003405 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003406 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003407 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003408 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00003409 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00003410 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003411 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003412 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003413 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00003414 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00003415 return true;
3416
Jack Carter873c7242013-01-12 01:03:14 +00003417 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3418
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003419 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00003420 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003421 } // case AsmToken::Percent
3422 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00003423 return true;
3424}
3425
Vladimir Medic4c299852013-11-06 11:27:05 +00003426const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00003427 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003428 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00003429 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003430 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00003431 // It's a constant, evaluate reloc value.
3432 int16_t Val;
3433 switch (getVariantKind(RelocStr)) {
3434 case MCSymbolRefExpr::VK_Mips_ABS_LO:
3435 // Get the 1st 16-bits.
3436 Val = MCE->getValue() & 0xffff;
3437 break;
3438 case MCSymbolRefExpr::VK_Mips_ABS_HI:
3439 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
3440 // 16 bits being negative.
3441 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
3442 break;
3443 case MCSymbolRefExpr::VK_Mips_HIGHER:
3444 // Get the 3rd 16-bits.
3445 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
3446 break;
3447 case MCSymbolRefExpr::VK_Mips_HIGHEST:
3448 // Get the 4th 16-bits.
3449 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
3450 break;
3451 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00003452 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00003453 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00003454 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003455 }
3456
Jack Carterb5cf5902013-04-17 00:18:04 +00003457 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003458 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00003459 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00003460 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003461 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003462 return Res;
3463 }
3464
3465 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00003466 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
3467
Sasa Stankovic06c47802014-04-03 10:37:45 +00003468 // Try to create target expression.
3469 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00003470 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003471
Jack Carterd0bd6422013-04-18 00:41:53 +00003472 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
3473 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003474 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003475 return Res;
3476 }
3477
3478 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003479 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003480 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00003481 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00003482 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003483 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003484 return Expr;
3485}
3486
3487bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
3488
3489 switch (Expr->getKind()) {
3490 case MCExpr::Constant:
3491 return true;
3492 case MCExpr::SymbolRef:
3493 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
3494 case MCExpr::Binary:
3495 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
3496 if (!isEvaluated(BE->getLHS()))
3497 return false;
3498 return isEvaluated(BE->getRHS());
3499 }
3500 case MCExpr::Unary:
3501 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003502 case MCExpr::Target:
3503 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003504 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003505 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00003506}
Jack Carterd0bd6422013-04-18 00:41:53 +00003507
Jack Carterb5cf5902013-04-17 00:18:04 +00003508bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003509 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003510 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00003511 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00003512 if (Tok.isNot(AsmToken::Identifier))
3513 return true;
3514
Yaron Keren075759a2015-03-30 15:42:36 +00003515 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00003516
Jack Carterd0bd6422013-04-18 00:41:53 +00003517 Parser.Lex(); // Eat the identifier.
3518 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003519 const MCExpr *IdVal;
3520 SMLoc EndLoc;
3521
3522 if (getLexer().getKind() == AsmToken::LParen) {
3523 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003524 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003525 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003526 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003527 const AsmToken &nextTok = Parser.getTok();
3528 if (nextTok.isNot(AsmToken::Identifier))
3529 return true;
3530 Str += "(%";
3531 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00003532 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00003533 if (getLexer().getKind() != AsmToken::LParen)
3534 return true;
3535 } else
3536 break;
3537 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003538 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00003539 return true;
3540
3541 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00003542 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003543
3544 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00003545 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003546
Jack Carterd0bd6422013-04-18 00:41:53 +00003547 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00003548 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003549}
3550
Jack Carterb4dbc172012-09-05 23:34:03 +00003551bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
3552 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003553 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00003554 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003555 if (ResTy == MatchOperand_Success) {
3556 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00003557 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003558 StartLoc = Operand.getStartLoc();
3559 EndLoc = Operand.getEndLoc();
3560
3561 // AFAIK, we only support numeric registers and named GPR's in CFI
3562 // directives.
3563 // Don't worry about eating tokens before failing. Using an unrecognised
3564 // register is a parse error.
3565 if (Operand.isGPRAsmReg()) {
3566 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003567 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003568 }
3569
3570 return (RegNo == (unsigned)-1);
3571 }
3572
3573 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00003574 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00003575}
3576
Jack Carterb5cf5902013-04-17 00:18:04 +00003577bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003578 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00003579 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003580 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003581 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00003582
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003583 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003584 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003585 ++NumOfLParen;
3586 }
Jack Carter873c7242013-01-12 01:03:14 +00003587
Jack Carterd0bd6422013-04-18 00:41:53 +00003588 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003589 default:
3590 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00003591 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00003592 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00003593 case AsmToken::Integer:
3594 case AsmToken::Minus:
3595 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00003596 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003597 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00003598 else
3599 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00003600 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00003601 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003602 break;
Jack Carter873c7242013-01-12 01:03:14 +00003603 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00003604 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003605 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003606 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003607}
3608
David Blaikie960ea3f2014-06-08 16:18:35 +00003609MipsAsmParser::OperandMatchResultTy
3610MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003611 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003612 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00003613 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00003614 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003615 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003616 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00003617 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00003618 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00003619
Jack Carterb5cf5902013-04-17 00:18:04 +00003620 if (getLexer().getKind() == AsmToken::LParen) {
3621 Parser.Lex();
3622 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003623 }
3624
Jack Carterb5cf5902013-04-17 00:18:04 +00003625 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003626 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00003627 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003628
Jack Carterd0bd6422013-04-18 00:41:53 +00003629 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003630 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003631 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003632 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003633 SMLoc E =
3634 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003635 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003636 return MatchOperand_Success;
3637 }
3638 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003639 SMLoc E =
3640 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00003641
Jack Carterd0bd6422013-04-18 00:41:53 +00003642 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003643 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00003644 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003645 S, E, *this);
3646 Operands.push_back(
3647 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003648 return MatchOperand_Success;
3649 }
3650 Error(Parser.getTok().getLoc(), "'(' expected");
3651 return MatchOperand_ParseFail;
3652 }
3653
Jack Carterd0bd6422013-04-18 00:41:53 +00003654 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003655 }
3656
Toma Tabacu13964452014-09-04 13:23:44 +00003657 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003658 if (Res != MatchOperand_Success)
3659 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003660
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003661 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003662 Error(Parser.getTok().getLoc(), "')' expected");
3663 return MatchOperand_ParseFail;
3664 }
3665
Jack Carter873c7242013-01-12 01:03:14 +00003666 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3667
Jack Carterd0bd6422013-04-18 00:41:53 +00003668 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003669
Craig Topper062a2ba2014-04-25 05:30:21 +00003670 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003671 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003672
Jack Carterd0bd6422013-04-18 00:41:53 +00003673 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00003674 std::unique_ptr<MipsOperand> op(
3675 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00003676 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003677 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003678 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00003679 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003680 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
3681 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003682 if (IdVal->evaluateAsAbsolute(Imm))
3683 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003684 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003685 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00003686 getContext());
3687 }
3688
David Blaikie960ea3f2014-06-08 16:18:35 +00003689 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003690 return MatchOperand_Success;
3691}
3692
David Blaikie960ea3f2014-06-08 16:18:35 +00003693bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003694 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00003695 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00003696 if (Sym) {
3697 SMLoc S = Parser.getTok().getLoc();
3698 const MCExpr *Expr;
3699 if (Sym->isVariable())
3700 Expr = Sym->getVariableValue();
3701 else
3702 return false;
3703 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003704 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00003705 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00003706 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003707 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003708 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00003709 if (ResTy == MatchOperand_Success) {
3710 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00003711 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00003712 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003713 llvm_unreachable("Should never ParseFail");
3714 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00003715 }
3716 } else if (Expr->getKind() == MCExpr::Constant) {
3717 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00003718 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00003719 Operands.push_back(
3720 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00003721 return true;
3722 }
3723 }
3724 return false;
3725}
Jack Carterd0bd6422013-04-18 00:41:53 +00003726
Jack Carter873c7242013-01-12 01:03:14 +00003727MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003728MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00003729 StringRef Identifier,
3730 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003731 int Index = matchCPURegisterName(Identifier);
3732 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003733 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003734 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3735 return MatchOperand_Success;
3736 }
3737
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003738 Index = matchHWRegsRegisterName(Identifier);
3739 if (Index != -1) {
3740 Operands.push_back(MipsOperand::createHWRegsReg(
3741 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3742 return MatchOperand_Success;
3743 }
3744
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003745 Index = matchFPURegisterName(Identifier);
3746 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003747 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003748 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3749 return MatchOperand_Success;
3750 }
3751
3752 Index = matchFCCRegisterName(Identifier);
3753 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003754 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003755 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3756 return MatchOperand_Success;
3757 }
3758
3759 Index = matchACRegisterName(Identifier);
3760 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003761 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003762 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3763 return MatchOperand_Success;
3764 }
3765
3766 Index = matchMSA128RegisterName(Identifier);
3767 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003768 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003769 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3770 return MatchOperand_Success;
3771 }
3772
3773 Index = matchMSA128CtrlRegisterName(Identifier);
3774 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003775 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003776 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3777 return MatchOperand_Success;
3778 }
3779
3780 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00003781}
3782
3783MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003784MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003785 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00003786 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003787
3788 if (Token.is(AsmToken::Identifier)) {
3789 DEBUG(dbgs() << ".. identifier\n");
3790 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00003791 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003792 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00003793 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003794 } else if (Token.is(AsmToken::Integer)) {
3795 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003796 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003797 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
3798 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003799 return MatchOperand_Success;
3800 }
3801
3802 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
3803
3804 return MatchOperand_NoMatch;
3805}
3806
David Blaikie960ea3f2014-06-08 16:18:35 +00003807MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003808MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003809 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003810 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003811
3812 auto Token = Parser.getTok();
3813
3814 SMLoc S = Token.getLoc();
3815
3816 if (Token.isNot(AsmToken::Dollar)) {
3817 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
3818 if (Token.is(AsmToken::Identifier)) {
3819 if (searchSymbolAlias(Operands))
3820 return MatchOperand_Success;
3821 }
3822 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
3823 return MatchOperand_NoMatch;
3824 }
3825 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003826
Toma Tabacu13964452014-09-04 13:23:44 +00003827 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00003828 if (ResTy == MatchOperand_Success) {
3829 Parser.Lex(); // $
3830 Parser.Lex(); // identifier
3831 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003832 return ResTy;
3833}
3834
3835MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003836MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003837 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003838 switch (getLexer().getKind()) {
3839 default:
3840 return MatchOperand_NoMatch;
3841 case AsmToken::LParen:
3842 case AsmToken::Minus:
3843 case AsmToken::Plus:
3844 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003845 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003846 case AsmToken::String:
3847 break;
3848 }
3849
3850 const MCExpr *IdVal;
3851 SMLoc S = Parser.getTok().getLoc();
3852 if (getParser().parseExpression(IdVal))
3853 return MatchOperand_ParseFail;
3854
3855 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3856 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
3857 return MatchOperand_Success;
3858}
3859
David Blaikie960ea3f2014-06-08 16:18:35 +00003860MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003861MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003862 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003863 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003864
3865 SMLoc S = getLexer().getLoc();
3866
3867 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00003868 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003869 if (ResTy != MatchOperand_NoMatch)
3870 return ResTy;
3871
Daniel Sanders315386c2014-04-01 10:40:14 +00003872 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00003873 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00003874 if (ResTy != MatchOperand_NoMatch)
3875 return ResTy;
3876
Daniel Sandersffd84362014-04-01 10:41:48 +00003877 const MCExpr *Expr = nullptr;
3878 if (Parser.parseExpression(Expr)) {
3879 // We have no way of knowing if a symbol was consumed so we must ParseFail
3880 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003881 }
Daniel Sandersffd84362014-04-01 10:41:48 +00003882 Operands.push_back(
3883 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003884 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00003885}
3886
Vladimir Medic2b953d02013-10-01 09:48:56 +00003887MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00003888MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003889 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00003890 const MCExpr *IdVal;
3891 // If the first token is '$' we may have register operand.
3892 if (Parser.getTok().is(AsmToken::Dollar))
3893 return MatchOperand_NoMatch;
3894 SMLoc S = Parser.getTok().getLoc();
3895 if (getParser().parseExpression(IdVal))
3896 return MatchOperand_ParseFail;
3897 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00003898 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00003899 int64_t Val = MCE->getValue();
3900 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3901 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003902 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00003903 return MatchOperand_Success;
3904}
3905
Matheus Almeida779c5932013-11-18 12:32:49 +00003906MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003907MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003908 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00003909 switch (getLexer().getKind()) {
3910 default:
3911 return MatchOperand_NoMatch;
3912 case AsmToken::LParen:
3913 case AsmToken::Plus:
3914 case AsmToken::Minus:
3915 case AsmToken::Integer:
3916 break;
3917 }
3918
3919 const MCExpr *Expr;
3920 SMLoc S = Parser.getTok().getLoc();
3921
3922 if (getParser().parseExpression(Expr))
3923 return MatchOperand_ParseFail;
3924
3925 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003926 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00003927 Error(S, "expected immediate value");
3928 return MatchOperand_ParseFail;
3929 }
3930
3931 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
3932 // and because the CPU always adds one to the immediate field, the allowed
3933 // range becomes 1..4. We'll only check the range here and will deal
3934 // with the addition/subtraction when actually decoding/encoding
3935 // the instruction.
3936 if (Val < 1 || Val > 4) {
3937 Error(S, "immediate not in range (1..4)");
3938 return MatchOperand_ParseFail;
3939 }
3940
Jack Carter3b2c96e2014-01-22 23:31:38 +00003941 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003942 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00003943 return MatchOperand_Success;
3944}
3945
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00003946MipsAsmParser::OperandMatchResultTy
3947MipsAsmParser::parseRegisterList(OperandVector &Operands) {
3948 MCAsmParser &Parser = getParser();
3949 SmallVector<unsigned, 10> Regs;
3950 unsigned RegNo;
3951 unsigned PrevReg = Mips::NoRegister;
3952 bool RegRange = false;
3953 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3954
3955 if (Parser.getTok().isNot(AsmToken::Dollar))
3956 return MatchOperand_ParseFail;
3957
3958 SMLoc S = Parser.getTok().getLoc();
3959 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
3960 SMLoc E = getLexer().getLoc();
3961 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
3962 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
3963 if (RegRange) {
3964 // Remove last register operand because registers from register range
3965 // should be inserted first.
3966 if (RegNo == Mips::RA) {
3967 Regs.push_back(RegNo);
3968 } else {
3969 unsigned TmpReg = PrevReg + 1;
3970 while (TmpReg <= RegNo) {
3971 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
3972 Error(E, "invalid register operand");
3973 return MatchOperand_ParseFail;
3974 }
3975
3976 PrevReg = TmpReg;
3977 Regs.push_back(TmpReg++);
3978 }
3979 }
3980
3981 RegRange = false;
3982 } else {
3983 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
3984 (RegNo != Mips::RA)) {
3985 Error(E, "$16 or $31 expected");
3986 return MatchOperand_ParseFail;
3987 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
3988 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3989 Error(E, "invalid register operand");
3990 return MatchOperand_ParseFail;
3991 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
3992 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3993 Error(E, "consecutive register numbers expected");
3994 return MatchOperand_ParseFail;
3995 }
3996
3997 Regs.push_back(RegNo);
3998 }
3999
4000 if (Parser.getTok().is(AsmToken::Minus))
4001 RegRange = true;
4002
4003 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4004 !Parser.getTok().isNot(AsmToken::Comma)) {
4005 Error(E, "',' or '-' expected");
4006 return MatchOperand_ParseFail;
4007 }
4008
4009 Lex(); // Consume comma or minus
4010 if (Parser.getTok().isNot(AsmToken::Dollar))
4011 break;
4012
4013 PrevReg = RegNo;
4014 }
4015
4016 SMLoc E = Parser.getTok().getLoc();
4017 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4018 parseMemOperand(Operands);
4019 return MatchOperand_Success;
4020}
4021
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004022MipsAsmParser::OperandMatchResultTy
4023MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4024 MCAsmParser &Parser = getParser();
4025
4026 SMLoc S = Parser.getTok().getLoc();
4027 if (parseAnyRegister(Operands) != MatchOperand_Success)
4028 return MatchOperand_ParseFail;
4029
4030 SMLoc E = Parser.getTok().getLoc();
4031 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
4032 unsigned Reg = Op.getGPR32Reg();
4033 Operands.pop_back();
4034 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
4035 return MatchOperand_Success;
4036}
4037
Zoran Jovanovic41688672015-02-10 16:36:20 +00004038MipsAsmParser::OperandMatchResultTy
4039MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4040 MCAsmParser &Parser = getParser();
4041 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4042 SmallVector<unsigned, 10> Regs;
4043
4044 if (Parser.getTok().isNot(AsmToken::Dollar))
4045 return MatchOperand_ParseFail;
4046
4047 SMLoc S = Parser.getTok().getLoc();
4048
4049 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4050 return MatchOperand_ParseFail;
4051
4052 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4053 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4054 Regs.push_back(RegNo);
4055
4056 SMLoc E = Parser.getTok().getLoc();
4057 if (Parser.getTok().isNot(AsmToken::Comma)) {
4058 Error(E, "',' expected");
4059 return MatchOperand_ParseFail;
4060 }
4061
4062 // Remove comma.
4063 Parser.Lex();
4064
4065 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4066 return MatchOperand_ParseFail;
4067
4068 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4069 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4070 Regs.push_back(RegNo);
4071
4072 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4073
4074 return MatchOperand_Success;
4075}
4076
Jack Carterdc1e35d2012-09-06 20:00:02 +00004077MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
4078
Vladimir Medic4c299852013-11-06 11:27:05 +00004079 MCSymbolRefExpr::VariantKind VK =
4080 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
4081 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
4082 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
4083 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
4084 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
4085 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
4086 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
4087 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
4088 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
4089 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
4090 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
4091 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
4092 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
4093 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
4094 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
4095 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
4096 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
4097 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00004098 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
4099 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
4100 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
4101 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
4102 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
4103 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00004104 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
4105 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00004106 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004107
Matheus Almeida2852af82014-04-22 10:15:54 +00004108 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00004109
Jack Carterdc1e35d2012-09-06 20:00:02 +00004110 return VK;
4111}
Jack Cartera63b16a2012-09-07 00:23:42 +00004112
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004113/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4114/// either this.
4115/// ::= '(', register, ')'
4116/// handle it before we iterate so we don't get tripped up by the lack of
4117/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004118bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004119 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004120 if (getLexer().is(AsmToken::LParen)) {
4121 Operands.push_back(
4122 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4123 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004124 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004125 SMLoc Loc = getLexer().getLoc();
4126 Parser.eatToEndOfStatement();
4127 return Error(Loc, "unexpected token in argument list");
4128 }
4129 if (Parser.getTok().isNot(AsmToken::RParen)) {
4130 SMLoc Loc = getLexer().getLoc();
4131 Parser.eatToEndOfStatement();
4132 return Error(Loc, "unexpected token, expected ')'");
4133 }
4134 Operands.push_back(
4135 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4136 Parser.Lex();
4137 }
4138 return false;
4139}
4140
4141/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4142/// either one of these.
4143/// ::= '[', register, ']'
4144/// ::= '[', integer, ']'
4145/// handle it before we iterate so we don't get tripped up by the lack of
4146/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004147bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004148 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004149 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004150 if (getLexer().is(AsmToken::LBrac)) {
4151 Operands.push_back(
4152 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4153 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004154 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004155 SMLoc Loc = getLexer().getLoc();
4156 Parser.eatToEndOfStatement();
4157 return Error(Loc, "unexpected token in argument list");
4158 }
4159 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4160 SMLoc Loc = getLexer().getLoc();
4161 Parser.eatToEndOfStatement();
4162 return Error(Loc, "unexpected token, expected ']'");
4163 }
4164 Operands.push_back(
4165 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4166 Parser.Lex();
4167 }
4168 return false;
4169}
4170
David Blaikie960ea3f2014-06-08 16:18:35 +00004171bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4172 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004173 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004174 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004175
4176 // We have reached first instruction, module directive are now forbidden.
4177 getTargetStreamer().forbidModuleDirective();
4178
Vladimir Medic74593e62013-07-17 15:00:42 +00004179 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004180 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004181 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004182 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004183 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004184 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004185 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004186
4187 // Read the remaining operands.
4188 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4189 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004190 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004191 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004192 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004193 return Error(Loc, "unexpected token in argument list");
4194 }
Toma Tabacu13964452014-09-04 13:23:44 +00004195 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004196 return true;
4197 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004198
Jack Carterd0bd6422013-04-18 00:41:53 +00004199 while (getLexer().is(AsmToken::Comma)) {
4200 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004201 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004202 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004203 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004204 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004205 return Error(Loc, "unexpected token in argument list");
4206 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004207 // Parse bracket and parenthesis suffixes before we iterate
4208 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004209 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004210 return true;
4211 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004212 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004213 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004214 }
4215 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004216 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4217 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004218 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004219 return Error(Loc, "unexpected token in argument list");
4220 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004221 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004222 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004223}
4224
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004225bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004226 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004227 SMLoc Loc = getLexer().getLoc();
4228 Parser.eatToEndOfStatement();
4229 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004230}
4231
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004232bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004233 return Error(Loc, ErrorMsg);
4234}
4235
Jack Carter0b744b32012-10-04 02:29:46 +00004236bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004237 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004238 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004239
4240 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004241 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004242
4243 Parser.Lex(); // Eat "noat".
4244
Jack Carterd0bd6422013-04-18 00:41:53 +00004245 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004246 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004247 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004248 return false;
4249 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004250
4251 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004252 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004253 return false;
4254}
Jack Carterd0bd6422013-04-18 00:41:53 +00004255
Jack Carter0b744b32012-10-04 02:29:46 +00004256bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004257 // Line can be: ".set at", which sets $at to $1
4258 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004259 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004260 Parser.Lex(); // Eat "at".
4261
Jack Carter0b744b32012-10-04 02:29:46 +00004262 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004263 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004264 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004265
4266 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004267 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004268 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004269 }
4270
4271 if (getLexer().isNot(AsmToken::Equal)) {
4272 reportParseError("unexpected token, expected equals sign");
4273 return false;
4274 }
4275 Parser.Lex(); // Eat "=".
4276
4277 if (getLexer().isNot(AsmToken::Dollar)) {
4278 if (getLexer().is(AsmToken::EndOfStatement)) {
4279 reportParseError("no register specified");
4280 return false;
4281 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004282 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004283 return false;
4284 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004285 }
4286 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004287
Toma Tabacu16a74492015-02-13 10:30:57 +00004288 // Find out what "reg" is.
4289 unsigned AtRegNo;
4290 const AsmToken &Reg = Parser.getTok();
4291 if (Reg.is(AsmToken::Identifier)) {
4292 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4293 } else if (Reg.is(AsmToken::Integer)) {
4294 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004295 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004296 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004297 return false;
4298 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004299
4300 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004301 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004302 reportParseError("invalid register");
4303 return false;
4304 }
4305 Parser.Lex(); // Eat "reg".
4306
4307 // If this is not the end of the statement, report an error.
4308 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4309 reportParseError("unexpected token, expected end of statement");
4310 return false;
4311 }
4312
4313 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4314
4315 Parser.Lex(); // Consume the EndOfStatement.
4316 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004317}
4318
4319bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004320 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004321 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004322 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004323 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004324 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004325 return false;
4326 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004327 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004328 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004329 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004330 return false;
4331}
4332
4333bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004334 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004335 Parser.Lex();
4336 // If this is not the end of the statement, report an error.
4337 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004338 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004339 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00004340 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004341 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00004342 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004343 Parser.Lex(); // Consume the EndOfStatement.
4344 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004345}
4346
4347bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004348 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004349 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004350 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004351 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004352 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004353 return false;
4354 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004355 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004356 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004357 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004358 return false;
4359}
4360
4361bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004362 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004363 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004364 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004365 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004366 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004367 return false;
4368 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004369 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00004370 reportParseError("`noreorder' must be set before `nomacro'");
4371 return false;
4372 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004373 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004374 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004375 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004376 return false;
4377}
Jack Carterd76b2372013-03-21 21:44:16 +00004378
Daniel Sanders44934432014-08-07 12:03:36 +00004379bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004380 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004381 Parser.Lex();
4382
4383 // If this is not the end of the statement, report an error.
4384 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004385 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004386
4387 setFeatureBits(Mips::FeatureMSA, "msa");
4388 getTargetStreamer().emitDirectiveSetMsa();
4389 return false;
4390}
4391
4392bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004393 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004394 Parser.Lex();
4395
4396 // If this is not the end of the statement, report an error.
4397 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004398 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004399
4400 clearFeatureBits(Mips::FeatureMSA, "msa");
4401 getTargetStreamer().emitDirectiveSetNoMsa();
4402 return false;
4403}
4404
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004405bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004406 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004407 Parser.Lex(); // Eat "nodsp".
4408
4409 // If this is not the end of the statement, report an error.
4410 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4411 reportParseError("unexpected token, expected end of statement");
4412 return false;
4413 }
4414
4415 clearFeatureBits(Mips::FeatureDSP, "dsp");
4416 getTargetStreamer().emitDirectiveSetNoDsp();
4417 return false;
4418}
4419
Toma Tabacucc2502d2014-11-04 17:18:07 +00004420bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004421 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004422 Parser.Lex(); // Eat "mips16".
4423
Jack Carter39536722014-01-22 23:08:42 +00004424 // If this is not the end of the statement, report an error.
4425 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004426 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00004427 return false;
4428 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00004429
4430 setFeatureBits(Mips::FeatureMips16, "mips16");
4431 getTargetStreamer().emitDirectiveSetMips16();
4432 Parser.Lex(); // Consume the EndOfStatement.
4433 return false;
4434}
4435
4436bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004437 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004438 Parser.Lex(); // Eat "nomips16".
4439
4440 // If this is not the end of the statement, report an error.
4441 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4442 reportParseError("unexpected token, expected end of statement");
4443 return false;
4444 }
4445
4446 clearFeatureBits(Mips::FeatureMips16, "mips16");
4447 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00004448 Parser.Lex(); // Consume the EndOfStatement.
4449 return false;
4450}
4451
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004452bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004453 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004454 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004455 // Line can be: .set fp=32
4456 // .set fp=xx
4457 // .set fp=64
4458 Parser.Lex(); // Eat fp token
4459 AsmToken Tok = Parser.getTok();
4460 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004461 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004462 return false;
4463 }
4464 Parser.Lex(); // Eat '=' token.
4465 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004466
4467 if (!parseFpABIValue(FpAbiVal, ".set"))
4468 return false;
4469
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004470 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004471 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004472 return false;
4473 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004474 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004475 Parser.Lex(); // Consume the EndOfStatement.
4476 return false;
4477}
4478
Toma Tabacu32c72aa2015-06-30 09:36:50 +00004479bool MipsAsmParser::parseSetOddSPRegDirective() {
4480 MCAsmParser &Parser = getParser();
4481
4482 Parser.Lex(); // Eat "oddspreg".
4483 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4484 reportParseError("unexpected token, expected end of statement");
4485 return false;
4486 }
4487
4488 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4489 getTargetStreamer().emitDirectiveSetOddSPReg();
4490 return false;
4491}
4492
4493bool MipsAsmParser::parseSetNoOddSPRegDirective() {
4494 MCAsmParser &Parser = getParser();
4495
4496 Parser.Lex(); // Eat "nooddspreg".
4497 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4498 reportParseError("unexpected token, expected end of statement");
4499 return false;
4500 }
4501
4502 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4503 getTargetStreamer().emitDirectiveSetNoOddSPReg();
4504 return false;
4505}
4506
Toma Tabacu9db22db2014-09-09 10:15:38 +00004507bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004508 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004509 SMLoc Loc = getLexer().getLoc();
4510
4511 Parser.Lex();
4512 if (getLexer().isNot(AsmToken::EndOfStatement))
4513 return reportParseError("unexpected token, expected end of statement");
4514
4515 // Always keep an element on the options "stack" to prevent the user
4516 // from changing the initial options. This is how we remember them.
4517 if (AssemblerOptions.size() == 2)
4518 return reportParseError(Loc, ".set pop with no .set push");
4519
4520 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00004521 setAvailableFeatures(
4522 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
4523 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00004524
4525 getTargetStreamer().emitDirectiveSetPop();
4526 return false;
4527}
4528
4529bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004530 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004531 Parser.Lex();
4532 if (getLexer().isNot(AsmToken::EndOfStatement))
4533 return reportParseError("unexpected token, expected end of statement");
4534
4535 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00004536 AssemblerOptions.push_back(
4537 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00004538
4539 getTargetStreamer().emitDirectiveSetPush();
4540 return false;
4541}
4542
Toma Tabacu29696502015-06-02 09:48:04 +00004543bool MipsAsmParser::parseSetSoftFloatDirective() {
4544 MCAsmParser &Parser = getParser();
4545 Parser.Lex();
4546 if (getLexer().isNot(AsmToken::EndOfStatement))
4547 return reportParseError("unexpected token, expected end of statement");
4548
4549 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4550 getTargetStreamer().emitDirectiveSetSoftFloat();
4551 return false;
4552}
4553
4554bool MipsAsmParser::parseSetHardFloatDirective() {
4555 MCAsmParser &Parser = getParser();
4556 Parser.Lex();
4557 if (getLexer().isNot(AsmToken::EndOfStatement))
4558 return reportParseError("unexpected token, expected end of statement");
4559
4560 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4561 getTargetStreamer().emitDirectiveSetHardFloat();
4562 return false;
4563}
4564
Jack Carterd76b2372013-03-21 21:44:16 +00004565bool MipsAsmParser::parseSetAssignment() {
4566 StringRef Name;
4567 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00004568 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00004569
4570 if (Parser.parseIdentifier(Name))
4571 reportParseError("expected identifier after .set");
4572
4573 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004574 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00004575 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00004576
Jack Carter3b2c96e2014-01-22 23:31:38 +00004577 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00004578 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00004579
Jim Grosbach6f482002015-05-18 18:43:14 +00004580 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00004581 Sym->setVariableValue(Value);
4582
4583 return false;
4584}
Jack Carterd0bd6422013-04-18 00:41:53 +00004585
Toma Tabacu26647792014-09-09 12:52:14 +00004586bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004587 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00004588 Parser.Lex();
4589 if (getLexer().isNot(AsmToken::EndOfStatement))
4590 return reportParseError("unexpected token, expected end of statement");
4591
4592 // Reset assembler options to their initial values.
Toma Tabacu465acfd2015-06-09 13:33:26 +00004593 setAvailableFeatures(
4594 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
4595 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00004596 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
4597
4598 getTargetStreamer().emitDirectiveSetMips0();
4599 return false;
4600}
4601
Toma Tabacu85618b32014-08-19 14:22:52 +00004602bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004603 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00004604 Parser.Lex();
4605 if (getLexer().isNot(AsmToken::Equal))
4606 return reportParseError("unexpected token, expected equals sign");
4607
4608 Parser.Lex();
4609 StringRef Arch;
4610 if (Parser.parseIdentifier(Arch))
4611 return reportParseError("expected arch identifier");
4612
4613 StringRef ArchFeatureName =
4614 StringSwitch<StringRef>(Arch)
4615 .Case("mips1", "mips1")
4616 .Case("mips2", "mips2")
4617 .Case("mips3", "mips3")
4618 .Case("mips4", "mips4")
4619 .Case("mips5", "mips5")
4620 .Case("mips32", "mips32")
4621 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004622 .Case("mips32r3", "mips32r3")
4623 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004624 .Case("mips32r6", "mips32r6")
4625 .Case("mips64", "mips64")
4626 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004627 .Case("mips64r3", "mips64r3")
4628 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004629 .Case("mips64r6", "mips64r6")
4630 .Case("cnmips", "cnmips")
4631 .Case("r4000", "mips3") // This is an implementation of Mips3.
4632 .Default("");
4633
4634 if (ArchFeatureName.empty())
4635 return reportParseError("unsupported architecture");
4636
4637 selectArch(ArchFeatureName);
4638 getTargetStreamer().emitDirectiveSetArch(Arch);
4639 return false;
4640}
4641
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004642bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004643 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004644 Parser.Lex();
4645 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004646 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004647
Matheus Almeida2852af82014-04-22 10:15:54 +00004648 switch (Feature) {
4649 default:
4650 llvm_unreachable("Unimplemented feature");
4651 case Mips::FeatureDSP:
4652 setFeatureBits(Mips::FeatureDSP, "dsp");
4653 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004654 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004655 case Mips::FeatureMicroMips:
4656 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004657 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004658 case Mips::FeatureMips1:
4659 selectArch("mips1");
4660 getTargetStreamer().emitDirectiveSetMips1();
4661 break;
4662 case Mips::FeatureMips2:
4663 selectArch("mips2");
4664 getTargetStreamer().emitDirectiveSetMips2();
4665 break;
4666 case Mips::FeatureMips3:
4667 selectArch("mips3");
4668 getTargetStreamer().emitDirectiveSetMips3();
4669 break;
4670 case Mips::FeatureMips4:
4671 selectArch("mips4");
4672 getTargetStreamer().emitDirectiveSetMips4();
4673 break;
4674 case Mips::FeatureMips5:
4675 selectArch("mips5");
4676 getTargetStreamer().emitDirectiveSetMips5();
4677 break;
4678 case Mips::FeatureMips32:
4679 selectArch("mips32");
4680 getTargetStreamer().emitDirectiveSetMips32();
4681 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004682 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004683 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004684 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004685 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004686 case Mips::FeatureMips32r3:
4687 selectArch("mips32r3");
4688 getTargetStreamer().emitDirectiveSetMips32R3();
4689 break;
4690 case Mips::FeatureMips32r5:
4691 selectArch("mips32r5");
4692 getTargetStreamer().emitDirectiveSetMips32R5();
4693 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004694 case Mips::FeatureMips32r6:
4695 selectArch("mips32r6");
4696 getTargetStreamer().emitDirectiveSetMips32R6();
4697 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004698 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004699 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00004700 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00004701 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004702 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004703 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004704 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00004705 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004706 case Mips::FeatureMips64r3:
4707 selectArch("mips64r3");
4708 getTargetStreamer().emitDirectiveSetMips64R3();
4709 break;
4710 case Mips::FeatureMips64r5:
4711 selectArch("mips64r5");
4712 getTargetStreamer().emitDirectiveSetMips64R5();
4713 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004714 case Mips::FeatureMips64r6:
4715 selectArch("mips64r6");
4716 getTargetStreamer().emitDirectiveSetMips64R6();
4717 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004718 }
4719 return false;
4720}
4721
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004722bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004723 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004724 if (getLexer().isNot(AsmToken::Comma)) {
4725 SMLoc Loc = getLexer().getLoc();
4726 Parser.eatToEndOfStatement();
4727 return Error(Loc, ErrorStr);
4728 }
4729
Matheus Almeida2852af82014-04-22 10:15:54 +00004730 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004731 return true;
4732}
4733
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004734bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00004735 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00004736 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004737
Toma Tabacudde4c462014-11-06 10:02:45 +00004738 if (inMips16Mode()) {
4739 reportParseError(".cpload is not supported in Mips16 mode");
4740 return false;
4741 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004742
David Blaikie960ea3f2014-06-08 16:18:35 +00004743 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00004744 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004745 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4746 reportParseError("expected register containing function address");
4747 return false;
4748 }
4749
David Blaikie960ea3f2014-06-08 16:18:35 +00004750 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
4751 if (!RegOpnd.isGPRAsmReg()) {
4752 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004753 return false;
4754 }
4755
Toma Tabacudde4c462014-11-06 10:02:45 +00004756 // If this is not the end of the statement, report an error.
4757 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4758 reportParseError("unexpected token, expected end of statement");
4759 return false;
4760 }
4761
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004762 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004763 return false;
4764}
4765
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004766bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004767 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004768 unsigned FuncReg;
4769 unsigned Save;
4770 bool SaveIsReg = true;
4771
Matheus Almeida7e815762014-06-18 13:08:59 +00004772 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004773 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00004774 if (ResTy == MatchOperand_NoMatch) {
4775 reportParseError("expected register containing function address");
4776 Parser.eatToEndOfStatement();
4777 return false;
4778 }
4779
4780 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4781 if (!FuncRegOpnd.isGPRAsmReg()) {
4782 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
4783 Parser.eatToEndOfStatement();
4784 return false;
4785 }
4786
4787 FuncReg = FuncRegOpnd.getGPR32Reg();
4788 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004789
Toma Tabacu65f10572014-09-16 15:00:52 +00004790 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004791 return true;
4792
Toma Tabacu13964452014-09-04 13:23:44 +00004793 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00004794 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004795 const AsmToken &Tok = Parser.getTok();
4796 if (Tok.is(AsmToken::Integer)) {
4797 Save = Tok.getIntVal();
4798 SaveIsReg = false;
4799 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00004800 } else {
4801 reportParseError("expected save register or stack offset");
4802 Parser.eatToEndOfStatement();
4803 return false;
4804 }
4805 } else {
4806 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4807 if (!SaveOpnd.isGPRAsmReg()) {
4808 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
4809 Parser.eatToEndOfStatement();
4810 return false;
4811 }
4812 Save = SaveOpnd.getGPR32Reg();
4813 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004814
Toma Tabacu65f10572014-09-16 15:00:52 +00004815 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004816 return true;
4817
Toma Tabacu8874eac2015-02-18 13:46:53 +00004818 const MCExpr *Expr;
4819 if (Parser.parseExpression(Expr)) {
4820 reportParseError("expected expression");
4821 return false;
4822 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004823
Toma Tabacu8874eac2015-02-18 13:46:53 +00004824 if (Expr->getKind() != MCExpr::SymbolRef) {
4825 reportParseError("expected symbol");
4826 return false;
4827 }
4828 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
4829
4830 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
4831 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004832 return false;
4833}
4834
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004835bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004836 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004837 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4838 const AsmToken &Tok = Parser.getTok();
4839
4840 if (Tok.getString() == "2008") {
4841 Parser.Lex();
4842 getTargetStreamer().emitDirectiveNaN2008();
4843 return false;
4844 } else if (Tok.getString() == "legacy") {
4845 Parser.Lex();
4846 getTargetStreamer().emitDirectiveNaNLegacy();
4847 return false;
4848 }
4849 }
4850 // If we don't recognize the option passed to the .nan
4851 // directive (e.g. no option or unknown option), emit an error.
4852 reportParseError("invalid option in .nan directive");
4853 return false;
4854}
4855
Jack Carter0b744b32012-10-04 02:29:46 +00004856bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004857 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004858 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00004859 const AsmToken &Tok = Parser.getTok();
4860
4861 if (Tok.getString() == "noat") {
4862 return parseSetNoAtDirective();
4863 } else if (Tok.getString() == "at") {
4864 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00004865 } else if (Tok.getString() == "arch") {
4866 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004867 } else if (Tok.getString() == "fp") {
4868 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00004869 } else if (Tok.getString() == "oddspreg") {
4870 return parseSetOddSPRegDirective();
4871 } else if (Tok.getString() == "nooddspreg") {
4872 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004873 } else if (Tok.getString() == "pop") {
4874 return parseSetPopDirective();
4875 } else if (Tok.getString() == "push") {
4876 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00004877 } else if (Tok.getString() == "reorder") {
4878 return parseSetReorderDirective();
4879 } else if (Tok.getString() == "noreorder") {
4880 return parseSetNoReorderDirective();
4881 } else if (Tok.getString() == "macro") {
4882 return parseSetMacroDirective();
4883 } else if (Tok.getString() == "nomacro") {
4884 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00004885 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00004886 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00004887 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00004888 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00004889 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00004890 getTargetStreamer().emitDirectiveSetNoMicroMips();
4891 Parser.eatToEndOfStatement();
4892 return false;
4893 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004894 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00004895 } else if (Tok.getString() == "mips0") {
4896 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00004897 } else if (Tok.getString() == "mips1") {
4898 return parseSetFeature(Mips::FeatureMips1);
4899 } else if (Tok.getString() == "mips2") {
4900 return parseSetFeature(Mips::FeatureMips2);
4901 } else if (Tok.getString() == "mips3") {
4902 return parseSetFeature(Mips::FeatureMips3);
4903 } else if (Tok.getString() == "mips4") {
4904 return parseSetFeature(Mips::FeatureMips4);
4905 } else if (Tok.getString() == "mips5") {
4906 return parseSetFeature(Mips::FeatureMips5);
4907 } else if (Tok.getString() == "mips32") {
4908 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00004909 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004910 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00004911 } else if (Tok.getString() == "mips32r3") {
4912 return parseSetFeature(Mips::FeatureMips32r3);
4913 } else if (Tok.getString() == "mips32r5") {
4914 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00004915 } else if (Tok.getString() == "mips32r6") {
4916 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00004917 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004918 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00004919 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004920 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00004921 } else if (Tok.getString() == "mips64r3") {
4922 return parseSetFeature(Mips::FeatureMips64r3);
4923 } else if (Tok.getString() == "mips64r5") {
4924 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00004925 } else if (Tok.getString() == "mips64r6") {
4926 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00004927 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004928 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004929 } else if (Tok.getString() == "nodsp") {
4930 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00004931 } else if (Tok.getString() == "msa") {
4932 return parseSetMsaDirective();
4933 } else if (Tok.getString() == "nomsa") {
4934 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00004935 } else if (Tok.getString() == "softfloat") {
4936 return parseSetSoftFloatDirective();
4937 } else if (Tok.getString() == "hardfloat") {
4938 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00004939 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00004940 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00004941 parseSetAssignment();
4942 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004943 }
Jack Carter07c818d2013-01-25 01:31:34 +00004944
Jack Carter0b744b32012-10-04 02:29:46 +00004945 return true;
4946}
4947
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004948/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00004949/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004950bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004951 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004952 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4953 for (;;) {
4954 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004955 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00004956 return true;
4957
4958 getParser().getStreamer().EmitValue(Value, Size);
4959
4960 if (getLexer().is(AsmToken::EndOfStatement))
4961 break;
4962
Jack Carter07c818d2013-01-25 01:31:34 +00004963 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004964 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00004965 Parser.Lex();
4966 }
4967 }
4968
4969 Parser.Lex();
4970 return false;
4971}
4972
Vladimir Medic4c299852013-11-06 11:27:05 +00004973/// parseDirectiveGpWord
4974/// ::= .gpword local_sym
4975bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004976 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004977 const MCExpr *Value;
4978 // EmitGPRel32Value requires an expression, so we are using base class
4979 // method to evaluate the expression.
4980 if (getParser().parseExpression(Value))
4981 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00004982 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00004983
Vladimir Medice10c1122013-11-13 13:18:04 +00004984 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004985 return Error(getLexer().getLoc(),
4986 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00004987 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00004988 return false;
4989}
4990
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004991/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00004992/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004993bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004994 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004995 const MCExpr *Value;
4996 // EmitGPRel64Value requires an expression, so we are using base class
4997 // method to evaluate the expression.
4998 if (getParser().parseExpression(Value))
4999 return true;
5000 getParser().getStreamer().EmitGPRel64Value(Value);
5001
5002 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005003 return Error(getLexer().getLoc(),
5004 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005005 Parser.Lex(); // Eat EndOfStatement token.
5006 return false;
5007}
5008
Jack Carter0cd3c192014-01-06 23:27:31 +00005009bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005010 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005011 // Get the option token.
5012 AsmToken Tok = Parser.getTok();
5013 // At the moment only identifiers are supported.
5014 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005015 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005016 Parser.eatToEndOfStatement();
5017 return false;
5018 }
5019
5020 StringRef Option = Tok.getIdentifier();
5021
5022 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005023 // MipsAsmParser needs to know if the current PIC mode changes.
5024 IsPicEnabled = false;
5025
Jack Carter0cd3c192014-01-06 23:27:31 +00005026 getTargetStreamer().emitDirectiveOptionPic0();
5027 Parser.Lex();
5028 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5029 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005030 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005031 Parser.eatToEndOfStatement();
5032 }
5033 return false;
5034 }
5035
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005036 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005037 // MipsAsmParser needs to know if the current PIC mode changes.
5038 IsPicEnabled = true;
5039
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005040 getTargetStreamer().emitDirectiveOptionPic2();
5041 Parser.Lex();
5042 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5043 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005044 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005045 Parser.eatToEndOfStatement();
5046 }
5047 return false;
5048 }
5049
Jack Carter0cd3c192014-01-06 23:27:31 +00005050 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005051 Warning(Parser.getTok().getLoc(),
5052 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005053 Parser.eatToEndOfStatement();
5054 return false;
5055}
5056
Toma Tabacu9ca50962015-04-16 09:53:47 +00005057/// parseInsnDirective
5058/// ::= .insn
5059bool MipsAsmParser::parseInsnDirective() {
5060 // If this is not the end of the statement, report an error.
5061 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5062 reportParseError("unexpected token, expected end of statement");
5063 return false;
5064 }
5065
5066 // The actual label marking happens in
5067 // MipsELFStreamer::createPendingLabelRelocs().
5068 getTargetStreamer().emitDirectiveInsn();
5069
5070 getParser().Lex(); // Eat EndOfStatement token.
5071 return false;
5072}
5073
Daniel Sanders7e527422014-07-10 13:38:23 +00005074/// parseDirectiveModule
5075/// ::= .module oddspreg
5076/// ::= .module nooddspreg
5077/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005078/// ::= .module softfloat
5079/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005080bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005081 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005082 MCAsmLexer &Lexer = getLexer();
5083 SMLoc L = Lexer.getLoc();
5084
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005085 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005086 // TODO : get a better message.
5087 reportParseError(".module directive must appear before any code");
5088 return false;
5089 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005090
Toma Tabacuc405c822015-01-23 10:40:19 +00005091 StringRef Option;
5092 if (Parser.parseIdentifier(Option)) {
5093 reportParseError("expected .module option identifier");
5094 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005095 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005096
Toma Tabacuc405c822015-01-23 10:40:19 +00005097 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005098 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005099
Toma Tabacu3c499582015-06-25 10:56:57 +00005100 // Synchronize the abiflags information with the FeatureBits information we
5101 // changed above.
5102 getTargetStreamer().updateABIInfo(*this);
5103
5104 // If printing assembly, use the recently updated abiflags information.
5105 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5106 // emitted at the end).
5107 getTargetStreamer().emitDirectiveModuleOddSPReg();
5108
Toma Tabacuc405c822015-01-23 10:40:19 +00005109 // If this is not the end of the statement, report an error.
5110 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5111 reportParseError("unexpected token, expected end of statement");
5112 return false;
5113 }
5114
5115 return false; // parseDirectiveModule has finished successfully.
5116 } else if (Option == "nooddspreg") {
5117 if (!isABI_O32()) {
5118 Error(L, "'.module nooddspreg' requires the O32 ABI");
5119 return false;
5120 }
5121
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005122 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005123
Toma Tabacu3c499582015-06-25 10:56:57 +00005124 // Synchronize the abiflags information with the FeatureBits information we
5125 // changed above.
5126 getTargetStreamer().updateABIInfo(*this);
5127
5128 // If printing assembly, use the recently updated abiflags information.
5129 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5130 // emitted at the end).
5131 getTargetStreamer().emitDirectiveModuleOddSPReg();
5132
Toma Tabacuc405c822015-01-23 10:40:19 +00005133 // If this is not the end of the statement, report an error.
5134 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5135 reportParseError("unexpected token, expected end of statement");
5136 return false;
5137 }
5138
5139 return false; // parseDirectiveModule has finished successfully.
5140 } else if (Option == "fp") {
5141 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005142 } else if (Option == "softfloat") {
5143 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5144
5145 // Synchronize the ABI Flags information with the FeatureBits information we
5146 // updated above.
5147 getTargetStreamer().updateABIInfo(*this);
5148
5149 // If printing assembly, use the recently updated ABI Flags information.
5150 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5151 // emitted later).
5152 getTargetStreamer().emitDirectiveModuleSoftFloat();
5153
5154 // If this is not the end of the statement, report an error.
5155 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5156 reportParseError("unexpected token, expected end of statement");
5157 return false;
5158 }
5159
5160 return false; // parseDirectiveModule has finished successfully.
5161 } else if (Option == "hardfloat") {
5162 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5163
5164 // Synchronize the ABI Flags information with the FeatureBits information we
5165 // updated above.
5166 getTargetStreamer().updateABIInfo(*this);
5167
5168 // If printing assembly, use the recently updated ABI Flags information.
5169 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5170 // emitted later).
5171 getTargetStreamer().emitDirectiveModuleHardFloat();
5172
5173 // If this is not the end of the statement, report an error.
5174 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5175 reportParseError("unexpected token, expected end of statement");
5176 return false;
5177 }
5178
5179 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005180 } else {
5181 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5182 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005183}
5184
5185/// parseDirectiveModuleFP
5186/// ::= =32
5187/// ::= =xx
5188/// ::= =64
5189bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005190 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005191 MCAsmLexer &Lexer = getLexer();
5192
5193 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005194 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005195 return false;
5196 }
5197 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005198
Daniel Sanders7e527422014-07-10 13:38:23 +00005199 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005200 if (!parseFpABIValue(FpABI, ".module"))
5201 return false;
5202
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005203 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005204 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005205 return false;
5206 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005207
Toma Tabacua64e5402015-06-25 12:44:38 +00005208 // Synchronize the abiflags information with the FeatureBits information we
5209 // changed above.
5210 getTargetStreamer().updateABIInfo(*this);
5211
5212 // If printing assembly, use the recently updated abiflags information.
5213 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5214 // emitted at the end).
5215 getTargetStreamer().emitDirectiveModuleFP();
5216
Daniel Sanders7e527422014-07-10 13:38:23 +00005217 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005218 return false;
5219}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005220
Daniel Sanders7e527422014-07-10 13:38:23 +00005221bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005222 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005223 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005224 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005225 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005226
5227 if (Lexer.is(AsmToken::Identifier)) {
5228 StringRef Value = Parser.getTok().getString();
5229 Parser.Lex();
5230
5231 if (Value != "xx") {
5232 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5233 return false;
5234 }
5235
5236 if (!isABI_O32()) {
5237 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5238 return false;
5239 }
5240
Daniel Sanders7e527422014-07-10 13:38:23 +00005241 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005242 if (ModuleLevelOptions) {
5243 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5244 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5245 } else {
5246 setFeatureBits(Mips::FeatureFPXX, "fpxx");
5247 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5248 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005249 return true;
5250 }
5251
5252 if (Lexer.is(AsmToken::Integer)) {
5253 unsigned Value = Parser.getTok().getIntVal();
5254 Parser.Lex();
5255
5256 if (Value != 32 && Value != 64) {
5257 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5258 return false;
5259 }
5260
5261 if (Value == 32) {
5262 if (!isABI_O32()) {
5263 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
5264 return false;
5265 }
5266
Daniel Sanders7e527422014-07-10 13:38:23 +00005267 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005268 if (ModuleLevelOptions) {
5269 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5270 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5271 } else {
5272 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5273 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5274 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005275 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00005276 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005277 if (ModuleLevelOptions) {
5278 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5279 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5280 } else {
5281 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5282 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
5283 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005284 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005285
Daniel Sanders7e527422014-07-10 13:38:23 +00005286 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005287 }
5288
5289 return false;
5290}
5291
Jack Carter0b744b32012-10-04 02:29:46 +00005292bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005293 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005294 StringRef IDVal = DirectiveID.getString();
5295
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005296 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005297 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00005298 if (IDVal == ".dword") {
5299 parseDataDirective(8, DirectiveID.getLoc());
5300 return false;
5301 }
Jack Carterd0bd6422013-04-18 00:41:53 +00005302 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005303 StringRef SymbolName;
5304
5305 if (Parser.parseIdentifier(SymbolName)) {
5306 reportParseError("expected identifier after .ent");
5307 return false;
5308 }
5309
5310 // There's an undocumented extension that allows an integer to
5311 // follow the name of the procedure which AFAICS is ignored by GAS.
5312 // Example: .ent foo,2
5313 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5314 if (getLexer().isNot(AsmToken::Comma)) {
5315 // Even though we accept this undocumented extension for compatibility
5316 // reasons, the additional integer argument does not actually change
5317 // the behaviour of the '.ent' directive, so we would like to discourage
5318 // its use. We do this by not referring to the extended version in
5319 // error messages which are not directly related to its use.
5320 reportParseError("unexpected token, expected end of statement");
5321 return false;
5322 }
5323 Parser.Lex(); // Eat the comma.
5324 const MCExpr *DummyNumber;
5325 int64_t DummyNumberVal;
5326 // If the user was explicitly trying to use the extended version,
5327 // we still give helpful extension-related error messages.
5328 if (Parser.parseExpression(DummyNumber)) {
5329 reportParseError("expected number after comma");
5330 return false;
5331 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00005332 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005333 reportParseError("expected an absolute expression after comma");
5334 return false;
5335 }
5336 }
5337
5338 // If this is not the end of the statement, report an error.
5339 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5340 reportParseError("unexpected token, expected end of statement");
5341 return false;
5342 }
5343
Jim Grosbach6f482002015-05-18 18:43:14 +00005344 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005345
5346 getTargetStreamer().emitDirectiveEnt(*Sym);
5347 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00005348 return false;
5349 }
5350
Jack Carter07c818d2013-01-25 01:31:34 +00005351 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005352 StringRef SymbolName;
5353
5354 if (Parser.parseIdentifier(SymbolName)) {
5355 reportParseError("expected identifier after .end");
5356 return false;
5357 }
5358
5359 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5360 reportParseError("unexpected token, expected end of statement");
5361 return false;
5362 }
5363
5364 if (CurrentFn == nullptr) {
5365 reportParseError(".end used without .ent");
5366 return false;
5367 }
5368
5369 if ((SymbolName != CurrentFn->getName())) {
5370 reportParseError(".end symbol does not match .ent symbol");
5371 return false;
5372 }
5373
5374 getTargetStreamer().emitDirectiveEnd(SymbolName);
5375 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00005376 return false;
5377 }
5378
Jack Carter07c818d2013-01-25 01:31:34 +00005379 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005380 // .frame $stack_reg, frame_size_in_bytes, $return_reg
5381 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005382 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005383 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5384 reportParseError("expected stack register");
5385 return false;
5386 }
5387
5388 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5389 if (!StackRegOpnd.isGPRAsmReg()) {
5390 reportParseError(StackRegOpnd.getStartLoc(),
5391 "expected general purpose register");
5392 return false;
5393 }
5394 unsigned StackReg = StackRegOpnd.getGPR32Reg();
5395
5396 if (Parser.getTok().is(AsmToken::Comma))
5397 Parser.Lex();
5398 else {
5399 reportParseError("unexpected token, expected comma");
5400 return false;
5401 }
5402
5403 // Parse the frame size.
5404 const MCExpr *FrameSize;
5405 int64_t FrameSizeVal;
5406
5407 if (Parser.parseExpression(FrameSize)) {
5408 reportParseError("expected frame size value");
5409 return false;
5410 }
5411
Jim Grosbach13760bd2015-05-30 01:25:56 +00005412 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005413 reportParseError("frame size not an absolute expression");
5414 return false;
5415 }
5416
5417 if (Parser.getTok().is(AsmToken::Comma))
5418 Parser.Lex();
5419 else {
5420 reportParseError("unexpected token, expected comma");
5421 return false;
5422 }
5423
5424 // Parse the return register.
5425 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00005426 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005427 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5428 reportParseError("expected return register");
5429 return false;
5430 }
5431
5432 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5433 if (!ReturnRegOpnd.isGPRAsmReg()) {
5434 reportParseError(ReturnRegOpnd.getStartLoc(),
5435 "expected general purpose register");
5436 return false;
5437 }
5438
5439 // If this is not the end of the statement, report an error.
5440 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5441 reportParseError("unexpected token, expected end of statement");
5442 return false;
5443 }
5444
5445 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
5446 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00005447 return false;
5448 }
5449
Jack Carter07c818d2013-01-25 01:31:34 +00005450 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00005451 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00005452 }
5453
Daniel Sandersd97a6342014-08-13 10:07:34 +00005454 if (IDVal == ".mask" || IDVal == ".fmask") {
5455 // .mask bitmask, frame_offset
5456 // bitmask: One bit for each register used.
5457 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
5458 // first register is expected to be saved.
5459 // Examples:
5460 // .mask 0x80000000, -4
5461 // .fmask 0x80000000, -4
5462 //
Jack Carterbe332172012-09-07 00:48:02 +00005463
Daniel Sandersd97a6342014-08-13 10:07:34 +00005464 // Parse the bitmask
5465 const MCExpr *BitMask;
5466 int64_t BitMaskVal;
5467
5468 if (Parser.parseExpression(BitMask)) {
5469 reportParseError("expected bitmask value");
5470 return false;
5471 }
5472
Jim Grosbach13760bd2015-05-30 01:25:56 +00005473 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005474 reportParseError("bitmask not an absolute expression");
5475 return false;
5476 }
5477
5478 if (Parser.getTok().is(AsmToken::Comma))
5479 Parser.Lex();
5480 else {
5481 reportParseError("unexpected token, expected comma");
5482 return false;
5483 }
5484
5485 // Parse the frame_offset
5486 const MCExpr *FrameOffset;
5487 int64_t FrameOffsetVal;
5488
5489 if (Parser.parseExpression(FrameOffset)) {
5490 reportParseError("expected frame offset value");
5491 return false;
5492 }
5493
Jim Grosbach13760bd2015-05-30 01:25:56 +00005494 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005495 reportParseError("frame offset not an absolute expression");
5496 return false;
5497 }
5498
5499 // If this is not the end of the statement, report an error.
5500 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5501 reportParseError("unexpected token, expected end of statement");
5502 return false;
5503 }
5504
5505 if (IDVal == ".mask")
5506 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
5507 else
5508 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00005509 return false;
5510 }
5511
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005512 if (IDVal == ".nan")
5513 return parseDirectiveNaN();
5514
Jack Carter07c818d2013-01-25 01:31:34 +00005515 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005516 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00005517 return false;
5518 }
5519
Rafael Espindolab59fb732014-03-28 18:50:26 +00005520 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005521 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005522 return false;
5523 }
5524
Jack Carter07c818d2013-01-25 01:31:34 +00005525 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005526 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00005527 return false;
5528 }
5529
Jack Carter0cd3c192014-01-06 23:27:31 +00005530 if (IDVal == ".option")
5531 return parseDirectiveOption();
5532
5533 if (IDVal == ".abicalls") {
5534 getTargetStreamer().emitDirectiveAbiCalls();
5535 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005536 Error(Parser.getTok().getLoc(),
5537 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005538 // Clear line
5539 Parser.eatToEndOfStatement();
5540 }
5541 return false;
5542 }
5543
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005544 if (IDVal == ".cpsetup")
5545 return parseDirectiveCPSetup();
5546
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005547 if (IDVal == ".module")
5548 return parseDirectiveModule();
5549
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005550 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
5551 return parseInternalDirectiveReallowModule();
5552
Toma Tabacu9ca50962015-04-16 09:53:47 +00005553 if (IDVal == ".insn")
5554 return parseInsnDirective();
5555
Rafael Espindola870c4e92012-01-11 03:56:41 +00005556 return true;
5557}
5558
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005559bool MipsAsmParser::parseInternalDirectiveReallowModule() {
5560 // If this is not the end of the statement, report an error.
5561 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5562 reportParseError("unexpected token, expected end of statement");
5563 return false;
5564 }
5565
5566 getTargetStreamer().reallowModuleDirective();
5567
5568 getParser().Lex(); // Eat EndOfStatement token.
5569 return false;
5570}
5571
Rafael Espindola870c4e92012-01-11 03:56:41 +00005572extern "C" void LLVMInitializeMipsAsmParser() {
5573 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
5574 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
5575 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
5576 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
5577}
Jack Carterb4dbc172012-09-05 23:34:03 +00005578
5579#define GET_REGISTER_MATCHER
5580#define GET_MATCHER_IMPLEMENTATION
5581#include "MipsGenAsmMatcher.inc"