blob: 2d82b35cc6e7a6c1754273cf31f8f19e9ecb775c [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"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000014#include "MipsTargetStreamer.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000015#include "llvm/ADT/APInt.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000016#include "llvm/ADT/SmallVector.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000017#include "llvm/ADT/StringSwitch.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000018#include "llvm/MC/MCContext.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000021#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000022#include "llvm/MC/MCParser/MCAsmLexer.h"
23#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000024#include "llvm/MC/MCStreamer.h"
25#include "llvm/MC/MCSubtargetInfo.h"
26#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000027#include "llvm/MC/MCTargetAsmParser.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000028#include "llvm/Support/Debug.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000029#include "llvm/Support/MathExtras.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000030#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000031#include "llvm/Support/TargetRegistry.h"
Benjamin Kramer799003b2015-03-23 19:32:43 +000032#include "llvm/Support/raw_ostream.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000033#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000034
35using namespace llvm;
36
Chandler Carruthe96dd892014-04-21 22:55:11 +000037#define DEBUG_TYPE "mips-asm-parser"
38
Joey Gouly0e76fa72013-09-12 10:28:05 +000039namespace llvm {
40class MCInstrInfo;
41}
42
Rafael Espindola870c4e92012-01-11 03:56:41 +000043namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000044class MipsAssemblerOptions {
45public:
Toma Tabacu465acfd2015-06-09 13:33:26 +000046 MipsAssemblerOptions(const FeatureBitset &Features_) :
Toma Tabacu9db22db2014-09-09 10:15:38 +000047 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000048
Toma Tabacu9db22db2014-09-09 10:15:38 +000049 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000050 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000051 Reorder = Opts->isReorder();
52 Macro = Opts->isMacro();
53 Features = Opts->getFeatures();
54 }
55
Toma Tabacub19cf202015-04-27 13:12:59 +000056 unsigned getATRegIndex() const { return ATReg; }
57 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000058 if (Reg > 31)
59 return false;
60
61 ATReg = Reg;
62 return true;
63 }
Jack Carter0b744b32012-10-04 02:29:46 +000064
Toma Tabacu9db22db2014-09-09 10:15:38 +000065 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000066 void setReorder() { Reorder = true; }
67 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000068
Toma Tabacu9db22db2014-09-09 10:15:38 +000069 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000070 void setMacro() { Macro = true; }
71 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000072
Toma Tabacu465acfd2015-06-09 13:33:26 +000073 const FeatureBitset &getFeatures() const { return Features; }
74 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000075
Daniel Sandersf0df2212014-08-04 12:20:00 +000076 // Set of features that are either architecture features or referenced
77 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
78 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
79 // The reason we need this mask is explained in the selectArch function.
80 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +000081 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +000082
Jack Carter0b744b32012-10-04 02:29:46 +000083private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000084 unsigned ATReg;
85 bool Reorder;
86 bool Macro;
Toma Tabacu465acfd2015-06-09 13:33:26 +000087 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +000088};
89}
90
Michael Kupersteindb0712f2015-05-26 10:47:10 +000091const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
92 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
93 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
94 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
95 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
96 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
97 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
98 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
99 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
100};
101
Jack Carter0b744b32012-10-04 02:29:46 +0000102namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +0000103class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000104 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000105 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000106 return static_cast<MipsTargetStreamer &>(TS);
107 }
108
Jack Carterb4dbc172012-09-05 23:34:03 +0000109 MCSubtargetInfo &STI;
Eric Christophera5762812015-01-26 17:33:46 +0000110 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000111 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000112 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
113 // nullptr, which indicates that no function is currently
114 // selected. This usually happens after an '.end func'
115 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000116 bool IsLittleEndian;
Jack Carter0b744b32012-10-04 02:29:46 +0000117
Daniel Sandersef638fe2014-10-03 15:37:37 +0000118 // Print a warning along with its fix-it message at the given range.
119 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
120 SMRange Range, bool ShowColors = true);
121
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000122#define GET_ASSEMBLER_HEADER
123#include "MipsGenAsmMatcher.inc"
124
Matheus Almeida595fcab2014-06-11 15:05:56 +0000125 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
126
Chad Rosier49963552012-10-13 00:26:04 +0000127 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000128 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000129 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000130 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000131
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000132 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000133 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000134
Toma Tabacu13964452014-09-04 13:23:44 +0000135 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000136
Toma Tabacu13964452014-09-04 13:23:44 +0000137 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000138
David Blaikie960ea3f2014-06-08 16:18:35 +0000139 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
140 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000141
Craig Topper56c590a2014-04-29 07:58:02 +0000142 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000143
David Blaikie960ea3f2014-06-08 16:18:35 +0000144 MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000145
146 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000147 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000148 StringRef Identifier, SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000149
Jack Carter873c7242013-01-12 01:03:14 +0000150 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000151 matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
Jack Carter873c7242013-01-12 01:03:14 +0000152
Toma Tabacu13964452014-09-04 13:23:44 +0000153 MipsAsmParser::OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000154
Toma Tabacu13964452014-09-04 13:23:44 +0000155 MipsAsmParser::OperandMatchResultTy parseImm(OperandVector &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000156
Toma Tabacu13964452014-09-04 13:23:44 +0000157 MipsAsmParser::OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000158
David Blaikie960ea3f2014-06-08 16:18:35 +0000159 MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000160
Toma Tabacu13964452014-09-04 13:23:44 +0000161 MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000162
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000163 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000164 parseRegisterPair (OperandVector &Operands);
165
166 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +0000167 parseMovePRegPair(OperandVector &Operands);
168
169 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000170 parseRegisterList (OperandVector &Operands);
171
David Blaikie960ea3f2014-06-08 16:18:35 +0000172 bool searchSymbolAlias(OperandVector &Operands);
173
Toma Tabacu13964452014-09-04 13:23:44 +0000174 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000175
Jack Carter30a59822012-10-04 04:03:53 +0000176 bool needsExpansion(MCInst &Inst);
177
Matheus Almeida3813d572014-06-19 14:39:14 +0000178 // Expands assembly pseudo instructions.
179 // Returns false on success, true otherwise.
180 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000181 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000182
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000183 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
184 SmallVectorImpl<MCInst> &Instructions);
185
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000186 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000187 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000188 SmallVectorImpl<MCInst> &Instructions);
189
Toma Tabacuf712ede2015-06-17 14:31:51 +0000190 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
191 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
192 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacu674825c2015-06-16 12:16:24 +0000193
Toma Tabacu00e98672015-05-01 12:19:27 +0000194 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000195 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000196
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000197 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
198 const MCOperand &Offset, bool Is32BitAddress,
199 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000200
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000201 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
202 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000203
Jack Carter9e65aa32013-03-22 00:05:30 +0000204 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000205 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
206 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000207
208 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
209 SmallVectorImpl<MCInst> &Instructions);
210
Toma Tabacue1e460d2015-06-11 10:36:10 +0000211 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc,
212 SmallVectorImpl<MCInst> &Instructions);
213
Toma Tabacu1a108322015-06-17 13:20:24 +0000214 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc,
215 SmallVectorImpl<MCInst> &Instructions);
216
Toma Tabacud88d79c2015-06-23 14:39:42 +0000217 bool expandUlhu(MCInst &Inst, SMLoc IDLoc,
218 SmallVectorImpl<MCInst> &Instructions);
219
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000220 bool expandUlw(MCInst &Inst, SMLoc IDLoc,
221 SmallVectorImpl<MCInst> &Instructions);
222
Toma Tabacu234482a2015-03-16 12:03:39 +0000223 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
224 SmallVectorImpl<MCInst> &Instructions);
225
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000226 void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +0000227 bool Is64Bit, SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000228
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000229 bool reportParseError(Twine ErrorMsg);
230 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000231
Jack Carterb5cf5902013-04-17 00:18:04 +0000232 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000233 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000234
Vladimir Medic4c299852013-11-06 11:27:05 +0000235 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000236
237 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000238 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000239 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000240 bool parseSetFeature(uint64_t Feature);
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000241 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000242 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000243 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000244 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000245 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000246 bool parseInsnDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000247
248 bool parseSetAtDirective();
249 bool parseSetNoAtDirective();
250 bool parseSetMacroDirective();
251 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000252 bool parseSetMsaDirective();
253 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000254 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000255 bool parseSetReorderDirective();
256 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000257 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000258 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000259 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000260 bool parseSetOddSPRegDirective();
261 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000262 bool parseSetPopDirective();
263 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000264 bool parseSetSoftFloatDirective();
265 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000266
Jack Carterd76b2372013-03-21 21:44:16 +0000267 bool parseSetAssignment();
268
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000269 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000270 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000271 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000272 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000273 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000274 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
275 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000276
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000277 bool parseInternalDirectiveReallowModule();
278
Jack Carterdc1e35d2012-09-06 20:00:02 +0000279 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000280
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000281 bool eatComma(StringRef ErrorStr);
282
Jack Carter1ac53222013-02-20 23:11:17 +0000283 int matchCPURegisterName(StringRef Symbol);
284
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000285 int matchHWRegsRegisterName(StringRef Symbol);
286
Jack Carter873c7242013-01-12 01:03:14 +0000287 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000288
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000289 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000290
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000291 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000292
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000293 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000294
Jack Carter5dc8ac92013-09-25 23:50:44 +0000295 int matchMSA128RegisterName(StringRef Name);
296
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000297 int matchMSA128CtrlRegisterName(StringRef Name);
298
Jack Carterd0bd6422013-04-18 00:41:53 +0000299 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000300
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000301 unsigned getGPR(int RegNo);
302
Toma Tabacu89a712b2015-04-15 10:48:56 +0000303 /// Returns the internal register number for the current AT. Also checks if
304 /// the current AT is unavailable (set to $0) and gives an error if it is.
305 /// This should be used in pseudo-instruction expansions which need AT.
306 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000307
308 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000309 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000310
311 // Helper function that checks if the value of a vector index is within the
312 // boundaries of accepted values for each RegisterKind
313 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
314 bool validateMSAIndex(int Val, int RegKind);
315
Daniel Sandersf0df2212014-08-04 12:20:00 +0000316 // Selects a new architecture by updating the FeatureBits with the necessary
317 // info including implied dependencies.
318 // Internally, it clears all the feature bits related to *any* architecture
319 // and selects the new one using the ToggleFeature functionality of the
320 // MCSubtargetInfo object that handles implied dependencies. The reason we
321 // clear all the arch related bits manually is because ToggleFeature only
322 // clears the features that imply the feature being cleared and not the
323 // features implied by the feature being cleared. This is easier to see
324 // with an example:
325 // --------------------------------------------------
326 // | Feature | Implies |
327 // | -------------------------------------------------|
328 // | FeatureMips1 | None |
329 // | FeatureMips2 | FeatureMips1 |
330 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
331 // | FeatureMips4 | FeatureMips3 |
332 // | ... | |
333 // --------------------------------------------------
334 //
335 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
336 // FeatureMipsGP64 | FeatureMips1)
337 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
338 void selectArch(StringRef ArchFeature) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000339 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000340 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
341 STI.setFeatureBits(FeatureBits);
342 setAvailableFeatures(
343 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000344 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000345 }
346
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000347 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000348 if (!(STI.getFeatureBits()[Feature])) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000349 setAvailableFeatures(
350 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000351 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000352 }
353 }
354
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000355 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000356 if (STI.getFeatureBits()[Feature]) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000357 setAvailableFeatures(
358 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000359 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000360 }
361 }
362
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000363 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
364 setFeatureBits(Feature, FeatureString);
365 AssemblerOptions.front()->setFeatures(STI.getFeatureBits());
366 }
367
368 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
369 clearFeatureBits(Feature, FeatureString);
370 AssemblerOptions.front()->setFeatures(STI.getFeatureBits());
371 }
372
Rafael Espindola870c4e92012-01-11 03:56:41 +0000373public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000374 enum MipsMatchResultTy {
375 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
376#define GET_OPERAND_DIAGNOSTIC_TYPES
377#include "MipsGenAsmMatcher.inc"
378#undef GET_OPERAND_DIAGNOSTIC_TYPES
379
380 };
381
Joey Gouly0e76fa72013-09-12 10:28:05 +0000382 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000383 const MCInstrInfo &MII, const MCTargetOptions &Options)
Colin LeMahieufe2c8b82015-07-27 21:56:53 +0000384 : MCTargetAsmParser(Options), STI(sti),
Eric Christophera5762812015-01-26 17:33:46 +0000385 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
386 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000387 MCAsmParserExtension::Initialize(parser);
388
Toma Tabacu11e14a92015-04-21 11:50:52 +0000389 parser.addAliasForDirective(".asciiz", ".asciz");
390
Jack Carterb4dbc172012-09-05 23:34:03 +0000391 // Initialize the set of available features.
392 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000393
Toma Tabacu9db22db2014-09-09 10:15:38 +0000394 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000395 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000396 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000397
Toma Tabacu9db22db2014-09-09 10:15:38 +0000398 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000399 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000400 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000401
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000402 getTargetStreamer().updateABIInfo(*this);
403
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000404 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000405 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000406
407 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000408
409 Triple TheTriple(sti.getTargetTriple());
410 if ((TheTriple.getArch() == Triple::mips) ||
411 (TheTriple.getArch() == Triple::mips64))
412 IsLittleEndian = false;
413 else
414 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000415 }
416
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000417 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
418 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
419
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000420 bool isGP64bit() const { return STI.getFeatureBits()[Mips::FeatureGP64Bit]; }
421 bool isFP64bit() const { return STI.getFeatureBits()[Mips::FeatureFP64Bit]; }
Eric Christophera5762812015-01-26 17:33:46 +0000422 const MipsABIInfo &getABI() const { return ABI; }
423 bool isABI_N32() const { return ABI.IsN32(); }
424 bool isABI_N64() const { return ABI.IsN64(); }
425 bool isABI_O32() const { return ABI.IsO32(); }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000426 bool isABI_FPXX() const { return STI.getFeatureBits()[Mips::FeatureFPXX]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000427
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000428 bool useOddSPReg() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000429 return !(STI.getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000430 }
431
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000432 bool inMicroMipsMode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000433 return STI.getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000434 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000435 bool hasMips1() const { return STI.getFeatureBits()[Mips::FeatureMips1]; }
436 bool hasMips2() const { return STI.getFeatureBits()[Mips::FeatureMips2]; }
437 bool hasMips3() const { return STI.getFeatureBits()[Mips::FeatureMips3]; }
438 bool hasMips4() const { return STI.getFeatureBits()[Mips::FeatureMips4]; }
439 bool hasMips5() const { return STI.getFeatureBits()[Mips::FeatureMips5]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000440 bool hasMips32() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000441 return STI.getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000442 }
443 bool hasMips64() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000444 return STI.getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000445 }
446 bool hasMips32r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000447 return STI.getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000448 }
449 bool hasMips64r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000450 return STI.getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000451 }
Daniel Sanders17793142015-02-18 16:24:50 +0000452 bool hasMips32r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000453 return (STI.getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000454 }
455 bool hasMips64r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000456 return (STI.getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000457 }
458 bool hasMips32r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000459 return (STI.getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000460 }
461 bool hasMips64r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000462 return (STI.getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000463 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000464 bool hasMips32r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000465 return STI.getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000466 }
467 bool hasMips64r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000468 return STI.getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000469 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000470
471 bool hasDSP() const { return STI.getFeatureBits()[Mips::FeatureDSP]; }
472 bool hasDSPR2() const { return STI.getFeatureBits()[Mips::FeatureDSPR2]; }
473 bool hasMSA() const { return STI.getFeatureBits()[Mips::FeatureMSA]; }
Kai Nackee0245392015-01-27 19:11:28 +0000474 bool hasCnMips() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000475 return (STI.getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000476 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000477
478 bool inMips16Mode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000479 return STI.getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000480 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000481
Eric Christophere8ae3e32015-05-07 23:10:21 +0000482 bool useSoftFloat() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000483 return STI.getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000484 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000485
Toma Tabacud9d344b2015-04-27 14:05:04 +0000486 /// Warn if RegIndex is the same as the current AT.
487 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000488
489 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000490
491 bool isLittle() const { return IsLittleEndian; }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000492};
493}
494
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000495namespace {
496
497/// MipsOperand - Instances of this class represent a parsed Mips machine
498/// instruction.
499class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000500public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000501 /// Broad categories of register classes
502 /// The exact class is finalized by the render method.
503 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000504 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000505 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000506 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000507 RegKind_FCC = 4, /// FCC
508 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
509 RegKind_MSACtrl = 16, /// MSA control registers
510 RegKind_COP2 = 32, /// COP2
511 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
512 /// context).
513 RegKind_CCR = 128, /// CCR
514 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000515 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000516 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000517 /// Potentially any (e.g. $1)
518 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
519 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000520 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000521 };
522
523private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000524 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000525 k_Immediate, /// An immediate (possibly involving symbol references)
526 k_Memory, /// Base + Offset Memory Address
527 k_PhysRegister, /// A physical register from the Mips namespace
528 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000529 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000530 k_RegList, /// A physical register list
531 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000532 } Kind;
533
David Blaikie960ea3f2014-06-08 16:18:35 +0000534public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000535 MipsOperand(KindTy K, MipsAsmParser &Parser)
536 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
537
David Blaikie960ea3f2014-06-08 16:18:35 +0000538private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000539 /// For diagnostics, and checking the assembler temporary
540 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000541
Eric Christopher8996c5d2013-03-15 00:42:55 +0000542 struct Token {
543 const char *Data;
544 unsigned Length;
545 };
546
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000547 struct PhysRegOp {
548 unsigned Num; /// Register Number
549 };
550
551 struct RegIdxOp {
552 unsigned Index; /// Index into the register class
553 RegKind Kind; /// Bitfield of the kinds it could possibly be
554 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000555 };
556
557 struct ImmOp {
558 const MCExpr *Val;
559 };
560
561 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000562 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000563 const MCExpr *Off;
564 };
565
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000566 struct RegListOp {
567 SmallVector<unsigned, 10> *List;
568 };
569
Jack Carterb4dbc172012-09-05 23:34:03 +0000570 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000571 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000572 struct PhysRegOp PhysReg;
573 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000574 struct ImmOp Imm;
575 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000576 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000577 };
578
579 SMLoc StartLoc, EndLoc;
580
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000581 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000582 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
583 const MCRegisterInfo *RegInfo,
584 SMLoc S, SMLoc E,
585 MipsAsmParser &Parser) {
586 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000587 Op->RegIdx.Index = Index;
588 Op->RegIdx.RegInfo = RegInfo;
589 Op->RegIdx.Kind = RegKind;
590 Op->StartLoc = S;
591 Op->EndLoc = E;
592 return Op;
593 }
594
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000595public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000596 /// Coerce the register to GPR32 and return the real register for the current
597 /// target.
598 unsigned getGPR32Reg() const {
599 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000600 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000601 unsigned ClassID = Mips::GPR32RegClassID;
602 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000603 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000604
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000605 /// Coerce the register to GPR32 and return the real register for the current
606 /// target.
607 unsigned getGPRMM16Reg() const {
608 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
609 unsigned ClassID = Mips::GPR32RegClassID;
610 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
611 }
612
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000613 /// Coerce the register to GPR64 and return the real register for the current
614 /// target.
615 unsigned getGPR64Reg() const {
616 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
617 unsigned ClassID = Mips::GPR64RegClassID;
618 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000619 }
620
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000621private:
622 /// Coerce the register to AFGR64 and return the real register for the current
623 /// target.
624 unsigned getAFGR64Reg() const {
625 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
626 if (RegIdx.Index % 2 != 0)
627 AsmParser.Warning(StartLoc, "Float register should be even.");
628 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
629 .getRegister(RegIdx.Index / 2);
630 }
631
632 /// Coerce the register to FGR64 and return the real register for the current
633 /// target.
634 unsigned getFGR64Reg() const {
635 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
636 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
637 .getRegister(RegIdx.Index);
638 }
639
640 /// Coerce the register to FGR32 and return the real register for the current
641 /// target.
642 unsigned getFGR32Reg() const {
643 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
644 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
645 .getRegister(RegIdx.Index);
646 }
647
648 /// Coerce the register to FGRH32 and return the real register for the current
649 /// target.
650 unsigned getFGRH32Reg() const {
651 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
652 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
653 .getRegister(RegIdx.Index);
654 }
655
656 /// Coerce the register to FCC and return the real register for the current
657 /// target.
658 unsigned getFCCReg() const {
659 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
660 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
661 .getRegister(RegIdx.Index);
662 }
663
664 /// Coerce the register to MSA128 and return the real register for the current
665 /// target.
666 unsigned getMSA128Reg() const {
667 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
668 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
669 // identical
670 unsigned ClassID = Mips::MSA128BRegClassID;
671 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
672 }
673
674 /// Coerce the register to MSACtrl and return the real register for the
675 /// current target.
676 unsigned getMSACtrlReg() const {
677 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
678 unsigned ClassID = Mips::MSACtrlRegClassID;
679 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
680 }
681
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000682 /// Coerce the register to COP0 and return the real register for the
683 /// current target.
684 unsigned getCOP0Reg() const {
685 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
686 unsigned ClassID = Mips::COP0RegClassID;
687 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
688 }
689
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000690 /// Coerce the register to COP2 and return the real register for the
691 /// current target.
692 unsigned getCOP2Reg() const {
693 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
694 unsigned ClassID = Mips::COP2RegClassID;
695 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
696 }
697
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000698 /// Coerce the register to COP3 and return the real register for the
699 /// current target.
700 unsigned getCOP3Reg() const {
701 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
702 unsigned ClassID = Mips::COP3RegClassID;
703 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
704 }
705
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000706 /// Coerce the register to ACC64DSP and return the real register for the
707 /// current target.
708 unsigned getACC64DSPReg() const {
709 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
710 unsigned ClassID = Mips::ACC64DSPRegClassID;
711 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
712 }
713
714 /// Coerce the register to HI32DSP and return the real register for the
715 /// current target.
716 unsigned getHI32DSPReg() const {
717 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
718 unsigned ClassID = Mips::HI32DSPRegClassID;
719 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
720 }
721
722 /// Coerce the register to LO32DSP and return the real register for the
723 /// current target.
724 unsigned getLO32DSPReg() const {
725 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
726 unsigned ClassID = Mips::LO32DSPRegClassID;
727 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
728 }
729
730 /// Coerce the register to CCR and return the real register for the
731 /// current target.
732 unsigned getCCRReg() const {
733 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
734 unsigned ClassID = Mips::CCRRegClassID;
735 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
736 }
737
738 /// Coerce the register to HWRegs and return the real register for the
739 /// current target.
740 unsigned getHWRegsReg() const {
741 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
742 unsigned ClassID = Mips::HWRegsRegClassID;
743 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
744 }
745
746public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000747 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000748 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000749 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000750 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000751 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000752 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000753 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000754 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000755 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000756
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000757 void addRegOperands(MCInst &Inst, unsigned N) const {
758 llvm_unreachable("Use a custom parser instead");
759 }
760
Daniel Sanders21bce302014-04-01 12:35:23 +0000761 /// Render the operand to an MCInst as a GPR32
762 /// Asserts if the wrong number of operands are requested, or the operand
763 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000764 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
765 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000766 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000767 }
768
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000769 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
770 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000771 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000772 }
773
Jozef Kolek1904fa22014-11-24 14:25:53 +0000774 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
775 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000776 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000777 }
778
Zoran Jovanovic41688672015-02-10 16:36:20 +0000779 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
780 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000781 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000782 }
783
Daniel Sanders21bce302014-04-01 12:35:23 +0000784 /// Render the operand to an MCInst as a GPR64
785 /// Asserts if the wrong number of operands are requested, or the operand
786 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000787 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
788 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000789 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000790 }
791
792 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
793 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000794 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000795 }
796
797 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
798 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000799 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000800 }
801
802 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
803 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000804 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000805 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000806 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000807 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
808 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000809 }
810
811 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
812 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000813 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000814 }
815
816 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
817 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000818 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000819 }
820
821 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
822 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000823 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000824 }
825
826 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
827 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000828 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000829 }
830
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000831 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
832 assert(N == 1 && "Invalid number of operands!");
833 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
834 }
835
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000836 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
837 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000838 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000839 }
840
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000841 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
842 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000843 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000844 }
845
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000846 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
847 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000848 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000849 }
850
851 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
852 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000853 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000854 }
855
856 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
857 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000858 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000859 }
860
861 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
862 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000863 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000864 }
865
866 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
867 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000868 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000869 }
870
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000871 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000872 assert(N == 1 && "Invalid number of operands!");
873 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000874 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000875 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000876
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000877 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000878 assert(N == 2 && "Invalid number of operands!");
879
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000880 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
881 ? getMemBase()->getGPR64Reg()
882 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000883
884 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000885 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000886 }
887
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000888 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
889 assert(N == 2 && "Invalid number of operands!");
890
Jim Grosbache9119e42015-05-13 18:37:00 +0000891 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000892
893 const MCExpr *Expr = getMemOff();
894 addExpr(Inst, Expr);
895 }
896
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000897 void addRegListOperands(MCInst &Inst, unsigned N) const {
898 assert(N == 1 && "Invalid number of operands!");
899
900 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000901 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000902 }
903
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000904 void addRegPairOperands(MCInst &Inst, unsigned N) const {
905 assert(N == 2 && "Invalid number of operands!");
906 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +0000907 Inst.addOperand(MCOperand::createReg(RegNo++));
908 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000909 }
910
Zoran Jovanovic41688672015-02-10 16:36:20 +0000911 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
912 assert(N == 2 && "Invalid number of operands!");
913 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000914 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000915 }
916
Craig Topper56c590a2014-04-29 07:58:02 +0000917 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000918 // As a special case until we sort out the definition of div/divu, pretend
919 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
920 if (isGPRAsmReg() && RegIdx.Index == 0)
921 return true;
922
923 return Kind == k_PhysRegister;
924 }
925 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000926 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000927 bool isConstantImm() const {
928 return isImm() && dyn_cast<MCConstantExpr>(getImm());
929 }
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +0000930 template <unsigned Bits> bool isUImm() const {
931 return isImm() && isConstantImm() && isUInt<Bits>(getConstantImm());
932 }
Craig Topper56c590a2014-04-29 07:58:02 +0000933 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000934 // Note: It's not possible to pretend that other operand kinds are tokens.
935 // The matcher emitter checks tokens first.
936 return Kind == k_Token;
937 }
Craig Topper56c590a2014-04-29 07:58:02 +0000938 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000939 bool isConstantMemOff() const {
940 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
941 }
942 template <unsigned Bits> bool isMemWithSimmOffset() const {
943 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
944 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000945 bool isMemWithGRPMM16Base() const {
946 return isMem() && getMemBase()->isMM16AsmReg();
947 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000948 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
949 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
950 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
951 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000952 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
953 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
954 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
955 && (getMemBase()->getGPR32Reg() == Mips::SP);
956 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000957 bool isRegList16() const {
958 if (!isRegList())
959 return false;
960
961 int Size = RegList.List->size();
962 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
963 RegList.List->back() != Mips::RA)
964 return false;
965
966 int PrevReg = *RegList.List->begin();
967 for (int i = 1; i < Size - 1; i++) {
968 int Reg = (*(RegList.List))[i];
969 if ( Reg != PrevReg + 1)
970 return false;
971 PrevReg = Reg;
972 }
973
974 return true;
975 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000976 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000977 bool isLSAImm() const {
978 if (!isConstantImm())
979 return false;
980 int64_t Val = getConstantImm();
981 return 1 <= Val && Val <= 4;
982 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000983 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +0000984 bool isMovePRegPair() const {
985 if (Kind != k_RegList || RegList.List->size() != 2)
986 return false;
987
988 unsigned R0 = RegList.List->front();
989 unsigned R1 = RegList.List->back();
990
991 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
992 (R0 == Mips::A1 && R1 == Mips::A3) ||
993 (R0 == Mips::A2 && R1 == Mips::A3) ||
994 (R0 == Mips::A0 && R1 == Mips::S5) ||
995 (R0 == Mips::A0 && R1 == Mips::S6) ||
996 (R0 == Mips::A0 && R1 == Mips::A1) ||
997 (R0 == Mips::A0 && R1 == Mips::A2) ||
998 (R0 == Mips::A0 && R1 == Mips::A3))
999 return true;
1000
1001 return false;
1002 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001003
1004 StringRef getToken() const {
1005 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001006 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001007 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001008 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001009
Craig Topper56c590a2014-04-29 07:58:02 +00001010 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001011 // As a special case until we sort out the definition of div/divu, pretend
1012 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1013 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1014 RegIdx.Kind & RegKind_GPR)
1015 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001016
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001017 assert(Kind == k_PhysRegister && "Invalid access!");
1018 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001019 }
1020
Jack Carterb4dbc172012-09-05 23:34:03 +00001021 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001022 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001023 return Imm.Val;
1024 }
1025
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001026 int64_t getConstantImm() const {
1027 const MCExpr *Val = getImm();
1028 return static_cast<const MCConstantExpr *>(Val)->getValue();
1029 }
1030
1031 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001032 assert((Kind == k_Memory) && "Invalid access!");
1033 return Mem.Base;
1034 }
1035
1036 const MCExpr *getMemOff() const {
1037 assert((Kind == k_Memory) && "Invalid access!");
1038 return Mem.Off;
1039 }
1040
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001041 int64_t getConstantMemOff() const {
1042 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1043 }
1044
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001045 const SmallVectorImpl<unsigned> &getRegList() const {
1046 assert((Kind == k_RegList) && "Invalid access!");
1047 return *(RegList.List);
1048 }
1049
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001050 unsigned getRegPair() const {
1051 assert((Kind == k_RegPair) && "Invalid access!");
1052 return RegIdx.Index;
1053 }
1054
David Blaikie960ea3f2014-06-08 16:18:35 +00001055 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1056 MipsAsmParser &Parser) {
1057 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001058 Op->Tok.Data = Str.data();
1059 Op->Tok.Length = Str.size();
1060 Op->StartLoc = S;
1061 Op->EndLoc = S;
1062 return Op;
1063 }
1064
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001065 /// Create a numeric register (e.g. $1). The exact register remains
1066 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001067 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001068 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001069 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001070 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001071 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001072 }
1073
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001074 /// Create a register that is definitely a GPR.
1075 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001076 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001077 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001078 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001079 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001080 }
1081
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001082 /// Create a register that is definitely a FGR.
1083 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001084 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001085 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001086 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001087 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1088 }
1089
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001090 /// Create a register that is definitely a HWReg.
1091 /// This is typically only used for named registers such as $hwr_cpunum.
1092 static std::unique_ptr<MipsOperand>
1093 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1094 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1095 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1096 }
1097
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001098 /// Create a register that is definitely an FCC.
1099 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001100 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001101 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001102 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001103 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1104 }
1105
1106 /// Create a register that is definitely an ACC.
1107 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001108 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001109 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001110 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001111 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1112 }
1113
1114 /// Create a register that is definitely an MSA128.
1115 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001116 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001117 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001118 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001119 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1120 }
1121
1122 /// Create a register that is definitely an MSACtrl.
1123 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001124 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001125 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001126 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001127 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1128 }
1129
David Blaikie960ea3f2014-06-08 16:18:35 +00001130 static std::unique_ptr<MipsOperand>
1131 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1132 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001133 Op->Imm.Val = Val;
1134 Op->StartLoc = S;
1135 Op->EndLoc = E;
1136 return Op;
1137 }
1138
David Blaikie960ea3f2014-06-08 16:18:35 +00001139 static std::unique_ptr<MipsOperand>
1140 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1141 SMLoc E, MipsAsmParser &Parser) {
1142 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1143 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001144 Op->Mem.Off = Off;
1145 Op->StartLoc = S;
1146 Op->EndLoc = E;
1147 return Op;
1148 }
1149
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001150 static std::unique_ptr<MipsOperand>
1151 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1152 MipsAsmParser &Parser) {
1153 assert (Regs.size() > 0 && "Empty list not allowed");
1154
1155 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001156 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001157 Op->StartLoc = StartLoc;
1158 Op->EndLoc = EndLoc;
1159 return Op;
1160 }
1161
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001162 static std::unique_ptr<MipsOperand>
1163 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1164 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1165 Op->RegIdx.Index = RegNo;
1166 Op->StartLoc = S;
1167 Op->EndLoc = E;
1168 return Op;
1169 }
1170
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001171 bool isGPRAsmReg() const {
1172 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001173 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001174 bool isMM16AsmReg() const {
1175 if (!(isRegIdx() && RegIdx.Kind))
1176 return false;
1177 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1178 || RegIdx.Index == 16 || RegIdx.Index == 17);
1179 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001180 bool isMM16AsmRegZero() const {
1181 if (!(isRegIdx() && RegIdx.Kind))
1182 return false;
1183 return (RegIdx.Index == 0 ||
1184 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1185 RegIdx.Index == 17);
1186 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001187 bool isMM16AsmRegMoveP() const {
1188 if (!(isRegIdx() && RegIdx.Kind))
1189 return false;
1190 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1191 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1192 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001193 bool isFGRAsmReg() const {
1194 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1195 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001196 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001197 bool isHWRegsAsmReg() const {
1198 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001199 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001200 bool isCCRAsmReg() const {
1201 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001202 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001203 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001204 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1205 return false;
1206 if (!AsmParser.hasEightFccRegisters())
1207 return RegIdx.Index == 0;
1208 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001209 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001210 bool isACCAsmReg() const {
1211 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001212 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001213 bool isCOP0AsmReg() const {
1214 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1215 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001216 bool isCOP2AsmReg() const {
1217 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001218 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001219 bool isCOP3AsmReg() const {
1220 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1221 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001222 bool isMSA128AsmReg() const {
1223 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001224 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001225 bool isMSACtrlAsmReg() const {
1226 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001227 }
1228
Jack Carterb4dbc172012-09-05 23:34:03 +00001229 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001230 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001231 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001232 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001233
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001234 virtual ~MipsOperand() {
1235 switch (Kind) {
1236 case k_Immediate:
1237 break;
1238 case k_Memory:
1239 delete Mem.Base;
1240 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001241 case k_RegList:
1242 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001243 case k_PhysRegister:
1244 case k_RegisterIndex:
1245 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001246 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001247 break;
1248 }
1249 }
1250
Craig Topper56c590a2014-04-29 07:58:02 +00001251 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001252 switch (Kind) {
1253 case k_Immediate:
1254 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001255 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001256 OS << ">";
1257 break;
1258 case k_Memory:
1259 OS << "Mem<";
1260 Mem.Base->print(OS);
1261 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001262 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001263 OS << ">";
1264 break;
1265 case k_PhysRegister:
1266 OS << "PhysReg<" << PhysReg.Num << ">";
1267 break;
1268 case k_RegisterIndex:
1269 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1270 break;
1271 case k_Token:
1272 OS << Tok.Data;
1273 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001274 case k_RegList:
1275 OS << "RegList< ";
1276 for (auto Reg : (*RegList.List))
1277 OS << Reg << " ";
1278 OS << ">";
1279 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001280 case k_RegPair:
1281 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1282 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001283 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001284 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001285}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001286} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001287
Jack Carter9e65aa32013-03-22 00:05:30 +00001288namespace llvm {
1289extern const MCInstrDesc MipsInsts[];
1290}
1291static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1292 return MipsInsts[Opcode];
1293}
1294
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001295static bool hasShortDelaySlot(unsigned Opcode) {
1296 switch (Opcode) {
1297 case Mips::JALS_MM:
1298 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001299 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001300 case Mips::BGEZALS_MM:
1301 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001302 return true;
1303 default:
1304 return false;
1305 }
1306}
1307
Jack Carter9e65aa32013-03-22 00:05:30 +00001308bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001309 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001310 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001311
Jack Carter9e65aa32013-03-22 00:05:30 +00001312 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001313
1314 if (MCID.isBranch() || MCID.isCall()) {
1315 const unsigned Opcode = Inst.getOpcode();
1316 MCOperand Offset;
1317
1318 switch (Opcode) {
1319 default:
1320 break;
Kai Nackee0245392015-01-27 19:11:28 +00001321 case Mips::BBIT0:
1322 case Mips::BBIT032:
1323 case Mips::BBIT1:
1324 case Mips::BBIT132:
1325 assert(hasCnMips() && "instruction only valid for octeon cpus");
1326 // Fall through
1327
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001328 case Mips::BEQ:
1329 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001330 case Mips::BEQ_MM:
1331 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001332 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001333 Offset = Inst.getOperand(2);
1334 if (!Offset.isImm())
1335 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001336 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001337 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001338 if (OffsetToAlignment(Offset.getImm(),
1339 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001340 return Error(IDLoc, "branch to misaligned address");
1341 break;
1342 case Mips::BGEZ:
1343 case Mips::BGTZ:
1344 case Mips::BLEZ:
1345 case Mips::BLTZ:
1346 case Mips::BGEZAL:
1347 case Mips::BLTZAL:
1348 case Mips::BC1F:
1349 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001350 case Mips::BGEZ_MM:
1351 case Mips::BGTZ_MM:
1352 case Mips::BLEZ_MM:
1353 case Mips::BLTZ_MM:
1354 case Mips::BGEZAL_MM:
1355 case Mips::BLTZAL_MM:
1356 case Mips::BC1F_MM:
1357 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001358 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001359 Offset = Inst.getOperand(1);
1360 if (!Offset.isImm())
1361 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001362 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001363 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001364 if (OffsetToAlignment(Offset.getImm(),
1365 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001366 return Error(IDLoc, "branch to misaligned address");
1367 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001368 case Mips::BEQZ16_MM:
1369 case Mips::BNEZ16_MM:
1370 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1371 Offset = Inst.getOperand(1);
1372 if (!Offset.isImm())
1373 break; // We'll deal with this situation later on when applying fixups.
1374 if (!isIntN(8, Offset.getImm()))
1375 return Error(IDLoc, "branch target out of range");
1376 if (OffsetToAlignment(Offset.getImm(), 2LL))
1377 return Error(IDLoc, "branch to misaligned address");
1378 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001379 }
1380 }
1381
Daniel Sandersa84989a2014-06-16 13:25:35 +00001382 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1383 // We still accept it but it is a normal nop.
1384 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1385 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1386 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1387 "nop instruction");
1388 }
1389
Kai Nackee0245392015-01-27 19:11:28 +00001390 if (hasCnMips()) {
1391 const unsigned Opcode = Inst.getOpcode();
1392 MCOperand Opnd;
1393 int Imm;
1394
1395 switch (Opcode) {
1396 default:
1397 break;
1398
1399 case Mips::BBIT0:
1400 case Mips::BBIT032:
1401 case Mips::BBIT1:
1402 case Mips::BBIT132:
1403 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1404 // The offset is handled above
1405 Opnd = Inst.getOperand(1);
1406 if (!Opnd.isImm())
1407 return Error(IDLoc, "expected immediate operand kind");
1408 Imm = Opnd.getImm();
1409 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1410 Opcode == Mips::BBIT1 ? 63 : 31))
1411 return Error(IDLoc, "immediate operand value out of range");
1412 if (Imm > 31) {
1413 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1414 : Mips::BBIT132);
1415 Inst.getOperand(1).setImm(Imm - 32);
1416 }
1417 break;
1418
1419 case Mips::CINS:
1420 case Mips::CINS32:
1421 case Mips::EXTS:
1422 case Mips::EXTS32:
1423 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1424 // Check length
1425 Opnd = Inst.getOperand(3);
1426 if (!Opnd.isImm())
1427 return Error(IDLoc, "expected immediate operand kind");
1428 Imm = Opnd.getImm();
1429 if (Imm < 0 || Imm > 31)
1430 return Error(IDLoc, "immediate operand value out of range");
1431 // Check position
1432 Opnd = Inst.getOperand(2);
1433 if (!Opnd.isImm())
1434 return Error(IDLoc, "expected immediate operand kind");
1435 Imm = Opnd.getImm();
1436 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1437 Opcode == Mips::EXTS ? 63 : 31))
1438 return Error(IDLoc, "immediate operand value out of range");
1439 if (Imm > 31) {
1440 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1441 Inst.getOperand(2).setImm(Imm - 32);
1442 }
1443 break;
1444
1445 case Mips::SEQi:
1446 case Mips::SNEi:
1447 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1448 Opnd = Inst.getOperand(2);
1449 if (!Opnd.isImm())
1450 return Error(IDLoc, "expected immediate operand kind");
1451 Imm = Opnd.getImm();
1452 if (!isInt<10>(Imm))
1453 return Error(IDLoc, "immediate operand value out of range");
1454 break;
1455 }
1456 }
1457
Jack Carter9e65aa32013-03-22 00:05:30 +00001458 if (MCID.mayLoad() || MCID.mayStore()) {
1459 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001460 // reference or immediate we may have to expand instructions.
1461 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001462 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001463 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1464 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001465 MCOperand &Op = Inst.getOperand(i);
1466 if (Op.isImm()) {
1467 int MemOffset = Op.getImm();
1468 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001469 // Offset can't exceed 16bit value.
1470 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001471 return false;
1472 }
1473 } else if (Op.isExpr()) {
1474 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001475 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001476 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001477 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001478 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001479 // Expand symbol.
1480 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001481 return false;
1482 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001483 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001484 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001485 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001486 }
1487 }
1488 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001489 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001490 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001491
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001492 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001493 if (MCID.mayLoad()) {
1494 // Try to create 16-bit GP relative load instruction.
1495 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1496 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1497 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1498 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1499 MCOperand &Op = Inst.getOperand(i);
1500 if (Op.isImm()) {
1501 int MemOffset = Op.getImm();
1502 MCOperand &DstReg = Inst.getOperand(0);
1503 MCOperand &BaseReg = Inst.getOperand(1);
1504 if (isIntN(9, MemOffset) && (MemOffset % 4 == 0) &&
1505 getContext().getRegisterInfo()->getRegClass(
1506 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
1507 BaseReg.getReg() == Mips::GP) {
1508 MCInst TmpInst;
1509 TmpInst.setLoc(IDLoc);
1510 TmpInst.setOpcode(Mips::LWGP_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00001511 TmpInst.addOperand(MCOperand::createReg(DstReg.getReg()));
1512 TmpInst.addOperand(MCOperand::createReg(Mips::GP));
1513 TmpInst.addOperand(MCOperand::createImm(MemOffset));
Jozef Koleke10a02e2015-01-28 17:27:26 +00001514 Instructions.push_back(TmpInst);
1515 return false;
1516 }
1517 }
1518 }
1519 } // for
1520 } // if load
1521
1522 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1523
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001524 MCOperand Opnd;
1525 int Imm;
1526
1527 switch (Inst.getOpcode()) {
1528 default:
1529 break;
1530 case Mips::ADDIUS5_MM:
1531 Opnd = Inst.getOperand(2);
1532 if (!Opnd.isImm())
1533 return Error(IDLoc, "expected immediate operand kind");
1534 Imm = Opnd.getImm();
1535 if (Imm < -8 || Imm > 7)
1536 return Error(IDLoc, "immediate operand value out of range");
1537 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001538 case Mips::ADDIUSP_MM:
1539 Opnd = Inst.getOperand(0);
1540 if (!Opnd.isImm())
1541 return Error(IDLoc, "expected immediate operand kind");
1542 Imm = Opnd.getImm();
1543 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1544 Imm % 4 != 0)
1545 return Error(IDLoc, "immediate operand value out of range");
1546 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001547 case Mips::SLL16_MM:
1548 case Mips::SRL16_MM:
1549 Opnd = Inst.getOperand(2);
1550 if (!Opnd.isImm())
1551 return Error(IDLoc, "expected immediate operand kind");
1552 Imm = Opnd.getImm();
1553 if (Imm < 1 || Imm > 8)
1554 return Error(IDLoc, "immediate operand value out of range");
1555 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001556 case Mips::LI16_MM:
1557 Opnd = Inst.getOperand(1);
1558 if (!Opnd.isImm())
1559 return Error(IDLoc, "expected immediate operand kind");
1560 Imm = Opnd.getImm();
1561 if (Imm < -1 || Imm > 126)
1562 return Error(IDLoc, "immediate operand value out of range");
1563 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001564 case Mips::ADDIUR2_MM:
1565 Opnd = Inst.getOperand(2);
1566 if (!Opnd.isImm())
1567 return Error(IDLoc, "expected immediate operand kind");
1568 Imm = Opnd.getImm();
1569 if (!(Imm == 1 || Imm == -1 ||
1570 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1571 return Error(IDLoc, "immediate operand value out of range");
1572 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001573 case Mips::ADDIUR1SP_MM:
1574 Opnd = Inst.getOperand(1);
1575 if (!Opnd.isImm())
1576 return Error(IDLoc, "expected immediate operand kind");
1577 Imm = Opnd.getImm();
1578 if (OffsetToAlignment(Imm, 4LL))
1579 return Error(IDLoc, "misaligned immediate operand value");
1580 if (Imm < 0 || Imm > 255)
1581 return Error(IDLoc, "immediate operand value out of range");
1582 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001583 case Mips::ANDI16_MM:
1584 Opnd = Inst.getOperand(2);
1585 if (!Opnd.isImm())
1586 return Error(IDLoc, "expected immediate operand kind");
1587 Imm = Opnd.getImm();
1588 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1589 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1590 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1591 return Error(IDLoc, "immediate operand value out of range");
1592 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001593 case Mips::LBU16_MM:
1594 Opnd = Inst.getOperand(2);
1595 if (!Opnd.isImm())
1596 return Error(IDLoc, "expected immediate operand kind");
1597 Imm = Opnd.getImm();
1598 if (Imm < -1 || Imm > 14)
1599 return Error(IDLoc, "immediate operand value out of range");
1600 break;
1601 case Mips::SB16_MM:
1602 Opnd = Inst.getOperand(2);
1603 if (!Opnd.isImm())
1604 return Error(IDLoc, "expected immediate operand kind");
1605 Imm = Opnd.getImm();
1606 if (Imm < 0 || Imm > 15)
1607 return Error(IDLoc, "immediate operand value out of range");
1608 break;
1609 case Mips::LHU16_MM:
1610 case Mips::SH16_MM:
1611 Opnd = Inst.getOperand(2);
1612 if (!Opnd.isImm())
1613 return Error(IDLoc, "expected immediate operand kind");
1614 Imm = Opnd.getImm();
1615 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1616 return Error(IDLoc, "immediate operand value out of range");
1617 break;
1618 case Mips::LW16_MM:
1619 case Mips::SW16_MM:
1620 Opnd = Inst.getOperand(2);
1621 if (!Opnd.isImm())
1622 return Error(IDLoc, "expected immediate operand kind");
1623 Imm = Opnd.getImm();
1624 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1625 return Error(IDLoc, "immediate operand value out of range");
1626 break;
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001627 case Mips::CACHE:
1628 case Mips::PREF:
1629 Opnd = Inst.getOperand(2);
1630 if (!Opnd.isImm())
1631 return Error(IDLoc, "expected immediate operand kind");
1632 Imm = Opnd.getImm();
1633 if (!isUInt<5>(Imm))
1634 return Error(IDLoc, "immediate operand value out of range");
1635 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001636 case Mips::ADDIUPC_MM:
1637 MCOperand Opnd = Inst.getOperand(1);
1638 if (!Opnd.isImm())
1639 return Error(IDLoc, "expected immediate operand kind");
1640 int Imm = Opnd.getImm();
1641 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1642 return Error(IDLoc, "immediate operand value out of range");
1643 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001644 }
1645 }
1646
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001647 if (needsExpansion(Inst)) {
1648 if (expandInstruction(Inst, IDLoc, Instructions))
1649 return true;
1650 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001651 Instructions.push_back(Inst);
1652
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001653 // If this instruction has a delay slot and .set reorder is active,
1654 // emit a NOP after it.
1655 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1656 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1657
Jack Carter9e65aa32013-03-22 00:05:30 +00001658 return false;
1659}
1660
Jack Carter30a59822012-10-04 04:03:53 +00001661bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1662
Jack Carterd0bd6422013-04-18 00:41:53 +00001663 switch (Inst.getOpcode()) {
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001664 case Mips::LoadImm32:
1665 case Mips::LoadImm64:
1666 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001667 case Mips::LoadAddrImm64:
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001668 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001669 case Mips::LoadAddrReg64:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001670 case Mips::B_MM_Pseudo:
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001671 case Mips::LWM_MM:
1672 case Mips::SWM_MM:
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001673 case Mips::JalOneReg:
1674 case Mips::JalTwoReg:
Toma Tabacue1e460d2015-06-11 10:36:10 +00001675 case Mips::BneImm:
1676 case Mips::BeqImm:
Toma Tabacu1a108322015-06-17 13:20:24 +00001677 case Mips::BLT:
1678 case Mips::BLE:
1679 case Mips::BGE:
1680 case Mips::BGT:
1681 case Mips::BLTU:
1682 case Mips::BLEU:
1683 case Mips::BGEU:
1684 case Mips::BGTU:
Toma Tabacud88d79c2015-06-23 14:39:42 +00001685 case Mips::Ulhu:
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00001686 case Mips::Ulw:
Jack Carterd0bd6422013-04-18 00:41:53 +00001687 return true;
1688 default:
1689 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001690 }
1691}
Jack Carter92995f12012-10-06 00:53:28 +00001692
Matheus Almeida3813d572014-06-19 14:39:14 +00001693bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001694 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001695 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001696 default: llvm_unreachable("unimplemented expansion");
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001697 case Mips::LoadImm32:
Toma Tabacu00e98672015-05-01 12:19:27 +00001698 return expandLoadImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001699 case Mips::LoadImm64:
Toma Tabacu00e98672015-05-01 12:19:27 +00001700 return expandLoadImm(Inst, false, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001701 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001702 case Mips::LoadAddrImm64:
1703 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1704 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1705 "expected immediate operand kind");
1706
1707 return expandLoadAddress(
1708 Inst.getOperand(0).getReg(), Mips::NoRegister, Inst.getOperand(1),
1709 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001710 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001711 case Mips::LoadAddrReg64:
1712 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1713 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1714 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
1715 "expected immediate operand kind");
1716
1717 return expandLoadAddress(
1718 Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(), Inst.getOperand(2),
1719 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001720 case Mips::B_MM_Pseudo:
1721 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001722 case Mips::SWM_MM:
1723 case Mips::LWM_MM:
1724 return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001725 case Mips::JalOneReg:
1726 case Mips::JalTwoReg:
1727 return expandJalWithRegs(Inst, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00001728 case Mips::BneImm:
1729 case Mips::BeqImm:
1730 return expandBranchImm(Inst, IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00001731 case Mips::BLT:
1732 case Mips::BLE:
1733 case Mips::BGE:
1734 case Mips::BGT:
1735 case Mips::BLTU:
1736 case Mips::BLEU:
1737 case Mips::BGEU:
1738 case Mips::BGTU:
1739 return expandCondBranches(Inst, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00001740 case Mips::Ulhu:
1741 return expandUlhu(Inst, IDLoc, Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00001742 case Mips::Ulw:
1743 return expandUlw(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001744 }
Jack Carter30a59822012-10-04 04:03:53 +00001745}
Jack Carter92995f12012-10-06 00:53:28 +00001746
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001747namespace {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001748void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc,
Daniel Sanders03f9c012015-07-14 12:24:22 +00001749 SmallVectorImpl<MCInst> &Instructions) {
1750 MCInst tmpInst;
1751 tmpInst.setOpcode(Opcode);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001752 tmpInst.addOperand(MCOperand::createReg(Reg0));
1753 tmpInst.addOperand(Op1);
Daniel Sanders03f9c012015-07-14 12:24:22 +00001754 tmpInst.setLoc(IDLoc);
1755 Instructions.push_back(tmpInst);
1756}
1757
Daniel Sandersf1ae3672015-08-18 09:55:57 +00001758void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc,
Daniel Sanders03f9c012015-07-14 12:24:22 +00001759 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001760 emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00001761}
1762
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001763void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2,
Daniel Sanders03f9c012015-07-14 12:24:22 +00001764 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1765 MCInst tmpInst;
1766 tmpInst.setOpcode(Opcode);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001767 tmpInst.addOperand(MCOperand::createReg(Reg0));
1768 tmpInst.addOperand(MCOperand::createReg(Reg1));
1769 tmpInst.addOperand(Op2);
Daniel Sanders03f9c012015-07-14 12:24:22 +00001770 tmpInst.setLoc(IDLoc);
1771 Instructions.push_back(tmpInst);
1772}
1773
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001774void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
Daniel Sanders03f9c012015-07-14 12:24:22 +00001775 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001776 emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc,
Daniel Sanders03f9c012015-07-14 12:24:22 +00001777 Instructions);
1778}
1779
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001780void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
1781 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1782 emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc,
1783 Instructions);
1784}
Daniel Sanders03f9c012015-07-14 12:24:22 +00001785
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001786void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount,
1787 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1788 if (ShiftAmount >= 32) {
1789 emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc,
1790 Instructions);
Toma Tabacu7dea2e32015-04-28 14:06:35 +00001791 return;
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001792 }
Toma Tabacu7dea2e32015-04-28 14:06:35 +00001793
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001794 emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001795}
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001796} // end anonymous namespace.
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001797
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001798bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
1799 SmallVectorImpl<MCInst> &Instructions) {
1800 // Create a JALR instruction which is going to replace the pseudo-JAL.
1801 MCInst JalrInst;
1802 JalrInst.setLoc(IDLoc);
1803 const MCOperand FirstRegOp = Inst.getOperand(0);
1804 const unsigned Opcode = Inst.getOpcode();
1805
1806 if (Opcode == Mips::JalOneReg) {
1807 // jal $rs => jalr $rs
1808 if (inMicroMipsMode()) {
1809 JalrInst.setOpcode(Mips::JALR16_MM);
1810 JalrInst.addOperand(FirstRegOp);
1811 } else {
1812 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00001813 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001814 JalrInst.addOperand(FirstRegOp);
1815 }
1816 } else if (Opcode == Mips::JalTwoReg) {
1817 // jal $rd, $rs => jalr $rd, $rs
1818 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
1819 JalrInst.addOperand(FirstRegOp);
1820 const MCOperand SecondRegOp = Inst.getOperand(1);
1821 JalrInst.addOperand(SecondRegOp);
1822 }
1823 Instructions.push_back(JalrInst);
1824
1825 // If .set reorder is active, emit a NOP after it.
1826 if (AssemblerOptions.back()->isReorder()) {
1827 // This is a 32-bit NOP because these 2 pseudo-instructions
1828 // do not have a short delay slot.
1829 MCInst NopInst;
1830 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00001831 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
1832 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
1833 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001834 Instructions.push_back(NopInst);
1835 }
1836
1837 return false;
1838}
1839
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001840/// Can the value be represented by a unsigned N-bit value and a shift left?
1841template<unsigned N>
1842bool isShiftedUIntAtAnyPosition(uint64_t x) {
1843 unsigned BitNum = findFirstSet(x);
1844
1845 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
1846}
1847
1848/// Load (or add) an immediate into a register.
1849///
1850/// @param ImmValue The immediate to load.
1851/// @param DstReg The register that will hold the immediate.
1852/// @param SrcReg A register to add to the immediate or Mips::NoRegister
1853/// for a simple initialization.
1854/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
1855/// @param IsAddress True if the immediate represents an address. False if it
1856/// is an integer.
1857/// @param IDLoc Location of the immediate in the source file.
1858/// @param Instructions The instructions emitted by this expansion.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001859bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001860 unsigned SrcReg, bool Is32BitImm,
1861 bool IsAddress, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001862 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00001863 if (!Is32BitImm && !isGP64bit()) {
1864 Error(IDLoc, "instruction requires a 64-bit architecture");
1865 return true;
1866 }
1867
Daniel Sanders03f9c012015-07-14 12:24:22 +00001868 if (Is32BitImm) {
1869 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
1870 // Sign extend up to 64-bit so that the predicates match the hardware
1871 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
1872 // true.
1873 ImmValue = SignExtend64<32>(ImmValue);
1874 } else {
1875 Error(IDLoc, "instruction requires a 32-bit immediate");
1876 return true;
1877 }
1878 }
1879
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001880 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
1881 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
1882
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001883 bool UseSrcReg = false;
1884 if (SrcReg != Mips::NoRegister)
1885 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00001886
Toma Tabacu8e0316d2015-06-22 13:10:23 +00001887 unsigned TmpReg = DstReg;
1888 if (UseSrcReg && (DstReg == SrcReg)) {
1889 // At this point we need AT to perform the expansions and we exit if it is
1890 // not available.
1891 unsigned ATReg = getATReg(IDLoc);
1892 if (!ATReg)
1893 return true;
1894 TmpReg = ATReg;
1895 }
1896
Daniel Sanders03f9c012015-07-14 12:24:22 +00001897 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00001898 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001899 SrcReg = ZeroReg;
1900
1901 // This doesn't quite follow the usual ABI expectations for N32 but matches
1902 // traditional assembler behaviour. N32 would normally use addiu for both
1903 // integers and addresses.
1904 if (IsAddress && !Is32BitImm) {
1905 emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
1906 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00001907 }
1908
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001909 emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
1910 return false;
1911 }
1912
1913 if (isUInt<16>(ImmValue)) {
1914 unsigned TmpReg = DstReg;
1915 if (SrcReg == DstReg) {
1916 TmpReg = getATReg(IDLoc);
1917 if (!TmpReg)
1918 return true;
1919 }
1920
1921 emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00001922 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001923 emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, Instructions);
1924 return false;
1925 }
1926
1927 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00001928 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00001929
Toma Tabacu79588102015-04-29 10:19:56 +00001930 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1931 uint16_t Bits15To0 = ImmValue & 0xffff;
1932
Toma Tabacua3d056f2015-05-15 09:42:11 +00001933 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001934 // Traditional behaviour seems to special case this particular value. It's
1935 // not clear why other masks are handled differently.
1936 if (ImmValue == 0xffffffff) {
Daniel Sandersf1ae3672015-08-18 09:55:57 +00001937 emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001938 emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, Instructions);
1939 if (UseSrcReg)
1940 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
1941 return false;
1942 }
1943
1944 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00001945 // upper 32 bits.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001946 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00001947 emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001948 if (Bits15To0)
1949 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
1950 if (UseSrcReg)
1951 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
1952 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00001953 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001954
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001955 emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions);
1956 if (Bits15To0)
1957 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001958 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001959 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
1960 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001961 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001962
1963 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
1964 if (Is32BitImm) {
1965 Error(IDLoc, "instruction requires a 32-bit immediate");
1966 return true;
1967 }
1968
1969 // Traditionally, these immediates are shifted as little as possible and as
1970 // such we align the most significant bit to bit 15 of our temporary.
1971 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
1972 unsigned LastSet = findLastSet((uint64_t)ImmValue);
1973 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
1974 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
1975 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, Instructions);
1976 emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, Instructions);
1977
1978 if (UseSrcReg)
1979 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
1980
1981 return false;
1982 }
1983
1984 warnIfNoMacro(IDLoc);
1985
1986 // The remaining case is packed with a sequence of dsll and ori with zeros
1987 // being omitted and any neighbouring dsll's being coalesced.
1988 // The highest 32-bit's are equivalent to a 32-bit immediate load.
1989
1990 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
1991 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
1992 IDLoc, Instructions))
1993 return false;
1994
1995 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
1996 // skip it and defer the shift to the next chunk.
1997 unsigned ShiftCarriedForwards = 16;
1998 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
1999 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2000
2001 if (ImmChunk != 0) {
2002 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2003 Instructions);
2004 emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, Instructions);
2005 ShiftCarriedForwards = 0;
2006 }
2007
2008 ShiftCarriedForwards += 16;
2009 }
2010 ShiftCarriedForwards -= 16;
2011
2012 // Finish any remaining shifts left by trailing zeros.
2013 if (ShiftCarriedForwards)
2014 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2015 Instructions);
2016
2017 if (UseSrcReg)
2018 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2019
Matheus Almeida3813d572014-06-19 14:39:14 +00002020 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002021}
Jack Carter92995f12012-10-06 00:53:28 +00002022
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002023bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
2024 SmallVectorImpl<MCInst> &Instructions) {
2025 const MCOperand &ImmOp = Inst.getOperand(1);
2026 assert(ImmOp.isImm() && "expected immediate operand kind");
2027 const MCOperand &DstRegOp = Inst.getOperand(0);
2028 assert(DstRegOp.isReg() && "expected register operand kind");
2029
2030 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002031 Is32BitImm, false, IDLoc, Instructions))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002032 return true;
2033
2034 return false;
2035}
2036
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002037bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2038 const MCOperand &Offset,
2039 bool Is32BitAddress, SMLoc IDLoc,
2040 SmallVectorImpl<MCInst> &Instructions) {
2041 // la can't produce a usable address when addresses are 64-bit.
2042 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2043 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2044 // We currently can't do this because we depend on the equality
2045 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2046 Error(IDLoc, "la used to load 64-bit address");
2047 // Continue as if we had 'dla' instead.
2048 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002049 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002050
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002051 // dla requires 64-bit addresses.
2052 if (!Is32BitAddress && !ABI.ArePtrs64bit()) {
2053 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002054 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002055 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002056
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002057 if (!Offset.isImm())
2058 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
2059 Is32BitAddress, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002060
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002061 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
2062 IDLoc, Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +00002063}
2064
Toma Tabacuf712ede2015-06-17 14:31:51 +00002065bool MipsAsmParser::loadAndAddSymbolAddress(
2066 const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
2067 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002068 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002069
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002070 // FIXME: The way we're handling symbols right now prevents simple expressions
2071 // like foo+8. We'll be able to fix this once our unary operators (%hi
2072 // and similar) are treated as operators rather than as fixup types.
Toma Tabacu674825c2015-06-16 12:16:24 +00002073 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymExpr);
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002074 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::create(
2075 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
2076 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::create(
2077 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
2078
Toma Tabacufb9d1252015-06-22 12:08:39 +00002079 bool UseSrcReg = SrcReg != Mips::NoRegister;
2080
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002081 // This is the 64-bit symbol address expansion.
2082 if (ABI.ArePtrs64bit() && isGP64bit()) {
2083 // We always need AT for the 64-bit expansion.
2084 // If it is not available we exit.
2085 unsigned ATReg = getATReg(IDLoc);
2086 if (!ATReg)
2087 return true;
2088
2089 const MCSymbolRefExpr *HighestExpr = MCSymbolRefExpr::create(
2090 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
2091 const MCSymbolRefExpr *HigherExpr = MCSymbolRefExpr::create(
2092 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
2093
2094 if (UseSrcReg && (DstReg == SrcReg)) {
2095 // If $rs is the same as $rd:
2096 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2097 // daddiu $at, $at, %higher(sym)
2098 // dsll $at, $at, 16
2099 // daddiu $at, $at, %hi(sym)
2100 // dsll $at, $at, 16
2101 // daddiu $at, $at, %lo(sym)
2102 // daddu $rd, $at, $rd
2103 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2104 Instructions);
2105 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr),
2106 IDLoc, Instructions);
2107 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2108 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2109 Instructions);
2110 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2111 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2112 Instructions);
2113 emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions);
2114
2115 return false;
2116 }
2117
2118 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2119 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2120 // lui $at, %hi(sym)
2121 // daddiu $rd, $rd, %higher(sym)
2122 // daddiu $at, $at, %lo(sym)
2123 // dsll32 $rd, $rd, 0
2124 // daddu $rd, $rd, $at
2125 // (daddu $rd, $rd, $rs)
2126 emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2127 Instructions);
2128 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2129 Instructions);
2130 emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr),
2131 IDLoc, Instructions);
2132 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2133 Instructions);
2134 emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions);
2135 emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions);
2136 if (UseSrcReg)
2137 emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions);
2138
2139 return false;
2140 }
2141
2142 // And now, the 32-bit symbol address expansion:
2143 // If $rs is the same as $rd:
2144 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2145 // ori $at, $at, %lo(sym)
2146 // addu $rd, $at, $rd
2147 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2148 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2149 // ori $rd, $rd, %lo(sym)
2150 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002151 unsigned TmpReg = DstReg;
2152 if (UseSrcReg && (DstReg == SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002153 // If $rs is the same as $rd, we need to use AT.
2154 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002155 unsigned ATReg = getATReg(IDLoc);
2156 if (!ATReg)
2157 return true;
2158 TmpReg = ATReg;
2159 }
2160
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002161 emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions);
2162 emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc,
2163 Instructions);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002164
Toma Tabacufb9d1252015-06-22 12:08:39 +00002165 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002166 emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2167 else
2168 assert(DstReg == TmpReg);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002169
Toma Tabacu674825c2015-06-16 12:16:24 +00002170 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002171}
2172
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002173bool MipsAsmParser::expandUncondBranchMMPseudo(
2174 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002175 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2176 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002177
2178 MCOperand Offset = Inst.getOperand(0);
2179 if (Offset.isExpr()) {
2180 Inst.clear();
2181 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002182 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2183 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2184 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002185 } else {
2186 assert(Offset.isImm() && "expected immediate operand kind");
2187 if (isIntN(11, Offset.getImm())) {
2188 // If offset fits into 11 bits then this instruction becomes microMIPS
2189 // 16-bit unconditional branch instruction.
2190 Inst.setOpcode(Mips::B16_MM);
2191 } else {
2192 if (!isIntN(17, Offset.getImm()))
2193 Error(IDLoc, "branch target out of range");
2194 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2195 Error(IDLoc, "branch to misaligned address");
2196 Inst.clear();
2197 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002198 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2199 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2200 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002201 }
2202 }
2203 Instructions.push_back(Inst);
2204
Toma Tabacu234482a2015-03-16 12:03:39 +00002205 // If .set reorder is active, emit a NOP after the branch instruction.
2206 if (AssemblerOptions.back()->isReorder())
2207 createNop(true, IDLoc, Instructions);
2208
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002209 return false;
2210}
2211
Toma Tabacue1e460d2015-06-11 10:36:10 +00002212bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2213 SmallVectorImpl<MCInst> &Instructions) {
2214 const MCOperand &DstRegOp = Inst.getOperand(0);
2215 assert(DstRegOp.isReg() && "expected register operand kind");
2216
2217 const MCOperand &ImmOp = Inst.getOperand(1);
2218 assert(ImmOp.isImm() && "expected immediate operand kind");
2219
2220 const MCOperand &MemOffsetOp = Inst.getOperand(2);
2221 assert(MemOffsetOp.isImm() && "expected immediate operand kind");
2222
2223 unsigned OpCode = 0;
2224 switch(Inst.getOpcode()) {
2225 case Mips::BneImm:
2226 OpCode = Mips::BNE;
2227 break;
2228 case Mips::BeqImm:
2229 OpCode = Mips::BEQ;
2230 break;
2231 default:
2232 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2233 break;
2234 }
2235
2236 int64_t ImmValue = ImmOp.getImm();
2237 if (ImmValue == 0) {
2238 MCInst BranchInst;
2239 BranchInst.setOpcode(OpCode);
2240 BranchInst.addOperand(DstRegOp);
2241 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2242 BranchInst.addOperand(MemOffsetOp);
2243 Instructions.push_back(BranchInst);
2244 } else {
2245 warnIfNoMacro(IDLoc);
2246
2247 unsigned ATReg = getATReg(IDLoc);
2248 if (!ATReg)
2249 return true;
2250
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002251 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
2252 IDLoc, Instructions))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002253 return true;
2254
2255 MCInst BranchInst;
2256 BranchInst.setOpcode(OpCode);
2257 BranchInst.addOperand(DstRegOp);
2258 BranchInst.addOperand(MCOperand::createReg(ATReg));
2259 BranchInst.addOperand(MemOffsetOp);
2260 Instructions.push_back(BranchInst);
2261 }
2262 return false;
2263}
2264
Jack Carter9e65aa32013-03-22 00:05:30 +00002265void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002266 SmallVectorImpl<MCInst> &Instructions,
2267 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002268 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00002269 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002270 const MCExpr *ExprOffset;
2271 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002272 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002273 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2274 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002275 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002276 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2277 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002278 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002279 if (isImmOpnd) {
2280 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2281 ImmOffset = Inst.getOperand(2).getImm();
2282 LoOffset = ImmOffset & 0x0000ffff;
2283 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002284 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002285 if (LoOffset & 0x8000)
2286 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002287 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002288 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002289 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002290 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002291 // These are some of the types of expansions we perform here:
2292 // 1) lw $8, sym => lui $8, %hi(sym)
2293 // lw $8, %lo(sym)($8)
2294 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2295 // add $8, $8, $9
2296 // lw $8, %lo(offset)($9)
2297 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2298 // add $at, $at, $8
2299 // lw $8, %lo(offset)($at)
2300 // 4) sw $8, sym => lui $at, %hi(sym)
2301 // sw $8, %lo(sym)($at)
2302 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2303 // add $at, $at, $8
2304 // sw $8, %lo(offset)($at)
2305 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2306 // ldc1 $f0, %lo(sym)($at)
2307 //
2308 // For load instructions we can use the destination register as a temporary
2309 // if base and dst are different (examples 1 and 2) and if the base register
2310 // is general purpose otherwise we must use $at (example 6) and error if it's
2311 // not available. For stores we must use $at (examples 4 and 5) because we
2312 // must not clobber the source register setting up the offset.
2313 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2314 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2315 unsigned RegClassIDOp0 =
2316 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2317 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2318 (RegClassIDOp0 == Mips::GPR64RegClassID);
2319 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002320 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002321 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002322 // At this point we need AT to perform the expansions and we exit if it is
2323 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002324 TmpRegNum = getATReg(IDLoc);
2325 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002326 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002327 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002328
Jack Carter9e65aa32013-03-22 00:05:30 +00002329 TempInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00002330 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002331 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002332 TempInst.addOperand(MCOperand::createImm(HiOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002333 else {
Toma Tabacu07c97b32015-06-17 10:43:45 +00002334 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
2335 TempInst.addOperand(MCOperand::createExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002336 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002337 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002338 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002339 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002340 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002341 // Add temp register to base.
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002342 if (BaseRegNum != Mips::ZERO) {
2343 TempInst.setOpcode(Mips::ADDu);
Jim Grosbache9119e42015-05-13 18:37:00 +00002344 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2345 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2346 TempInst.addOperand(MCOperand::createReg(BaseRegNum));
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002347 Instructions.push_back(TempInst);
2348 TempInst.clear();
2349 }
Alp Tokercb402912014-01-24 17:20:08 +00002350 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002351 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002352 TempInst.setOpcode(Inst.getOpcode());
Jim Grosbache9119e42015-05-13 18:37:00 +00002353 TempInst.addOperand(MCOperand::createReg(RegOpNum));
2354 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002355 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002356 TempInst.addOperand(MCOperand::createImm(LoOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002357 else {
Toma Tabacu07c97b32015-06-17 10:43:45 +00002358 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
2359 TempInst.addOperand(MCOperand::createExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002360 }
2361 Instructions.push_back(TempInst);
2362 TempInst.clear();
2363}
2364
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002365bool
2366MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2367 SmallVectorImpl<MCInst> &Instructions) {
2368 unsigned OpNum = Inst.getNumOperands();
2369 unsigned Opcode = Inst.getOpcode();
2370 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2371
2372 assert (Inst.getOperand(OpNum - 1).isImm() &&
2373 Inst.getOperand(OpNum - 2).isReg() &&
2374 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2375
2376 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2377 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2378 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2379 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2380 // It can be implemented as SWM16 or LWM16 instruction.
2381 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2382
2383 Inst.setOpcode(NewOpcode);
2384 Instructions.push_back(Inst);
2385 return false;
2386}
2387
Toma Tabacu1a108322015-06-17 13:20:24 +00002388bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2389 SmallVectorImpl<MCInst> &Instructions) {
2390 unsigned PseudoOpcode = Inst.getOpcode();
2391 unsigned SrcReg = Inst.getOperand(0).getReg();
2392 unsigned TrgReg = Inst.getOperand(1).getReg();
2393 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2394
2395 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
2396 bool ReverseOrderSLT, IsUnsigned, AcceptsEquality;
2397
2398 switch (PseudoOpcode) {
2399 case Mips::BLT:
2400 case Mips::BLTU:
2401 AcceptsEquality = false;
2402 ReverseOrderSLT = false;
2403 IsUnsigned = (PseudoOpcode == Mips::BLTU);
2404 ZeroSrcOpcode = Mips::BGTZ;
2405 ZeroTrgOpcode = Mips::BLTZ;
2406 break;
2407 case Mips::BLE:
2408 case Mips::BLEU:
2409 AcceptsEquality = true;
2410 ReverseOrderSLT = true;
2411 IsUnsigned = (PseudoOpcode == Mips::BLEU);
2412 ZeroSrcOpcode = Mips::BGEZ;
2413 ZeroTrgOpcode = Mips::BLEZ;
2414 break;
2415 case Mips::BGE:
2416 case Mips::BGEU:
2417 AcceptsEquality = true;
2418 ReverseOrderSLT = false;
2419 IsUnsigned = (PseudoOpcode == Mips::BGEU);
2420 ZeroSrcOpcode = Mips::BLEZ;
2421 ZeroTrgOpcode = Mips::BGEZ;
2422 break;
2423 case Mips::BGT:
2424 case Mips::BGTU:
2425 AcceptsEquality = false;
2426 ReverseOrderSLT = true;
2427 IsUnsigned = (PseudoOpcode == Mips::BGTU);
2428 ZeroSrcOpcode = Mips::BLTZ;
2429 ZeroTrgOpcode = Mips::BGTZ;
2430 break;
2431 default:
2432 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2433 }
2434
2435 MCInst BranchInst;
2436 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2437 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2438 if (IsSrcRegZero && IsTrgRegZero) {
2439 // FIXME: All of these Opcode-specific if's are needed for compatibility
2440 // with GAS' behaviour. However, they may not generate the most efficient
2441 // code in some circumstances.
2442 if (PseudoOpcode == Mips::BLT) {
2443 BranchInst.setOpcode(Mips::BLTZ);
2444 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2445 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2446 Instructions.push_back(BranchInst);
2447 return false;
2448 }
2449 if (PseudoOpcode == Mips::BLE) {
2450 BranchInst.setOpcode(Mips::BLEZ);
2451 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2452 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2453 Instructions.push_back(BranchInst);
2454 Warning(IDLoc, "branch is always taken");
2455 return false;
2456 }
2457 if (PseudoOpcode == Mips::BGE) {
2458 BranchInst.setOpcode(Mips::BGEZ);
2459 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2460 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2461 Instructions.push_back(BranchInst);
2462 Warning(IDLoc, "branch is always taken");
2463 return false;
2464 }
2465 if (PseudoOpcode == Mips::BGT) {
2466 BranchInst.setOpcode(Mips::BGTZ);
2467 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2468 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2469 Instructions.push_back(BranchInst);
2470 return false;
2471 }
2472 if (PseudoOpcode == Mips::BGTU) {
2473 BranchInst.setOpcode(Mips::BNE);
2474 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2475 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2476 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2477 Instructions.push_back(BranchInst);
2478 return false;
2479 }
2480 if (AcceptsEquality) {
2481 // If both registers are $0 and the pseudo-branch accepts equality, it
2482 // will always be taken, so we emit an unconditional branch.
2483 BranchInst.setOpcode(Mips::BEQ);
2484 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2485 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2486 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2487 Instructions.push_back(BranchInst);
2488 Warning(IDLoc, "branch is always taken");
2489 return false;
2490 }
2491 // If both registers are $0 and the pseudo-branch does not accept
2492 // equality, it will never be taken, so we don't have to emit anything.
2493 return false;
2494 }
2495 if (IsSrcRegZero || IsTrgRegZero) {
2496 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2497 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2498 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2499 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2500 // the pseudo-branch will never be taken, so we don't emit anything.
2501 // This only applies to unsigned pseudo-branches.
2502 return false;
2503 }
2504 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2505 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2506 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2507 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2508 // the pseudo-branch will always be taken, so we emit an unconditional
2509 // branch.
2510 // This only applies to unsigned pseudo-branches.
2511 BranchInst.setOpcode(Mips::BEQ);
2512 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2513 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2514 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2515 Instructions.push_back(BranchInst);
2516 Warning(IDLoc, "branch is always taken");
2517 return false;
2518 }
2519 if (IsUnsigned) {
2520 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2521 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2522 // the pseudo-branch will be taken only when the non-zero register is
2523 // different from 0, so we emit a BNEZ.
2524 //
2525 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2526 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2527 // the pseudo-branch will be taken only when the non-zero register is
2528 // equal to 0, so we emit a BEQZ.
2529 //
2530 // Because only BLEU and BGEU branch on equality, we can use the
2531 // AcceptsEquality variable to decide when to emit the BEQZ.
2532 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQ : Mips::BNE);
2533 BranchInst.addOperand(
2534 MCOperand::createReg(IsSrcRegZero ? TrgReg : SrcReg));
2535 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2536 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2537 Instructions.push_back(BranchInst);
2538 return false;
2539 }
2540 // If we have a signed pseudo-branch and one of the registers is $0,
2541 // we can use an appropriate compare-to-zero branch. We select which one
2542 // to use in the switch statement above.
2543 BranchInst.setOpcode(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode);
2544 BranchInst.addOperand(MCOperand::createReg(IsSrcRegZero ? TrgReg : SrcReg));
2545 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2546 Instructions.push_back(BranchInst);
2547 return false;
2548 }
2549
2550 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2551 // expansions. If it is not available, we return.
2552 unsigned ATRegNum = getATReg(IDLoc);
2553 if (!ATRegNum)
2554 return true;
2555
2556 warnIfNoMacro(IDLoc);
2557
2558 // SLT fits well with 2 of our 4 pseudo-branches:
2559 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2560 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2561 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2562 // This is accomplished by using a BNEZ with the result of the SLT.
2563 //
2564 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2565 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2566 // Because only BGE and BLE branch on equality, we can use the
2567 // AcceptsEquality variable to decide when to emit the BEQZ.
2568 // Note that the order of the SLT arguments doesn't change between
2569 // opposites.
2570 //
2571 // The same applies to the unsigned variants, except that SLTu is used
2572 // instead of SLT.
2573 MCInst SetInst;
2574 SetInst.setOpcode(IsUnsigned ? Mips::SLTu : Mips::SLT);
2575 SetInst.addOperand(MCOperand::createReg(ATRegNum));
2576 SetInst.addOperand(MCOperand::createReg(ReverseOrderSLT ? TrgReg : SrcReg));
2577 SetInst.addOperand(MCOperand::createReg(ReverseOrderSLT ? SrcReg : TrgReg));
2578 Instructions.push_back(SetInst);
2579
2580 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQ : Mips::BNE);
2581 BranchInst.addOperand(MCOperand::createReg(ATRegNum));
2582 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2583 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2584 Instructions.push_back(BranchInst);
2585 return false;
2586}
2587
Toma Tabacud88d79c2015-06-23 14:39:42 +00002588bool MipsAsmParser::expandUlhu(MCInst &Inst, SMLoc IDLoc,
2589 SmallVectorImpl<MCInst> &Instructions) {
2590 if (hasMips32r6() || hasMips64r6()) {
2591 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2592 return false;
2593 }
2594
2595 warnIfNoMacro(IDLoc);
2596
2597 const MCOperand &DstRegOp = Inst.getOperand(0);
2598 assert(DstRegOp.isReg() && "expected register operand kind");
2599
2600 const MCOperand &SrcRegOp = Inst.getOperand(1);
2601 assert(SrcRegOp.isReg() && "expected register operand kind");
2602
2603 const MCOperand &OffsetImmOp = Inst.getOperand(2);
2604 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
2605
2606 unsigned DstReg = DstRegOp.getReg();
2607 unsigned SrcReg = SrcRegOp.getReg();
2608 int64_t OffsetValue = OffsetImmOp.getImm();
2609
2610 // NOTE: We always need AT for ULHU, as it is always used as the source
2611 // register for one of the LBu's.
2612 unsigned ATReg = getATReg(IDLoc);
2613 if (!ATReg)
2614 return true;
2615
2616 // When the value of offset+1 does not fit in 16 bits, we have to load the
2617 // offset in AT, (D)ADDu the original source register (if there was one), and
2618 // then use AT as the source register for the 2 generated LBu's.
2619 bool LoadedOffsetInAT = false;
2620 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
2621 LoadedOffsetInAT = true;
2622
2623 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002624 true, IDLoc, Instructions))
Toma Tabacud88d79c2015-06-23 14:39:42 +00002625 return true;
2626
2627 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
2628 // because it will make our output more similar to GAS'. For example,
2629 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
2630 // instead of just an "ori $1, $9, 32768".
2631 // NOTE: If there is no source register specified in the ULHU, the parser
2632 // will interpret it as $0.
2633 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
2634 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
2635 }
2636
2637 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
2638 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
2639 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
2640
2641 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
2642 if (isLittle()) {
2643 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
2644 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
2645 } else {
2646 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
2647 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
2648 }
2649
2650 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
2651
2652 MCInst TmpInst;
2653 TmpInst.setOpcode(Mips::LBu);
2654 TmpInst.addOperand(MCOperand::createReg(FirstLbuDstReg));
2655 TmpInst.addOperand(MCOperand::createReg(LbuSrcReg));
2656 TmpInst.addOperand(MCOperand::createImm(FirstLbuOffset));
2657 Instructions.push_back(TmpInst);
2658
2659 TmpInst.clear();
2660 TmpInst.setOpcode(Mips::LBu);
2661 TmpInst.addOperand(MCOperand::createReg(SecondLbuDstReg));
2662 TmpInst.addOperand(MCOperand::createReg(LbuSrcReg));
2663 TmpInst.addOperand(MCOperand::createImm(SecondLbuOffset));
2664 Instructions.push_back(TmpInst);
2665
2666 TmpInst.clear();
2667 TmpInst.setOpcode(Mips::SLL);
2668 TmpInst.addOperand(MCOperand::createReg(SllReg));
2669 TmpInst.addOperand(MCOperand::createReg(SllReg));
2670 TmpInst.addOperand(MCOperand::createImm(8));
2671 Instructions.push_back(TmpInst);
2672
2673 TmpInst.clear();
2674 TmpInst.setOpcode(Mips::OR);
2675 TmpInst.addOperand(MCOperand::createReg(DstReg));
2676 TmpInst.addOperand(MCOperand::createReg(DstReg));
2677 TmpInst.addOperand(MCOperand::createReg(ATReg));
2678 Instructions.push_back(TmpInst);
2679
2680 return false;
2681}
2682
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00002683bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
2684 SmallVectorImpl<MCInst> &Instructions) {
2685 if (hasMips32r6() || hasMips64r6()) {
2686 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2687 return false;
2688 }
2689
2690 const MCOperand &DstRegOp = Inst.getOperand(0);
2691 assert(DstRegOp.isReg() && "expected register operand kind");
2692
2693 const MCOperand &SrcRegOp = Inst.getOperand(1);
2694 assert(SrcRegOp.isReg() && "expected register operand kind");
2695
2696 const MCOperand &OffsetImmOp = Inst.getOperand(2);
2697 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
2698
2699 unsigned SrcReg = SrcRegOp.getReg();
2700 int64_t OffsetValue = OffsetImmOp.getImm();
2701 unsigned ATReg = 0;
2702
2703 // When the value of offset+3 does not fit in 16 bits, we have to load the
2704 // offset in AT, (D)ADDu the original source register (if there was one), and
2705 // then use AT as the source register for the generated LWL and LWR.
2706 bool LoadedOffsetInAT = false;
2707 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
2708 ATReg = getATReg(IDLoc);
2709 if (!ATReg)
2710 return true;
2711 LoadedOffsetInAT = true;
2712
2713 warnIfNoMacro(IDLoc);
2714
2715 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002716 true, IDLoc, Instructions))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00002717 return true;
2718
2719 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
2720 // because it will make our output more similar to GAS'. For example,
2721 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
2722 // instead of just an "ori $1, $9, 32768".
2723 // NOTE: If there is no source register specified in the ULW, the parser
2724 // will interpret it as $0.
2725 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
2726 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
2727 }
2728
2729 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
2730 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
2731 if (isLittle()) {
2732 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
2733 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
2734 } else {
2735 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
2736 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
2737 }
2738
2739 MCInst LeftLoadInst;
2740 LeftLoadInst.setOpcode(Mips::LWL);
2741 LeftLoadInst.addOperand(DstRegOp);
2742 LeftLoadInst.addOperand(MCOperand::createReg(FinalSrcReg));
2743 LeftLoadInst.addOperand(MCOperand::createImm(LeftLoadOffset));
2744 Instructions.push_back(LeftLoadInst);
2745
2746 MCInst RightLoadInst;
2747 RightLoadInst.setOpcode(Mips::LWR);
2748 RightLoadInst.addOperand(DstRegOp);
2749 RightLoadInst.addOperand(MCOperand::createReg(FinalSrcReg));
2750 RightLoadInst.addOperand(MCOperand::createImm(RightLoadOffset ));
2751 Instructions.push_back(RightLoadInst);
2752
2753 return false;
2754}
2755
Toma Tabacu234482a2015-03-16 12:03:39 +00002756void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
2757 SmallVectorImpl<MCInst> &Instructions) {
2758 MCInst NopInst;
2759 if (hasShortDelaySlot) {
2760 NopInst.setOpcode(Mips::MOVE16_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002761 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2762 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
Toma Tabacu234482a2015-03-16 12:03:39 +00002763 } else {
2764 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00002765 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2766 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2767 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu234482a2015-03-16 12:03:39 +00002768 }
2769 Instructions.push_back(NopInst);
2770}
2771
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002772void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +00002773 unsigned TrgReg, bool Is64Bit,
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002774 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders03f9c012015-07-14 12:24:22 +00002775 emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
2776 Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002777}
2778
Matheus Almeida595fcab2014-06-11 15:05:56 +00002779unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
2780 // As described by the Mips32r2 spec, the registers Rd and Rs for
2781 // jalr.hb must be different.
2782 unsigned Opcode = Inst.getOpcode();
2783
2784 if (Opcode == Mips::JALR_HB &&
2785 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
2786 return Match_RequiresDifferentSrcAndDst;
2787
2788 return Match_Success;
2789}
2790
David Blaikie960ea3f2014-06-08 16:18:35 +00002791bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
2792 OperandVector &Operands,
2793 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00002794 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00002795 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00002796
Jack Carterb4dbc172012-09-05 23:34:03 +00002797 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00002798 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00002799 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00002800 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00002801
2802 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002803 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002804 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00002805 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00002806 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00002807 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00002808 return false;
2809 }
2810 case Match_MissingFeature:
2811 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
2812 return true;
2813 case Match_InvalidOperand: {
2814 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00002815 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002816 if (ErrorInfo >= Operands.size())
2817 return Error(IDLoc, "too few operands for instruction");
2818
David Blaikie960ea3f2014-06-08 16:18:35 +00002819 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00002820 if (ErrorLoc == SMLoc())
2821 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00002822 }
2823
2824 return Error(ErrorLoc, "invalid operand for instruction");
2825 }
2826 case Match_MnemonicFail:
2827 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00002828 case Match_RequiresDifferentSrcAndDst:
2829 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00002830 }
Craig Topper589ceee2015-01-03 08:16:34 +00002831
2832 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00002833}
2834
Toma Tabacud9d344b2015-04-27 14:05:04 +00002835void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
2836 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
2837 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
2838 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002839}
2840
Toma Tabacu81496c12015-05-20 08:54:45 +00002841void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
2842 if (!AssemblerOptions.back()->isMacro())
2843 Warning(Loc, "macro instruction expanded into multiple instructions");
2844}
2845
Daniel Sandersef638fe2014-10-03 15:37:37 +00002846void
2847MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
2848 SMRange Range, bool ShowColors) {
2849 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00002850 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00002851 ShowColors);
2852}
2853
Jack Carter1ac53222013-02-20 23:11:17 +00002854int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002855 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002856
Vladimir Medic4c299852013-11-06 11:27:05 +00002857 CC = StringSwitch<unsigned>(Name)
2858 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002859 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00002860 .Case("a0", 4)
2861 .Case("a1", 5)
2862 .Case("a2", 6)
2863 .Case("a3", 7)
2864 .Case("v0", 2)
2865 .Case("v1", 3)
2866 .Case("s0", 16)
2867 .Case("s1", 17)
2868 .Case("s2", 18)
2869 .Case("s3", 19)
2870 .Case("s4", 20)
2871 .Case("s5", 21)
2872 .Case("s6", 22)
2873 .Case("s7", 23)
2874 .Case("k0", 26)
2875 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002876 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00002877 .Case("sp", 29)
2878 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002879 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00002880 .Case("ra", 31)
2881 .Case("t0", 8)
2882 .Case("t1", 9)
2883 .Case("t2", 10)
2884 .Case("t3", 11)
2885 .Case("t4", 12)
2886 .Case("t5", 13)
2887 .Case("t6", 14)
2888 .Case("t7", 15)
2889 .Case("t8", 24)
2890 .Case("t9", 25)
2891 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002892
Toma Tabacufda445c2014-09-15 15:33:01 +00002893 if (!(isABI_N32() || isABI_N64()))
2894 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002895
Daniel Sandersef638fe2014-10-03 15:37:37 +00002896 if (12 <= CC && CC <= 15) {
2897 // Name is one of t4-t7
2898 AsmToken RegTok = getLexer().peekTok();
2899 SMRange RegRange = RegTok.getLocRange();
2900
2901 StringRef FixedName = StringSwitch<StringRef>(Name)
2902 .Case("t4", "t0")
2903 .Case("t5", "t1")
2904 .Case("t6", "t2")
2905 .Case("t7", "t3")
2906 .Default("");
2907 assert(FixedName != "" && "Register name is not one of t4-t7.");
2908
2909 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
2910 "Did you mean $" + FixedName + "?", RegRange);
2911 }
2912
Toma Tabacufda445c2014-09-15 15:33:01 +00002913 // Although SGI documentation just cuts out t0-t3 for n32/n64,
2914 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
2915 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
2916 if (8 <= CC && CC <= 11)
2917 CC += 4;
2918
2919 if (CC == -1)
2920 CC = StringSwitch<unsigned>(Name)
2921 .Case("a4", 8)
2922 .Case("a5", 9)
2923 .Case("a6", 10)
2924 .Case("a7", 11)
2925 .Case("kt0", 26)
2926 .Case("kt1", 27)
2927 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002928
2929 return CC;
2930}
Jack Carterd0bd6422013-04-18 00:41:53 +00002931
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002932int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
2933 int CC;
2934
2935 CC = StringSwitch<unsigned>(Name)
2936 .Case("hwr_cpunum", 0)
2937 .Case("hwr_synci_step", 1)
2938 .Case("hwr_cc", 2)
2939 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00002940 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002941 .Default(-1);
2942
2943 return CC;
2944}
2945
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002946int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002947
Jack Cartera63b16a2012-09-07 00:23:42 +00002948 if (Name[0] == 'f') {
2949 StringRef NumString = Name.substr(1);
2950 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002951 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002952 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002953 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00002954 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002955 return IntVal;
2956 }
2957 return -1;
2958}
Jack Cartera63b16a2012-09-07 00:23:42 +00002959
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002960int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
2961
2962 if (Name.startswith("fcc")) {
2963 StringRef NumString = Name.substr(3);
2964 unsigned IntVal;
2965 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002966 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002967 if (IntVal > 7) // There are only 8 fcc registers.
2968 return -1;
2969 return IntVal;
2970 }
2971 return -1;
2972}
2973
2974int MipsAsmParser::matchACRegisterName(StringRef Name) {
2975
Akira Hatanaka274d24c2013-08-14 01:15:52 +00002976 if (Name.startswith("ac")) {
2977 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002978 unsigned IntVal;
2979 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002980 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002981 if (IntVal > 3) // There are only 3 acc registers.
2982 return -1;
2983 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00002984 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002985 return -1;
2986}
Jack Carterd0bd6422013-04-18 00:41:53 +00002987
Jack Carter5dc8ac92013-09-25 23:50:44 +00002988int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
2989 unsigned IntVal;
2990
2991 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2992 return -1;
2993
2994 if (IntVal > 31)
2995 return -1;
2996
2997 return IntVal;
2998}
2999
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003000int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3001 int CC;
3002
3003 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003004 .Case("msair", 0)
3005 .Case("msacsr", 1)
3006 .Case("msaaccess", 2)
3007 .Case("msasave", 3)
3008 .Case("msamodify", 4)
3009 .Case("msarequest", 5)
3010 .Case("msamap", 6)
3011 .Case("msaunmap", 7)
3012 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003013
3014 return CC;
3015}
3016
Toma Tabacu89a712b2015-04-15 10:48:56 +00003017unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00003018 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00003019 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00003020 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00003021 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00003022 return 0;
3023 }
3024 unsigned AT = getReg(
3025 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00003026 return AT;
3027}
Jack Carter0b744b32012-10-04 02:29:46 +00003028
Jack Carterd0bd6422013-04-18 00:41:53 +00003029unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00003030 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00003031}
3032
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003033unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003034 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00003035 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003036}
3037
Jack Carter873c7242013-01-12 01:03:14 +00003038int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003039 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00003040 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00003041 return -1;
3042
Jack Carter873c7242013-01-12 01:03:14 +00003043 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00003044}
3045
Toma Tabacu13964452014-09-04 13:23:44 +00003046bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003047 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003048 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003049
Jack Carter30a59822012-10-04 04:03:53 +00003050 // Check if the current operand has a custom associated parser, if so, try to
3051 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00003052 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3053 if (ResTy == MatchOperand_Success)
3054 return false;
3055 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3056 // there was a match, but an error occurred, in which case, just return that
3057 // the operand parsing failed.
3058 if (ResTy == MatchOperand_ParseFail)
3059 return true;
3060
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003061 DEBUG(dbgs() << ".. Generic Parser\n");
3062
Jack Carterb4dbc172012-09-05 23:34:03 +00003063 switch (getLexer().getKind()) {
3064 default:
3065 Error(Parser.getTok().getLoc(), "unexpected token in operand");
3066 return true;
3067 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003068 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00003069 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00003070
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003071 // Almost all registers have been parsed by custom parsers. There is only
3072 // one exception to this. $zero (and it's alias $0) will reach this point
3073 // for div, divu, and similar instructions because it is not an operand
3074 // to the instruction definition but an explicit register. Special case
3075 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00003076 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00003077 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003078
Jack Carterd0bd6422013-04-18 00:41:53 +00003079 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00003080 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003081 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00003082 return true;
3083
Jack Carter873c7242013-01-12 01:03:14 +00003084 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00003085 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00003086 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00003087 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003088 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00003089
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003090 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003091 return false;
3092 }
Vladimir Medic4c299852013-11-06 11:27:05 +00003093 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00003094 case AsmToken::LParen:
3095 case AsmToken::Minus:
3096 case AsmToken::Plus:
3097 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003098 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00003099 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003100 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003101 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003102 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00003103 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00003104 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003105 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003106 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003107 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00003108 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00003109 return true;
3110
Jack Carter873c7242013-01-12 01:03:14 +00003111 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3112
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003113 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00003114 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003115 } // case AsmToken::Percent
3116 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00003117 return true;
3118}
3119
Vladimir Medic4c299852013-11-06 11:27:05 +00003120const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00003121 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003122 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00003123 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003124 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00003125 // It's a constant, evaluate reloc value.
3126 int16_t Val;
3127 switch (getVariantKind(RelocStr)) {
3128 case MCSymbolRefExpr::VK_Mips_ABS_LO:
3129 // Get the 1st 16-bits.
3130 Val = MCE->getValue() & 0xffff;
3131 break;
3132 case MCSymbolRefExpr::VK_Mips_ABS_HI:
3133 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
3134 // 16 bits being negative.
3135 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
3136 break;
3137 case MCSymbolRefExpr::VK_Mips_HIGHER:
3138 // Get the 3rd 16-bits.
3139 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
3140 break;
3141 case MCSymbolRefExpr::VK_Mips_HIGHEST:
3142 // Get the 4th 16-bits.
3143 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
3144 break;
3145 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00003146 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00003147 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00003148 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003149 }
3150
Jack Carterb5cf5902013-04-17 00:18:04 +00003151 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003152 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00003153 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00003154 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003155 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003156 return Res;
3157 }
3158
3159 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00003160 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
3161
Sasa Stankovic06c47802014-04-03 10:37:45 +00003162 // Try to create target expression.
3163 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00003164 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003165
Jack Carterd0bd6422013-04-18 00:41:53 +00003166 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
3167 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003168 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003169 return Res;
3170 }
3171
3172 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003173 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003174 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00003175 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00003176 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003177 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003178 return Expr;
3179}
3180
3181bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
3182
3183 switch (Expr->getKind()) {
3184 case MCExpr::Constant:
3185 return true;
3186 case MCExpr::SymbolRef:
3187 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
3188 case MCExpr::Binary:
3189 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
3190 if (!isEvaluated(BE->getLHS()))
3191 return false;
3192 return isEvaluated(BE->getRHS());
3193 }
3194 case MCExpr::Unary:
3195 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003196 case MCExpr::Target:
3197 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003198 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003199 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00003200}
Jack Carterd0bd6422013-04-18 00:41:53 +00003201
Jack Carterb5cf5902013-04-17 00:18:04 +00003202bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003203 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003204 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00003205 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00003206 if (Tok.isNot(AsmToken::Identifier))
3207 return true;
3208
Yaron Keren075759a2015-03-30 15:42:36 +00003209 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00003210
Jack Carterd0bd6422013-04-18 00:41:53 +00003211 Parser.Lex(); // Eat the identifier.
3212 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003213 const MCExpr *IdVal;
3214 SMLoc EndLoc;
3215
3216 if (getLexer().getKind() == AsmToken::LParen) {
3217 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003218 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003219 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003220 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003221 const AsmToken &nextTok = Parser.getTok();
3222 if (nextTok.isNot(AsmToken::Identifier))
3223 return true;
3224 Str += "(%";
3225 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00003226 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00003227 if (getLexer().getKind() != AsmToken::LParen)
3228 return true;
3229 } else
3230 break;
3231 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003232 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00003233 return true;
3234
3235 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00003236 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003237
3238 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00003239 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003240
Jack Carterd0bd6422013-04-18 00:41:53 +00003241 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00003242 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003243}
3244
Jack Carterb4dbc172012-09-05 23:34:03 +00003245bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
3246 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003247 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00003248 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003249 if (ResTy == MatchOperand_Success) {
3250 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00003251 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003252 StartLoc = Operand.getStartLoc();
3253 EndLoc = Operand.getEndLoc();
3254
3255 // AFAIK, we only support numeric registers and named GPR's in CFI
3256 // directives.
3257 // Don't worry about eating tokens before failing. Using an unrecognised
3258 // register is a parse error.
3259 if (Operand.isGPRAsmReg()) {
3260 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003261 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003262 }
3263
3264 return (RegNo == (unsigned)-1);
3265 }
3266
3267 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00003268 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00003269}
3270
Jack Carterb5cf5902013-04-17 00:18:04 +00003271bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003272 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00003273 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003274 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003275 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00003276
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003277 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003278 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003279 ++NumOfLParen;
3280 }
Jack Carter873c7242013-01-12 01:03:14 +00003281
Jack Carterd0bd6422013-04-18 00:41:53 +00003282 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003283 default:
3284 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00003285 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00003286 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00003287 case AsmToken::Integer:
3288 case AsmToken::Minus:
3289 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00003290 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003291 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00003292 else
3293 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00003294 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00003295 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003296 break;
Jack Carter873c7242013-01-12 01:03:14 +00003297 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00003298 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003299 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003300 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003301}
3302
David Blaikie960ea3f2014-06-08 16:18:35 +00003303MipsAsmParser::OperandMatchResultTy
3304MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003305 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003306 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00003307 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00003308 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003309 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003310 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00003311 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00003312 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00003313
Jack Carterb5cf5902013-04-17 00:18:04 +00003314 if (getLexer().getKind() == AsmToken::LParen) {
3315 Parser.Lex();
3316 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003317 }
3318
Jack Carterb5cf5902013-04-17 00:18:04 +00003319 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003320 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00003321 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003322
Jack Carterd0bd6422013-04-18 00:41:53 +00003323 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003324 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003325 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003326 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003327 SMLoc E =
3328 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003329 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003330 return MatchOperand_Success;
3331 }
3332 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003333 SMLoc E =
3334 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00003335
Jack Carterd0bd6422013-04-18 00:41:53 +00003336 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003337 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00003338 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003339 S, E, *this);
3340 Operands.push_back(
3341 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003342 return MatchOperand_Success;
3343 }
3344 Error(Parser.getTok().getLoc(), "'(' expected");
3345 return MatchOperand_ParseFail;
3346 }
3347
Jack Carterd0bd6422013-04-18 00:41:53 +00003348 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003349 }
3350
Toma Tabacu13964452014-09-04 13:23:44 +00003351 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003352 if (Res != MatchOperand_Success)
3353 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003354
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003355 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003356 Error(Parser.getTok().getLoc(), "')' expected");
3357 return MatchOperand_ParseFail;
3358 }
3359
Jack Carter873c7242013-01-12 01:03:14 +00003360 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3361
Jack Carterd0bd6422013-04-18 00:41:53 +00003362 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003363
Craig Topper062a2ba2014-04-25 05:30:21 +00003364 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003365 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003366
Jack Carterd0bd6422013-04-18 00:41:53 +00003367 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00003368 std::unique_ptr<MipsOperand> op(
3369 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00003370 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003371 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003372 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00003373 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003374 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
3375 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003376 if (IdVal->evaluateAsAbsolute(Imm))
3377 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003378 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003379 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00003380 getContext());
3381 }
3382
David Blaikie960ea3f2014-06-08 16:18:35 +00003383 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003384 return MatchOperand_Success;
3385}
3386
David Blaikie960ea3f2014-06-08 16:18:35 +00003387bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003388 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00003389 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00003390 if (Sym) {
3391 SMLoc S = Parser.getTok().getLoc();
3392 const MCExpr *Expr;
3393 if (Sym->isVariable())
3394 Expr = Sym->getVariableValue();
3395 else
3396 return false;
3397 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003398 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00003399 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00003400 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003401 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003402 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00003403 if (ResTy == MatchOperand_Success) {
3404 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00003405 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00003406 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003407 llvm_unreachable("Should never ParseFail");
3408 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00003409 }
3410 } else if (Expr->getKind() == MCExpr::Constant) {
3411 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00003412 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00003413 Operands.push_back(
3414 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00003415 return true;
3416 }
3417 }
3418 return false;
3419}
Jack Carterd0bd6422013-04-18 00:41:53 +00003420
Jack Carter873c7242013-01-12 01:03:14 +00003421MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003422MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00003423 StringRef Identifier,
3424 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003425 int Index = matchCPURegisterName(Identifier);
3426 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003427 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003428 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3429 return MatchOperand_Success;
3430 }
3431
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003432 Index = matchHWRegsRegisterName(Identifier);
3433 if (Index != -1) {
3434 Operands.push_back(MipsOperand::createHWRegsReg(
3435 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3436 return MatchOperand_Success;
3437 }
3438
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003439 Index = matchFPURegisterName(Identifier);
3440 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003441 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003442 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3443 return MatchOperand_Success;
3444 }
3445
3446 Index = matchFCCRegisterName(Identifier);
3447 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003448 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003449 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3450 return MatchOperand_Success;
3451 }
3452
3453 Index = matchACRegisterName(Identifier);
3454 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003455 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003456 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3457 return MatchOperand_Success;
3458 }
3459
3460 Index = matchMSA128RegisterName(Identifier);
3461 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003462 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003463 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3464 return MatchOperand_Success;
3465 }
3466
3467 Index = matchMSA128CtrlRegisterName(Identifier);
3468 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003469 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003470 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3471 return MatchOperand_Success;
3472 }
3473
3474 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00003475}
3476
3477MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003478MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003479 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00003480 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003481
3482 if (Token.is(AsmToken::Identifier)) {
3483 DEBUG(dbgs() << ".. identifier\n");
3484 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00003485 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003486 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00003487 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003488 } else if (Token.is(AsmToken::Integer)) {
3489 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003490 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003491 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
3492 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003493 return MatchOperand_Success;
3494 }
3495
3496 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
3497
3498 return MatchOperand_NoMatch;
3499}
3500
David Blaikie960ea3f2014-06-08 16:18:35 +00003501MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003502MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003503 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003504 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003505
3506 auto Token = Parser.getTok();
3507
3508 SMLoc S = Token.getLoc();
3509
3510 if (Token.isNot(AsmToken::Dollar)) {
3511 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
3512 if (Token.is(AsmToken::Identifier)) {
3513 if (searchSymbolAlias(Operands))
3514 return MatchOperand_Success;
3515 }
3516 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
3517 return MatchOperand_NoMatch;
3518 }
3519 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003520
Toma Tabacu13964452014-09-04 13:23:44 +00003521 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00003522 if (ResTy == MatchOperand_Success) {
3523 Parser.Lex(); // $
3524 Parser.Lex(); // identifier
3525 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003526 return ResTy;
3527}
3528
3529MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003530MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003531 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003532 switch (getLexer().getKind()) {
3533 default:
3534 return MatchOperand_NoMatch;
3535 case AsmToken::LParen:
3536 case AsmToken::Minus:
3537 case AsmToken::Plus:
3538 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003539 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003540 case AsmToken::String:
3541 break;
3542 }
3543
3544 const MCExpr *IdVal;
3545 SMLoc S = Parser.getTok().getLoc();
3546 if (getParser().parseExpression(IdVal))
3547 return MatchOperand_ParseFail;
3548
3549 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3550 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
3551 return MatchOperand_Success;
3552}
3553
David Blaikie960ea3f2014-06-08 16:18:35 +00003554MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003555MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003556 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003557 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003558
3559 SMLoc S = getLexer().getLoc();
3560
3561 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00003562 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003563 if (ResTy != MatchOperand_NoMatch)
3564 return ResTy;
3565
Daniel Sanders315386c2014-04-01 10:40:14 +00003566 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00003567 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00003568 if (ResTy != MatchOperand_NoMatch)
3569 return ResTy;
3570
Daniel Sandersffd84362014-04-01 10:41:48 +00003571 const MCExpr *Expr = nullptr;
3572 if (Parser.parseExpression(Expr)) {
3573 // We have no way of knowing if a symbol was consumed so we must ParseFail
3574 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003575 }
Daniel Sandersffd84362014-04-01 10:41:48 +00003576 Operands.push_back(
3577 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003578 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00003579}
3580
Vladimir Medic2b953d02013-10-01 09:48:56 +00003581MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00003582MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003583 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00003584 const MCExpr *IdVal;
3585 // If the first token is '$' we may have register operand.
3586 if (Parser.getTok().is(AsmToken::Dollar))
3587 return MatchOperand_NoMatch;
3588 SMLoc S = Parser.getTok().getLoc();
3589 if (getParser().parseExpression(IdVal))
3590 return MatchOperand_ParseFail;
3591 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00003592 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00003593 int64_t Val = MCE->getValue();
3594 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3595 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003596 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00003597 return MatchOperand_Success;
3598}
3599
Matheus Almeida779c5932013-11-18 12:32:49 +00003600MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003601MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003602 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00003603 switch (getLexer().getKind()) {
3604 default:
3605 return MatchOperand_NoMatch;
3606 case AsmToken::LParen:
3607 case AsmToken::Plus:
3608 case AsmToken::Minus:
3609 case AsmToken::Integer:
3610 break;
3611 }
3612
3613 const MCExpr *Expr;
3614 SMLoc S = Parser.getTok().getLoc();
3615
3616 if (getParser().parseExpression(Expr))
3617 return MatchOperand_ParseFail;
3618
3619 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003620 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00003621 Error(S, "expected immediate value");
3622 return MatchOperand_ParseFail;
3623 }
3624
3625 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
3626 // and because the CPU always adds one to the immediate field, the allowed
3627 // range becomes 1..4. We'll only check the range here and will deal
3628 // with the addition/subtraction when actually decoding/encoding
3629 // the instruction.
3630 if (Val < 1 || Val > 4) {
3631 Error(S, "immediate not in range (1..4)");
3632 return MatchOperand_ParseFail;
3633 }
3634
Jack Carter3b2c96e2014-01-22 23:31:38 +00003635 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003636 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00003637 return MatchOperand_Success;
3638}
3639
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00003640MipsAsmParser::OperandMatchResultTy
3641MipsAsmParser::parseRegisterList(OperandVector &Operands) {
3642 MCAsmParser &Parser = getParser();
3643 SmallVector<unsigned, 10> Regs;
3644 unsigned RegNo;
3645 unsigned PrevReg = Mips::NoRegister;
3646 bool RegRange = false;
3647 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3648
3649 if (Parser.getTok().isNot(AsmToken::Dollar))
3650 return MatchOperand_ParseFail;
3651
3652 SMLoc S = Parser.getTok().getLoc();
3653 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
3654 SMLoc E = getLexer().getLoc();
3655 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
3656 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
3657 if (RegRange) {
3658 // Remove last register operand because registers from register range
3659 // should be inserted first.
3660 if (RegNo == Mips::RA) {
3661 Regs.push_back(RegNo);
3662 } else {
3663 unsigned TmpReg = PrevReg + 1;
3664 while (TmpReg <= RegNo) {
3665 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
3666 Error(E, "invalid register operand");
3667 return MatchOperand_ParseFail;
3668 }
3669
3670 PrevReg = TmpReg;
3671 Regs.push_back(TmpReg++);
3672 }
3673 }
3674
3675 RegRange = false;
3676 } else {
3677 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
3678 (RegNo != Mips::RA)) {
3679 Error(E, "$16 or $31 expected");
3680 return MatchOperand_ParseFail;
3681 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
3682 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3683 Error(E, "invalid register operand");
3684 return MatchOperand_ParseFail;
3685 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
3686 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3687 Error(E, "consecutive register numbers expected");
3688 return MatchOperand_ParseFail;
3689 }
3690
3691 Regs.push_back(RegNo);
3692 }
3693
3694 if (Parser.getTok().is(AsmToken::Minus))
3695 RegRange = true;
3696
3697 if (!Parser.getTok().isNot(AsmToken::Minus) &&
3698 !Parser.getTok().isNot(AsmToken::Comma)) {
3699 Error(E, "',' or '-' expected");
3700 return MatchOperand_ParseFail;
3701 }
3702
3703 Lex(); // Consume comma or minus
3704 if (Parser.getTok().isNot(AsmToken::Dollar))
3705 break;
3706
3707 PrevReg = RegNo;
3708 }
3709
3710 SMLoc E = Parser.getTok().getLoc();
3711 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3712 parseMemOperand(Operands);
3713 return MatchOperand_Success;
3714}
3715
Zoran Jovanovic2deca342014-12-16 14:59:10 +00003716MipsAsmParser::OperandMatchResultTy
3717MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
3718 MCAsmParser &Parser = getParser();
3719
3720 SMLoc S = Parser.getTok().getLoc();
3721 if (parseAnyRegister(Operands) != MatchOperand_Success)
3722 return MatchOperand_ParseFail;
3723
3724 SMLoc E = Parser.getTok().getLoc();
3725 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
3726 unsigned Reg = Op.getGPR32Reg();
3727 Operands.pop_back();
3728 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
3729 return MatchOperand_Success;
3730}
3731
Zoran Jovanovic41688672015-02-10 16:36:20 +00003732MipsAsmParser::OperandMatchResultTy
3733MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
3734 MCAsmParser &Parser = getParser();
3735 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3736 SmallVector<unsigned, 10> Regs;
3737
3738 if (Parser.getTok().isNot(AsmToken::Dollar))
3739 return MatchOperand_ParseFail;
3740
3741 SMLoc S = Parser.getTok().getLoc();
3742
3743 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3744 return MatchOperand_ParseFail;
3745
3746 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3747 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3748 Regs.push_back(RegNo);
3749
3750 SMLoc E = Parser.getTok().getLoc();
3751 if (Parser.getTok().isNot(AsmToken::Comma)) {
3752 Error(E, "',' expected");
3753 return MatchOperand_ParseFail;
3754 }
3755
3756 // Remove comma.
3757 Parser.Lex();
3758
3759 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3760 return MatchOperand_ParseFail;
3761
3762 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3763 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3764 Regs.push_back(RegNo);
3765
3766 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3767
3768 return MatchOperand_Success;
3769}
3770
Jack Carterdc1e35d2012-09-06 20:00:02 +00003771MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
3772
Vladimir Medic4c299852013-11-06 11:27:05 +00003773 MCSymbolRefExpr::VariantKind VK =
3774 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
3775 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
3776 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
3777 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
3778 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
3779 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
3780 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
3781 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
3782 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
3783 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
3784 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
3785 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
3786 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
3787 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
3788 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
3789 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
3790 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
3791 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00003792 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
3793 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
3794 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
3795 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
3796 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
3797 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00003798 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
3799 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00003800 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003801
Matheus Almeida2852af82014-04-22 10:15:54 +00003802 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00003803
Jack Carterdc1e35d2012-09-06 20:00:02 +00003804 return VK;
3805}
Jack Cartera63b16a2012-09-07 00:23:42 +00003806
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003807/// Sometimes (i.e. load/stores) the operand may be followed immediately by
3808/// either this.
3809/// ::= '(', register, ')'
3810/// handle it before we iterate so we don't get tripped up by the lack of
3811/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003812bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003813 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003814 if (getLexer().is(AsmToken::LParen)) {
3815 Operands.push_back(
3816 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
3817 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003818 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003819 SMLoc Loc = getLexer().getLoc();
3820 Parser.eatToEndOfStatement();
3821 return Error(Loc, "unexpected token in argument list");
3822 }
3823 if (Parser.getTok().isNot(AsmToken::RParen)) {
3824 SMLoc Loc = getLexer().getLoc();
3825 Parser.eatToEndOfStatement();
3826 return Error(Loc, "unexpected token, expected ')'");
3827 }
3828 Operands.push_back(
3829 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
3830 Parser.Lex();
3831 }
3832 return false;
3833}
3834
3835/// Sometimes (i.e. in MSA) the operand may be followed immediately by
3836/// either one of these.
3837/// ::= '[', register, ']'
3838/// ::= '[', integer, ']'
3839/// handle it before we iterate so we don't get tripped up by the lack of
3840/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003841bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00003842 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003843 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003844 if (getLexer().is(AsmToken::LBrac)) {
3845 Operands.push_back(
3846 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
3847 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003848 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003849 SMLoc Loc = getLexer().getLoc();
3850 Parser.eatToEndOfStatement();
3851 return Error(Loc, "unexpected token in argument list");
3852 }
3853 if (Parser.getTok().isNot(AsmToken::RBrac)) {
3854 SMLoc Loc = getLexer().getLoc();
3855 Parser.eatToEndOfStatement();
3856 return Error(Loc, "unexpected token, expected ']'");
3857 }
3858 Operands.push_back(
3859 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
3860 Parser.Lex();
3861 }
3862 return false;
3863}
3864
David Blaikie960ea3f2014-06-08 16:18:35 +00003865bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
3866 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003867 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003868 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003869
3870 // We have reached first instruction, module directive are now forbidden.
3871 getTargetStreamer().forbidModuleDirective();
3872
Vladimir Medic74593e62013-07-17 15:00:42 +00003873 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00003874 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00003875 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00003876 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00003877 }
Vladimir Medic64828a12013-07-16 10:07:14 +00003878 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003879 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003880
3881 // Read the remaining operands.
3882 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3883 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003884 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003885 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003886 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003887 return Error(Loc, "unexpected token in argument list");
3888 }
Toma Tabacu13964452014-09-04 13:23:44 +00003889 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003890 return true;
3891 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00003892
Jack Carterd0bd6422013-04-18 00:41:53 +00003893 while (getLexer().is(AsmToken::Comma)) {
3894 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00003895 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003896 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003897 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003898 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003899 return Error(Loc, "unexpected token in argument list");
3900 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003901 // Parse bracket and parenthesis suffixes before we iterate
3902 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00003903 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003904 return true;
3905 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00003906 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003907 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003908 }
3909 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003910 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3911 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003912 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003913 return Error(Loc, "unexpected token in argument list");
3914 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003915 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00003916 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00003917}
3918
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003919bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003920 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003921 SMLoc Loc = getLexer().getLoc();
3922 Parser.eatToEndOfStatement();
3923 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00003924}
3925
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003926bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003927 return Error(Loc, ErrorMsg);
3928}
3929
Jack Carter0b744b32012-10-04 02:29:46 +00003930bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003931 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003932 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00003933
3934 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00003935 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00003936
3937 Parser.Lex(); // Eat "noat".
3938
Jack Carterd0bd6422013-04-18 00:41:53 +00003939 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003940 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003941 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003942 return false;
3943 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003944
3945 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003946 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003947 return false;
3948}
Jack Carterd0bd6422013-04-18 00:41:53 +00003949
Jack Carter0b744b32012-10-04 02:29:46 +00003950bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00003951 // Line can be: ".set at", which sets $at to $1
3952 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00003953 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00003954 Parser.Lex(); // Eat "at".
3955
Jack Carter0b744b32012-10-04 02:29:46 +00003956 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003957 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00003958 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00003959
3960 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003961 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003962 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00003963 }
3964
3965 if (getLexer().isNot(AsmToken::Equal)) {
3966 reportParseError("unexpected token, expected equals sign");
3967 return false;
3968 }
3969 Parser.Lex(); // Eat "=".
3970
3971 if (getLexer().isNot(AsmToken::Dollar)) {
3972 if (getLexer().is(AsmToken::EndOfStatement)) {
3973 reportParseError("no register specified");
3974 return false;
3975 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00003976 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00003977 return false;
3978 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003979 }
3980 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00003981
Toma Tabacu16a74492015-02-13 10:30:57 +00003982 // Find out what "reg" is.
3983 unsigned AtRegNo;
3984 const AsmToken &Reg = Parser.getTok();
3985 if (Reg.is(AsmToken::Identifier)) {
3986 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
3987 } else if (Reg.is(AsmToken::Integer)) {
3988 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00003989 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00003990 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00003991 return false;
3992 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003993
3994 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00003995 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003996 reportParseError("invalid register");
3997 return false;
3998 }
3999 Parser.Lex(); // Eat "reg".
4000
4001 // If this is not the end of the statement, report an error.
4002 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4003 reportParseError("unexpected token, expected end of statement");
4004 return false;
4005 }
4006
4007 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4008
4009 Parser.Lex(); // Consume the EndOfStatement.
4010 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004011}
4012
4013bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004014 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004015 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004016 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004017 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004018 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004019 return false;
4020 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004021 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004022 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004023 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004024 return false;
4025}
4026
4027bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004028 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004029 Parser.Lex();
4030 // If this is not the end of the statement, report an error.
4031 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004032 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004033 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00004034 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004035 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00004036 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004037 Parser.Lex(); // Consume the EndOfStatement.
4038 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004039}
4040
4041bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004042 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004043 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004044 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004045 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004046 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004047 return false;
4048 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004049 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004050 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004051 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004052 return false;
4053}
4054
4055bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004056 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004057 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004058 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004059 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004060 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004061 return false;
4062 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004063 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00004064 reportParseError("`noreorder' must be set before `nomacro'");
4065 return false;
4066 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004067 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004068 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004069 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004070 return false;
4071}
Jack Carterd76b2372013-03-21 21:44:16 +00004072
Daniel Sanders44934432014-08-07 12:03:36 +00004073bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004074 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004075 Parser.Lex();
4076
4077 // If this is not the end of the statement, report an error.
4078 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004079 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004080
4081 setFeatureBits(Mips::FeatureMSA, "msa");
4082 getTargetStreamer().emitDirectiveSetMsa();
4083 return false;
4084}
4085
4086bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004087 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004088 Parser.Lex();
4089
4090 // If this is not the end of the statement, report an error.
4091 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004092 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004093
4094 clearFeatureBits(Mips::FeatureMSA, "msa");
4095 getTargetStreamer().emitDirectiveSetNoMsa();
4096 return false;
4097}
4098
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004099bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004100 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004101 Parser.Lex(); // Eat "nodsp".
4102
4103 // If this is not the end of the statement, report an error.
4104 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4105 reportParseError("unexpected token, expected end of statement");
4106 return false;
4107 }
4108
4109 clearFeatureBits(Mips::FeatureDSP, "dsp");
4110 getTargetStreamer().emitDirectiveSetNoDsp();
4111 return false;
4112}
4113
Toma Tabacucc2502d2014-11-04 17:18:07 +00004114bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004115 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004116 Parser.Lex(); // Eat "mips16".
4117
Jack Carter39536722014-01-22 23:08:42 +00004118 // If this is not the end of the statement, report an error.
4119 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004120 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00004121 return false;
4122 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00004123
4124 setFeatureBits(Mips::FeatureMips16, "mips16");
4125 getTargetStreamer().emitDirectiveSetMips16();
4126 Parser.Lex(); // Consume the EndOfStatement.
4127 return false;
4128}
4129
4130bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004131 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004132 Parser.Lex(); // Eat "nomips16".
4133
4134 // If this is not the end of the statement, report an error.
4135 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4136 reportParseError("unexpected token, expected end of statement");
4137 return false;
4138 }
4139
4140 clearFeatureBits(Mips::FeatureMips16, "mips16");
4141 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00004142 Parser.Lex(); // Consume the EndOfStatement.
4143 return false;
4144}
4145
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004146bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004147 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004148 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004149 // Line can be: .set fp=32
4150 // .set fp=xx
4151 // .set fp=64
4152 Parser.Lex(); // Eat fp token
4153 AsmToken Tok = Parser.getTok();
4154 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004155 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004156 return false;
4157 }
4158 Parser.Lex(); // Eat '=' token.
4159 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004160
4161 if (!parseFpABIValue(FpAbiVal, ".set"))
4162 return false;
4163
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004164 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004165 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004166 return false;
4167 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004168 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004169 Parser.Lex(); // Consume the EndOfStatement.
4170 return false;
4171}
4172
Toma Tabacu32c72aa2015-06-30 09:36:50 +00004173bool MipsAsmParser::parseSetOddSPRegDirective() {
4174 MCAsmParser &Parser = getParser();
4175
4176 Parser.Lex(); // Eat "oddspreg".
4177 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4178 reportParseError("unexpected token, expected end of statement");
4179 return false;
4180 }
4181
4182 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4183 getTargetStreamer().emitDirectiveSetOddSPReg();
4184 return false;
4185}
4186
4187bool MipsAsmParser::parseSetNoOddSPRegDirective() {
4188 MCAsmParser &Parser = getParser();
4189
4190 Parser.Lex(); // Eat "nooddspreg".
4191 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4192 reportParseError("unexpected token, expected end of statement");
4193 return false;
4194 }
4195
4196 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4197 getTargetStreamer().emitDirectiveSetNoOddSPReg();
4198 return false;
4199}
4200
Toma Tabacu9db22db2014-09-09 10:15:38 +00004201bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004202 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004203 SMLoc Loc = getLexer().getLoc();
4204
4205 Parser.Lex();
4206 if (getLexer().isNot(AsmToken::EndOfStatement))
4207 return reportParseError("unexpected token, expected end of statement");
4208
4209 // Always keep an element on the options "stack" to prevent the user
4210 // from changing the initial options. This is how we remember them.
4211 if (AssemblerOptions.size() == 2)
4212 return reportParseError(Loc, ".set pop with no .set push");
4213
4214 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00004215 setAvailableFeatures(
4216 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
4217 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00004218
4219 getTargetStreamer().emitDirectiveSetPop();
4220 return false;
4221}
4222
4223bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004224 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004225 Parser.Lex();
4226 if (getLexer().isNot(AsmToken::EndOfStatement))
4227 return reportParseError("unexpected token, expected end of statement");
4228
4229 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00004230 AssemblerOptions.push_back(
4231 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00004232
4233 getTargetStreamer().emitDirectiveSetPush();
4234 return false;
4235}
4236
Toma Tabacu29696502015-06-02 09:48:04 +00004237bool MipsAsmParser::parseSetSoftFloatDirective() {
4238 MCAsmParser &Parser = getParser();
4239 Parser.Lex();
4240 if (getLexer().isNot(AsmToken::EndOfStatement))
4241 return reportParseError("unexpected token, expected end of statement");
4242
4243 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4244 getTargetStreamer().emitDirectiveSetSoftFloat();
4245 return false;
4246}
4247
4248bool MipsAsmParser::parseSetHardFloatDirective() {
4249 MCAsmParser &Parser = getParser();
4250 Parser.Lex();
4251 if (getLexer().isNot(AsmToken::EndOfStatement))
4252 return reportParseError("unexpected token, expected end of statement");
4253
4254 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4255 getTargetStreamer().emitDirectiveSetHardFloat();
4256 return false;
4257}
4258
Jack Carterd76b2372013-03-21 21:44:16 +00004259bool MipsAsmParser::parseSetAssignment() {
4260 StringRef Name;
4261 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00004262 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00004263
4264 if (Parser.parseIdentifier(Name))
4265 reportParseError("expected identifier after .set");
4266
4267 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004268 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00004269 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00004270
Jack Carter3b2c96e2014-01-22 23:31:38 +00004271 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00004272 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00004273
Jim Grosbach6f482002015-05-18 18:43:14 +00004274 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00004275 Sym->setVariableValue(Value);
4276
4277 return false;
4278}
Jack Carterd0bd6422013-04-18 00:41:53 +00004279
Toma Tabacu26647792014-09-09 12:52:14 +00004280bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004281 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00004282 Parser.Lex();
4283 if (getLexer().isNot(AsmToken::EndOfStatement))
4284 return reportParseError("unexpected token, expected end of statement");
4285
4286 // Reset assembler options to their initial values.
Toma Tabacu465acfd2015-06-09 13:33:26 +00004287 setAvailableFeatures(
4288 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
4289 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00004290 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
4291
4292 getTargetStreamer().emitDirectiveSetMips0();
4293 return false;
4294}
4295
Toma Tabacu85618b32014-08-19 14:22:52 +00004296bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004297 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00004298 Parser.Lex();
4299 if (getLexer().isNot(AsmToken::Equal))
4300 return reportParseError("unexpected token, expected equals sign");
4301
4302 Parser.Lex();
4303 StringRef Arch;
4304 if (Parser.parseIdentifier(Arch))
4305 return reportParseError("expected arch identifier");
4306
4307 StringRef ArchFeatureName =
4308 StringSwitch<StringRef>(Arch)
4309 .Case("mips1", "mips1")
4310 .Case("mips2", "mips2")
4311 .Case("mips3", "mips3")
4312 .Case("mips4", "mips4")
4313 .Case("mips5", "mips5")
4314 .Case("mips32", "mips32")
4315 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004316 .Case("mips32r3", "mips32r3")
4317 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004318 .Case("mips32r6", "mips32r6")
4319 .Case("mips64", "mips64")
4320 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004321 .Case("mips64r3", "mips64r3")
4322 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004323 .Case("mips64r6", "mips64r6")
4324 .Case("cnmips", "cnmips")
4325 .Case("r4000", "mips3") // This is an implementation of Mips3.
4326 .Default("");
4327
4328 if (ArchFeatureName.empty())
4329 return reportParseError("unsupported architecture");
4330
4331 selectArch(ArchFeatureName);
4332 getTargetStreamer().emitDirectiveSetArch(Arch);
4333 return false;
4334}
4335
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004336bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004337 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004338 Parser.Lex();
4339 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004340 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004341
Matheus Almeida2852af82014-04-22 10:15:54 +00004342 switch (Feature) {
4343 default:
4344 llvm_unreachable("Unimplemented feature");
4345 case Mips::FeatureDSP:
4346 setFeatureBits(Mips::FeatureDSP, "dsp");
4347 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004348 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004349 case Mips::FeatureMicroMips:
4350 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004351 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004352 case Mips::FeatureMips1:
4353 selectArch("mips1");
4354 getTargetStreamer().emitDirectiveSetMips1();
4355 break;
4356 case Mips::FeatureMips2:
4357 selectArch("mips2");
4358 getTargetStreamer().emitDirectiveSetMips2();
4359 break;
4360 case Mips::FeatureMips3:
4361 selectArch("mips3");
4362 getTargetStreamer().emitDirectiveSetMips3();
4363 break;
4364 case Mips::FeatureMips4:
4365 selectArch("mips4");
4366 getTargetStreamer().emitDirectiveSetMips4();
4367 break;
4368 case Mips::FeatureMips5:
4369 selectArch("mips5");
4370 getTargetStreamer().emitDirectiveSetMips5();
4371 break;
4372 case Mips::FeatureMips32:
4373 selectArch("mips32");
4374 getTargetStreamer().emitDirectiveSetMips32();
4375 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004376 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004377 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004378 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004379 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004380 case Mips::FeatureMips32r3:
4381 selectArch("mips32r3");
4382 getTargetStreamer().emitDirectiveSetMips32R3();
4383 break;
4384 case Mips::FeatureMips32r5:
4385 selectArch("mips32r5");
4386 getTargetStreamer().emitDirectiveSetMips32R5();
4387 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004388 case Mips::FeatureMips32r6:
4389 selectArch("mips32r6");
4390 getTargetStreamer().emitDirectiveSetMips32R6();
4391 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004392 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004393 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00004394 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00004395 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004396 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004397 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004398 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00004399 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004400 case Mips::FeatureMips64r3:
4401 selectArch("mips64r3");
4402 getTargetStreamer().emitDirectiveSetMips64R3();
4403 break;
4404 case Mips::FeatureMips64r5:
4405 selectArch("mips64r5");
4406 getTargetStreamer().emitDirectiveSetMips64R5();
4407 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004408 case Mips::FeatureMips64r6:
4409 selectArch("mips64r6");
4410 getTargetStreamer().emitDirectiveSetMips64R6();
4411 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004412 }
4413 return false;
4414}
4415
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004416bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004417 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004418 if (getLexer().isNot(AsmToken::Comma)) {
4419 SMLoc Loc = getLexer().getLoc();
4420 Parser.eatToEndOfStatement();
4421 return Error(Loc, ErrorStr);
4422 }
4423
Matheus Almeida2852af82014-04-22 10:15:54 +00004424 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004425 return true;
4426}
4427
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004428bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00004429 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00004430 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004431
Toma Tabacudde4c462014-11-06 10:02:45 +00004432 if (inMips16Mode()) {
4433 reportParseError(".cpload is not supported in Mips16 mode");
4434 return false;
4435 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004436
David Blaikie960ea3f2014-06-08 16:18:35 +00004437 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00004438 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004439 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4440 reportParseError("expected register containing function address");
4441 return false;
4442 }
4443
David Blaikie960ea3f2014-06-08 16:18:35 +00004444 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
4445 if (!RegOpnd.isGPRAsmReg()) {
4446 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004447 return false;
4448 }
4449
Toma Tabacudde4c462014-11-06 10:02:45 +00004450 // If this is not the end of the statement, report an error.
4451 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4452 reportParseError("unexpected token, expected end of statement");
4453 return false;
4454 }
4455
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004456 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004457 return false;
4458}
4459
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004460bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004461 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004462 unsigned FuncReg;
4463 unsigned Save;
4464 bool SaveIsReg = true;
4465
Matheus Almeida7e815762014-06-18 13:08:59 +00004466 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004467 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00004468 if (ResTy == MatchOperand_NoMatch) {
4469 reportParseError("expected register containing function address");
4470 Parser.eatToEndOfStatement();
4471 return false;
4472 }
4473
4474 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4475 if (!FuncRegOpnd.isGPRAsmReg()) {
4476 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
4477 Parser.eatToEndOfStatement();
4478 return false;
4479 }
4480
4481 FuncReg = FuncRegOpnd.getGPR32Reg();
4482 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004483
Toma Tabacu65f10572014-09-16 15:00:52 +00004484 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004485 return true;
4486
Toma Tabacu13964452014-09-04 13:23:44 +00004487 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00004488 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004489 const AsmToken &Tok = Parser.getTok();
4490 if (Tok.is(AsmToken::Integer)) {
4491 Save = Tok.getIntVal();
4492 SaveIsReg = false;
4493 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00004494 } else {
4495 reportParseError("expected save register or stack offset");
4496 Parser.eatToEndOfStatement();
4497 return false;
4498 }
4499 } else {
4500 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4501 if (!SaveOpnd.isGPRAsmReg()) {
4502 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
4503 Parser.eatToEndOfStatement();
4504 return false;
4505 }
4506 Save = SaveOpnd.getGPR32Reg();
4507 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004508
Toma Tabacu65f10572014-09-16 15:00:52 +00004509 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004510 return true;
4511
Toma Tabacu8874eac2015-02-18 13:46:53 +00004512 const MCExpr *Expr;
4513 if (Parser.parseExpression(Expr)) {
4514 reportParseError("expected expression");
4515 return false;
4516 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004517
Toma Tabacu8874eac2015-02-18 13:46:53 +00004518 if (Expr->getKind() != MCExpr::SymbolRef) {
4519 reportParseError("expected symbol");
4520 return false;
4521 }
4522 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
4523
4524 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
4525 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004526 return false;
4527}
4528
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004529bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004530 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004531 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4532 const AsmToken &Tok = Parser.getTok();
4533
4534 if (Tok.getString() == "2008") {
4535 Parser.Lex();
4536 getTargetStreamer().emitDirectiveNaN2008();
4537 return false;
4538 } else if (Tok.getString() == "legacy") {
4539 Parser.Lex();
4540 getTargetStreamer().emitDirectiveNaNLegacy();
4541 return false;
4542 }
4543 }
4544 // If we don't recognize the option passed to the .nan
4545 // directive (e.g. no option or unknown option), emit an error.
4546 reportParseError("invalid option in .nan directive");
4547 return false;
4548}
4549
Jack Carter0b744b32012-10-04 02:29:46 +00004550bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004551 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004552 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00004553 const AsmToken &Tok = Parser.getTok();
4554
4555 if (Tok.getString() == "noat") {
4556 return parseSetNoAtDirective();
4557 } else if (Tok.getString() == "at") {
4558 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00004559 } else if (Tok.getString() == "arch") {
4560 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004561 } else if (Tok.getString() == "fp") {
4562 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00004563 } else if (Tok.getString() == "oddspreg") {
4564 return parseSetOddSPRegDirective();
4565 } else if (Tok.getString() == "nooddspreg") {
4566 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004567 } else if (Tok.getString() == "pop") {
4568 return parseSetPopDirective();
4569 } else if (Tok.getString() == "push") {
4570 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00004571 } else if (Tok.getString() == "reorder") {
4572 return parseSetReorderDirective();
4573 } else if (Tok.getString() == "noreorder") {
4574 return parseSetNoReorderDirective();
4575 } else if (Tok.getString() == "macro") {
4576 return parseSetMacroDirective();
4577 } else if (Tok.getString() == "nomacro") {
4578 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00004579 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00004580 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00004581 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00004582 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00004583 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00004584 getTargetStreamer().emitDirectiveSetNoMicroMips();
4585 Parser.eatToEndOfStatement();
4586 return false;
4587 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004588 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00004589 } else if (Tok.getString() == "mips0") {
4590 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00004591 } else if (Tok.getString() == "mips1") {
4592 return parseSetFeature(Mips::FeatureMips1);
4593 } else if (Tok.getString() == "mips2") {
4594 return parseSetFeature(Mips::FeatureMips2);
4595 } else if (Tok.getString() == "mips3") {
4596 return parseSetFeature(Mips::FeatureMips3);
4597 } else if (Tok.getString() == "mips4") {
4598 return parseSetFeature(Mips::FeatureMips4);
4599 } else if (Tok.getString() == "mips5") {
4600 return parseSetFeature(Mips::FeatureMips5);
4601 } else if (Tok.getString() == "mips32") {
4602 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00004603 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004604 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00004605 } else if (Tok.getString() == "mips32r3") {
4606 return parseSetFeature(Mips::FeatureMips32r3);
4607 } else if (Tok.getString() == "mips32r5") {
4608 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00004609 } else if (Tok.getString() == "mips32r6") {
4610 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00004611 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004612 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00004613 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004614 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00004615 } else if (Tok.getString() == "mips64r3") {
4616 return parseSetFeature(Mips::FeatureMips64r3);
4617 } else if (Tok.getString() == "mips64r5") {
4618 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00004619 } else if (Tok.getString() == "mips64r6") {
4620 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00004621 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004622 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004623 } else if (Tok.getString() == "nodsp") {
4624 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00004625 } else if (Tok.getString() == "msa") {
4626 return parseSetMsaDirective();
4627 } else if (Tok.getString() == "nomsa") {
4628 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00004629 } else if (Tok.getString() == "softfloat") {
4630 return parseSetSoftFloatDirective();
4631 } else if (Tok.getString() == "hardfloat") {
4632 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00004633 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00004634 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00004635 parseSetAssignment();
4636 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004637 }
Jack Carter07c818d2013-01-25 01:31:34 +00004638
Jack Carter0b744b32012-10-04 02:29:46 +00004639 return true;
4640}
4641
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004642/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00004643/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004644bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004645 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004646 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4647 for (;;) {
4648 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004649 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00004650 return true;
4651
4652 getParser().getStreamer().EmitValue(Value, Size);
4653
4654 if (getLexer().is(AsmToken::EndOfStatement))
4655 break;
4656
Jack Carter07c818d2013-01-25 01:31:34 +00004657 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004658 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00004659 Parser.Lex();
4660 }
4661 }
4662
4663 Parser.Lex();
4664 return false;
4665}
4666
Vladimir Medic4c299852013-11-06 11:27:05 +00004667/// parseDirectiveGpWord
4668/// ::= .gpword local_sym
4669bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004670 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004671 const MCExpr *Value;
4672 // EmitGPRel32Value requires an expression, so we are using base class
4673 // method to evaluate the expression.
4674 if (getParser().parseExpression(Value))
4675 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00004676 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00004677
Vladimir Medice10c1122013-11-13 13:18:04 +00004678 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004679 return Error(getLexer().getLoc(),
4680 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00004681 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00004682 return false;
4683}
4684
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004685/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00004686/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004687bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004688 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004689 const MCExpr *Value;
4690 // EmitGPRel64Value requires an expression, so we are using base class
4691 // method to evaluate the expression.
4692 if (getParser().parseExpression(Value))
4693 return true;
4694 getParser().getStreamer().EmitGPRel64Value(Value);
4695
4696 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004697 return Error(getLexer().getLoc(),
4698 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00004699 Parser.Lex(); // Eat EndOfStatement token.
4700 return false;
4701}
4702
Jack Carter0cd3c192014-01-06 23:27:31 +00004703bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004704 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00004705 // Get the option token.
4706 AsmToken Tok = Parser.getTok();
4707 // At the moment only identifiers are supported.
4708 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004709 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00004710 Parser.eatToEndOfStatement();
4711 return false;
4712 }
4713
4714 StringRef Option = Tok.getIdentifier();
4715
4716 if (Option == "pic0") {
4717 getTargetStreamer().emitDirectiveOptionPic0();
4718 Parser.Lex();
4719 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4720 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004721 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004722 Parser.eatToEndOfStatement();
4723 }
4724 return false;
4725 }
4726
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004727 if (Option == "pic2") {
4728 getTargetStreamer().emitDirectiveOptionPic2();
4729 Parser.Lex();
4730 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4731 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004732 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004733 Parser.eatToEndOfStatement();
4734 }
4735 return false;
4736 }
4737
Jack Carter0cd3c192014-01-06 23:27:31 +00004738 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00004739 Warning(Parser.getTok().getLoc(),
4740 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00004741 Parser.eatToEndOfStatement();
4742 return false;
4743}
4744
Toma Tabacu9ca50962015-04-16 09:53:47 +00004745/// parseInsnDirective
4746/// ::= .insn
4747bool MipsAsmParser::parseInsnDirective() {
4748 // If this is not the end of the statement, report an error.
4749 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4750 reportParseError("unexpected token, expected end of statement");
4751 return false;
4752 }
4753
4754 // The actual label marking happens in
4755 // MipsELFStreamer::createPendingLabelRelocs().
4756 getTargetStreamer().emitDirectiveInsn();
4757
4758 getParser().Lex(); // Eat EndOfStatement token.
4759 return false;
4760}
4761
Daniel Sanders7e527422014-07-10 13:38:23 +00004762/// parseDirectiveModule
4763/// ::= .module oddspreg
4764/// ::= .module nooddspreg
4765/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00004766/// ::= .module softfloat
4767/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004768bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004769 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004770 MCAsmLexer &Lexer = getLexer();
4771 SMLoc L = Lexer.getLoc();
4772
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004773 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004774 // TODO : get a better message.
4775 reportParseError(".module directive must appear before any code");
4776 return false;
4777 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004778
Toma Tabacuc405c822015-01-23 10:40:19 +00004779 StringRef Option;
4780 if (Parser.parseIdentifier(Option)) {
4781 reportParseError("expected .module option identifier");
4782 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004783 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004784
Toma Tabacuc405c822015-01-23 10:40:19 +00004785 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00004786 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00004787
Toma Tabacu3c499582015-06-25 10:56:57 +00004788 // Synchronize the abiflags information with the FeatureBits information we
4789 // changed above.
4790 getTargetStreamer().updateABIInfo(*this);
4791
4792 // If printing assembly, use the recently updated abiflags information.
4793 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
4794 // emitted at the end).
4795 getTargetStreamer().emitDirectiveModuleOddSPReg();
4796
Toma Tabacuc405c822015-01-23 10:40:19 +00004797 // If this is not the end of the statement, report an error.
4798 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4799 reportParseError("unexpected token, expected end of statement");
4800 return false;
4801 }
4802
4803 return false; // parseDirectiveModule has finished successfully.
4804 } else if (Option == "nooddspreg") {
4805 if (!isABI_O32()) {
4806 Error(L, "'.module nooddspreg' requires the O32 ABI");
4807 return false;
4808 }
4809
Toma Tabacufc97d8a2015-06-30 12:41:33 +00004810 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00004811
Toma Tabacu3c499582015-06-25 10:56:57 +00004812 // Synchronize the abiflags information with the FeatureBits information we
4813 // changed above.
4814 getTargetStreamer().updateABIInfo(*this);
4815
4816 // If printing assembly, use the recently updated abiflags information.
4817 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
4818 // emitted at the end).
4819 getTargetStreamer().emitDirectiveModuleOddSPReg();
4820
Toma Tabacuc405c822015-01-23 10:40:19 +00004821 // If this is not the end of the statement, report an error.
4822 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4823 reportParseError("unexpected token, expected end of statement");
4824 return false;
4825 }
4826
4827 return false; // parseDirectiveModule has finished successfully.
4828 } else if (Option == "fp") {
4829 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00004830 } else if (Option == "softfloat") {
4831 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4832
4833 // Synchronize the ABI Flags information with the FeatureBits information we
4834 // updated above.
4835 getTargetStreamer().updateABIInfo(*this);
4836
4837 // If printing assembly, use the recently updated ABI Flags information.
4838 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
4839 // emitted later).
4840 getTargetStreamer().emitDirectiveModuleSoftFloat();
4841
4842 // If this is not the end of the statement, report an error.
4843 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4844 reportParseError("unexpected token, expected end of statement");
4845 return false;
4846 }
4847
4848 return false; // parseDirectiveModule has finished successfully.
4849 } else if (Option == "hardfloat") {
4850 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4851
4852 // Synchronize the ABI Flags information with the FeatureBits information we
4853 // updated above.
4854 getTargetStreamer().updateABIInfo(*this);
4855
4856 // If printing assembly, use the recently updated ABI Flags information.
4857 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
4858 // emitted later).
4859 getTargetStreamer().emitDirectiveModuleHardFloat();
4860
4861 // If this is not the end of the statement, report an error.
4862 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4863 reportParseError("unexpected token, expected end of statement");
4864 return false;
4865 }
4866
4867 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00004868 } else {
4869 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
4870 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004871}
4872
4873/// parseDirectiveModuleFP
4874/// ::= =32
4875/// ::= =xx
4876/// ::= =64
4877bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004878 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004879 MCAsmLexer &Lexer = getLexer();
4880
4881 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004882 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004883 return false;
4884 }
4885 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004886
Daniel Sanders7e527422014-07-10 13:38:23 +00004887 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004888 if (!parseFpABIValue(FpABI, ".module"))
4889 return false;
4890
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004891 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004892 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004893 return false;
4894 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004895
Toma Tabacua64e5402015-06-25 12:44:38 +00004896 // Synchronize the abiflags information with the FeatureBits information we
4897 // changed above.
4898 getTargetStreamer().updateABIInfo(*this);
4899
4900 // If printing assembly, use the recently updated abiflags information.
4901 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
4902 // emitted at the end).
4903 getTargetStreamer().emitDirectiveModuleFP();
4904
Daniel Sanders7e527422014-07-10 13:38:23 +00004905 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004906 return false;
4907}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004908
Daniel Sanders7e527422014-07-10 13:38:23 +00004909bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004910 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004911 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004912 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00004913 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004914
4915 if (Lexer.is(AsmToken::Identifier)) {
4916 StringRef Value = Parser.getTok().getString();
4917 Parser.Lex();
4918
4919 if (Value != "xx") {
4920 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4921 return false;
4922 }
4923
4924 if (!isABI_O32()) {
4925 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
4926 return false;
4927 }
4928
Daniel Sanders7e527422014-07-10 13:38:23 +00004929 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00004930 if (ModuleLevelOptions) {
4931 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
4932 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
4933 } else {
4934 setFeatureBits(Mips::FeatureFPXX, "fpxx");
4935 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
4936 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004937 return true;
4938 }
4939
4940 if (Lexer.is(AsmToken::Integer)) {
4941 unsigned Value = Parser.getTok().getIntVal();
4942 Parser.Lex();
4943
4944 if (Value != 32 && Value != 64) {
4945 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4946 return false;
4947 }
4948
4949 if (Value == 32) {
4950 if (!isABI_O32()) {
4951 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
4952 return false;
4953 }
4954
Daniel Sanders7e527422014-07-10 13:38:23 +00004955 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00004956 if (ModuleLevelOptions) {
4957 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
4958 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
4959 } else {
4960 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
4961 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
4962 }
Toma Tabacua64e5402015-06-25 12:44:38 +00004963 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00004964 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00004965 if (ModuleLevelOptions) {
4966 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
4967 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
4968 } else {
4969 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
4970 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
4971 }
Toma Tabacua64e5402015-06-25 12:44:38 +00004972 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004973
Daniel Sanders7e527422014-07-10 13:38:23 +00004974 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004975 }
4976
4977 return false;
4978}
4979
Jack Carter0b744b32012-10-04 02:29:46 +00004980bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004981 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004982 StringRef IDVal = DirectiveID.getString();
4983
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004984 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004985 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00004986 if (IDVal == ".dword") {
4987 parseDataDirective(8, DirectiveID.getLoc());
4988 return false;
4989 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004990 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004991 StringRef SymbolName;
4992
4993 if (Parser.parseIdentifier(SymbolName)) {
4994 reportParseError("expected identifier after .ent");
4995 return false;
4996 }
4997
4998 // There's an undocumented extension that allows an integer to
4999 // follow the name of the procedure which AFAICS is ignored by GAS.
5000 // Example: .ent foo,2
5001 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5002 if (getLexer().isNot(AsmToken::Comma)) {
5003 // Even though we accept this undocumented extension for compatibility
5004 // reasons, the additional integer argument does not actually change
5005 // the behaviour of the '.ent' directive, so we would like to discourage
5006 // its use. We do this by not referring to the extended version in
5007 // error messages which are not directly related to its use.
5008 reportParseError("unexpected token, expected end of statement");
5009 return false;
5010 }
5011 Parser.Lex(); // Eat the comma.
5012 const MCExpr *DummyNumber;
5013 int64_t DummyNumberVal;
5014 // If the user was explicitly trying to use the extended version,
5015 // we still give helpful extension-related error messages.
5016 if (Parser.parseExpression(DummyNumber)) {
5017 reportParseError("expected number after comma");
5018 return false;
5019 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00005020 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005021 reportParseError("expected an absolute expression after comma");
5022 return false;
5023 }
5024 }
5025
5026 // If this is not the end of the statement, report an error.
5027 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5028 reportParseError("unexpected token, expected end of statement");
5029 return false;
5030 }
5031
Jim Grosbach6f482002015-05-18 18:43:14 +00005032 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005033
5034 getTargetStreamer().emitDirectiveEnt(*Sym);
5035 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00005036 return false;
5037 }
5038
Jack Carter07c818d2013-01-25 01:31:34 +00005039 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005040 StringRef SymbolName;
5041
5042 if (Parser.parseIdentifier(SymbolName)) {
5043 reportParseError("expected identifier after .end");
5044 return false;
5045 }
5046
5047 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5048 reportParseError("unexpected token, expected end of statement");
5049 return false;
5050 }
5051
5052 if (CurrentFn == nullptr) {
5053 reportParseError(".end used without .ent");
5054 return false;
5055 }
5056
5057 if ((SymbolName != CurrentFn->getName())) {
5058 reportParseError(".end symbol does not match .ent symbol");
5059 return false;
5060 }
5061
5062 getTargetStreamer().emitDirectiveEnd(SymbolName);
5063 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00005064 return false;
5065 }
5066
Jack Carter07c818d2013-01-25 01:31:34 +00005067 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005068 // .frame $stack_reg, frame_size_in_bytes, $return_reg
5069 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005070 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005071 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5072 reportParseError("expected stack register");
5073 return false;
5074 }
5075
5076 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5077 if (!StackRegOpnd.isGPRAsmReg()) {
5078 reportParseError(StackRegOpnd.getStartLoc(),
5079 "expected general purpose register");
5080 return false;
5081 }
5082 unsigned StackReg = StackRegOpnd.getGPR32Reg();
5083
5084 if (Parser.getTok().is(AsmToken::Comma))
5085 Parser.Lex();
5086 else {
5087 reportParseError("unexpected token, expected comma");
5088 return false;
5089 }
5090
5091 // Parse the frame size.
5092 const MCExpr *FrameSize;
5093 int64_t FrameSizeVal;
5094
5095 if (Parser.parseExpression(FrameSize)) {
5096 reportParseError("expected frame size value");
5097 return false;
5098 }
5099
Jim Grosbach13760bd2015-05-30 01:25:56 +00005100 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005101 reportParseError("frame size not an absolute expression");
5102 return false;
5103 }
5104
5105 if (Parser.getTok().is(AsmToken::Comma))
5106 Parser.Lex();
5107 else {
5108 reportParseError("unexpected token, expected comma");
5109 return false;
5110 }
5111
5112 // Parse the return register.
5113 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00005114 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005115 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5116 reportParseError("expected return register");
5117 return false;
5118 }
5119
5120 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5121 if (!ReturnRegOpnd.isGPRAsmReg()) {
5122 reportParseError(ReturnRegOpnd.getStartLoc(),
5123 "expected general purpose register");
5124 return false;
5125 }
5126
5127 // If this is not the end of the statement, report an error.
5128 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5129 reportParseError("unexpected token, expected end of statement");
5130 return false;
5131 }
5132
5133 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
5134 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00005135 return false;
5136 }
5137
Jack Carter07c818d2013-01-25 01:31:34 +00005138 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00005139 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00005140 }
5141
Daniel Sandersd97a6342014-08-13 10:07:34 +00005142 if (IDVal == ".mask" || IDVal == ".fmask") {
5143 // .mask bitmask, frame_offset
5144 // bitmask: One bit for each register used.
5145 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
5146 // first register is expected to be saved.
5147 // Examples:
5148 // .mask 0x80000000, -4
5149 // .fmask 0x80000000, -4
5150 //
Jack Carterbe332172012-09-07 00:48:02 +00005151
Daniel Sandersd97a6342014-08-13 10:07:34 +00005152 // Parse the bitmask
5153 const MCExpr *BitMask;
5154 int64_t BitMaskVal;
5155
5156 if (Parser.parseExpression(BitMask)) {
5157 reportParseError("expected bitmask value");
5158 return false;
5159 }
5160
Jim Grosbach13760bd2015-05-30 01:25:56 +00005161 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005162 reportParseError("bitmask not an absolute expression");
5163 return false;
5164 }
5165
5166 if (Parser.getTok().is(AsmToken::Comma))
5167 Parser.Lex();
5168 else {
5169 reportParseError("unexpected token, expected comma");
5170 return false;
5171 }
5172
5173 // Parse the frame_offset
5174 const MCExpr *FrameOffset;
5175 int64_t FrameOffsetVal;
5176
5177 if (Parser.parseExpression(FrameOffset)) {
5178 reportParseError("expected frame offset value");
5179 return false;
5180 }
5181
Jim Grosbach13760bd2015-05-30 01:25:56 +00005182 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005183 reportParseError("frame offset not an absolute expression");
5184 return false;
5185 }
5186
5187 // If this is not the end of the statement, report an error.
5188 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5189 reportParseError("unexpected token, expected end of statement");
5190 return false;
5191 }
5192
5193 if (IDVal == ".mask")
5194 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
5195 else
5196 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00005197 return false;
5198 }
5199
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005200 if (IDVal == ".nan")
5201 return parseDirectiveNaN();
5202
Jack Carter07c818d2013-01-25 01:31:34 +00005203 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005204 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00005205 return false;
5206 }
5207
Rafael Espindolab59fb732014-03-28 18:50:26 +00005208 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005209 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005210 return false;
5211 }
5212
Jack Carter07c818d2013-01-25 01:31:34 +00005213 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005214 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00005215 return false;
5216 }
5217
Jack Carter0cd3c192014-01-06 23:27:31 +00005218 if (IDVal == ".option")
5219 return parseDirectiveOption();
5220
5221 if (IDVal == ".abicalls") {
5222 getTargetStreamer().emitDirectiveAbiCalls();
5223 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005224 Error(Parser.getTok().getLoc(),
5225 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005226 // Clear line
5227 Parser.eatToEndOfStatement();
5228 }
5229 return false;
5230 }
5231
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005232 if (IDVal == ".cpsetup")
5233 return parseDirectiveCPSetup();
5234
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005235 if (IDVal == ".module")
5236 return parseDirectiveModule();
5237
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005238 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
5239 return parseInternalDirectiveReallowModule();
5240
Toma Tabacu9ca50962015-04-16 09:53:47 +00005241 if (IDVal == ".insn")
5242 return parseInsnDirective();
5243
Rafael Espindola870c4e92012-01-11 03:56:41 +00005244 return true;
5245}
5246
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005247bool MipsAsmParser::parseInternalDirectiveReallowModule() {
5248 // If this is not the end of the statement, report an error.
5249 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5250 reportParseError("unexpected token, expected end of statement");
5251 return false;
5252 }
5253
5254 getTargetStreamer().reallowModuleDirective();
5255
5256 getParser().Lex(); // Eat EndOfStatement token.
5257 return false;
5258}
5259
Rafael Espindola870c4e92012-01-11 03:56:41 +00005260extern "C" void LLVMInitializeMipsAsmParser() {
5261 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
5262 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
5263 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
5264 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
5265}
Jack Carterb4dbc172012-09-05 23:34:03 +00005266
5267#define GET_REGISTER_MATCHER
5268#define GET_MATCHER_IMPLEMENTATION
5269#include "MipsGenAsmMatcher.inc"