blob: 80a0de1105e53e4352bb7eb71c09588569c8bd33 [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.
Jack Carter0b744b32012-10-04 02:29:46 +0000116
Daniel Sandersef638fe2014-10-03 15:37:37 +0000117 // Print a warning along with its fix-it message at the given range.
118 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
119 SMRange Range, bool ShowColors = true);
120
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000121#define GET_ASSEMBLER_HEADER
122#include "MipsGenAsmMatcher.inc"
123
Matheus Almeida595fcab2014-06-11 15:05:56 +0000124 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
125
Chad Rosier49963552012-10-13 00:26:04 +0000126 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000127 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000128 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000129 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000130
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000131 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000132 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000133
Toma Tabacu13964452014-09-04 13:23:44 +0000134 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000135
Toma Tabacu13964452014-09-04 13:23:44 +0000136 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000137
David Blaikie960ea3f2014-06-08 16:18:35 +0000138 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
139 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000140
Craig Topper56c590a2014-04-29 07:58:02 +0000141 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000142
David Blaikie960ea3f2014-06-08 16:18:35 +0000143 MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000144
145 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000146 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000147 StringRef Identifier, SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000148
Jack Carter873c7242013-01-12 01:03:14 +0000149 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000150 matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
Jack Carter873c7242013-01-12 01:03:14 +0000151
Toma Tabacu13964452014-09-04 13:23:44 +0000152 MipsAsmParser::OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000153
Toma Tabacu13964452014-09-04 13:23:44 +0000154 MipsAsmParser::OperandMatchResultTy parseImm(OperandVector &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000155
Toma Tabacu13964452014-09-04 13:23:44 +0000156 MipsAsmParser::OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000157
David Blaikie960ea3f2014-06-08 16:18:35 +0000158 MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000159
Toma Tabacu13964452014-09-04 13:23:44 +0000160 MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000161
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000162 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000163 parseRegisterPair (OperandVector &Operands);
164
165 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +0000166 parseMovePRegPair(OperandVector &Operands);
167
168 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000169 parseRegisterList (OperandVector &Operands);
170
David Blaikie960ea3f2014-06-08 16:18:35 +0000171 bool searchSymbolAlias(OperandVector &Operands);
172
Toma Tabacu13964452014-09-04 13:23:44 +0000173 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000174
Jack Carter30a59822012-10-04 04:03:53 +0000175 bool needsExpansion(MCInst &Inst);
176
Matheus Almeida3813d572014-06-19 14:39:14 +0000177 // Expands assembly pseudo instructions.
178 // Returns false on success, true otherwise.
179 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000180 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000181
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000182 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
183 SmallVectorImpl<MCInst> &Instructions);
184
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000185 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
186 bool Is32BitImm, SMLoc IDLoc,
187 SmallVectorImpl<MCInst> &Instructions);
188
Toma Tabacu674825c2015-06-16 12:16:24 +0000189 bool loadSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
190 bool Is32BitSym, SMLoc IDLoc,
191 SmallVectorImpl<MCInst> &Instructions);
192
Toma Tabacu00e98672015-05-01 12:19:27 +0000193 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000194 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000195
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000196 bool expandLoadAddressImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000197 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000198
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000199 bool expandLoadAddressReg(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000200 SmallVectorImpl<MCInst> &Instructions);
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 Tabacu234482a2015-03-16 12:03:39 +0000217 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
218 SmallVectorImpl<MCInst> &Instructions);
219
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000220 void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
221 SmallVectorImpl<MCInst> &Instructions);
222
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000223 bool reportParseError(Twine ErrorMsg);
224 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000225
Jack Carterb5cf5902013-04-17 00:18:04 +0000226 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000227 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000228
Vladimir Medic4c299852013-11-06 11:27:05 +0000229 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000230
231 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000232 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000233 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000234 bool parseSetFeature(uint64_t Feature);
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000235 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000236 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000237 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000238 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000239 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000240 bool parseInsnDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000241
242 bool parseSetAtDirective();
243 bool parseSetNoAtDirective();
244 bool parseSetMacroDirective();
245 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000246 bool parseSetMsaDirective();
247 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000248 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000249 bool parseSetReorderDirective();
250 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000251 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000252 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000253 bool parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000254 bool parseSetPopDirective();
255 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000256 bool parseSetSoftFloatDirective();
257 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000258
Jack Carterd76b2372013-03-21 21:44:16 +0000259 bool parseSetAssignment();
260
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000261 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000262 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000263 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000264 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000265 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000266 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
267 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000268
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000269 bool parseInternalDirectiveReallowModule();
270
Jack Carterdc1e35d2012-09-06 20:00:02 +0000271 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000272
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000273 bool eatComma(StringRef ErrorStr);
274
Jack Carter1ac53222013-02-20 23:11:17 +0000275 int matchCPURegisterName(StringRef Symbol);
276
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000277 int matchHWRegsRegisterName(StringRef Symbol);
278
Jack Carter873c7242013-01-12 01:03:14 +0000279 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000280
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000281 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000282
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000283 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000284
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000285 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000286
Jack Carter5dc8ac92013-09-25 23:50:44 +0000287 int matchMSA128RegisterName(StringRef Name);
288
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000289 int matchMSA128CtrlRegisterName(StringRef Name);
290
Jack Carterd0bd6422013-04-18 00:41:53 +0000291 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000292
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000293 unsigned getGPR(int RegNo);
294
Toma Tabacu89a712b2015-04-15 10:48:56 +0000295 /// Returns the internal register number for the current AT. Also checks if
296 /// the current AT is unavailable (set to $0) and gives an error if it is.
297 /// This should be used in pseudo-instruction expansions which need AT.
298 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000299
300 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000301 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000302
303 // Helper function that checks if the value of a vector index is within the
304 // boundaries of accepted values for each RegisterKind
305 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
306 bool validateMSAIndex(int Val, int RegKind);
307
Daniel Sandersf0df2212014-08-04 12:20:00 +0000308 // Selects a new architecture by updating the FeatureBits with the necessary
309 // info including implied dependencies.
310 // Internally, it clears all the feature bits related to *any* architecture
311 // and selects the new one using the ToggleFeature functionality of the
312 // MCSubtargetInfo object that handles implied dependencies. The reason we
313 // clear all the arch related bits manually is because ToggleFeature only
314 // clears the features that imply the feature being cleared and not the
315 // features implied by the feature being cleared. This is easier to see
316 // with an example:
317 // --------------------------------------------------
318 // | Feature | Implies |
319 // | -------------------------------------------------|
320 // | FeatureMips1 | None |
321 // | FeatureMips2 | FeatureMips1 |
322 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
323 // | FeatureMips4 | FeatureMips3 |
324 // | ... | |
325 // --------------------------------------------------
326 //
327 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
328 // FeatureMipsGP64 | FeatureMips1)
329 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
330 void selectArch(StringRef ArchFeature) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000331 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000332 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
333 STI.setFeatureBits(FeatureBits);
334 setAvailableFeatures(
335 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000336 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000337 }
338
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000339 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000340 if (!(STI.getFeatureBits()[Feature])) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000341 setAvailableFeatures(
342 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000343 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000344 }
345 }
346
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000347 void clearFeatureBits(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
Rafael Espindola870c4e92012-01-11 03:56:41 +0000355public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000356 enum MipsMatchResultTy {
357 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
358#define GET_OPERAND_DIAGNOSTIC_TYPES
359#include "MipsGenAsmMatcher.inc"
360#undef GET_OPERAND_DIAGNOSTIC_TYPES
361
362 };
363
Joey Gouly0e76fa72013-09-12 10:28:05 +0000364 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000365 const MCInstrInfo &MII, const MCTargetOptions &Options)
Eric Christophera5762812015-01-26 17:33:46 +0000366 : MCTargetAsmParser(), STI(sti),
367 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
368 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000369 MCAsmParserExtension::Initialize(parser);
370
Toma Tabacu11e14a92015-04-21 11:50:52 +0000371 parser.addAliasForDirective(".asciiz", ".asciz");
372
Jack Carterb4dbc172012-09-05 23:34:03 +0000373 // Initialize the set of available features.
374 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000375
376 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000377 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000378 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000379
380 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000381 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000382 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000383
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000384 getTargetStreamer().updateABIInfo(*this);
385
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000386 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000387 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000388
389 CurrentFn = nullptr;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000390 }
391
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000392 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
393 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
394
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000395 bool isGP64bit() const { return STI.getFeatureBits()[Mips::FeatureGP64Bit]; }
396 bool isFP64bit() const { return STI.getFeatureBits()[Mips::FeatureFP64Bit]; }
Eric Christophera5762812015-01-26 17:33:46 +0000397 const MipsABIInfo &getABI() const { return ABI; }
398 bool isABI_N32() const { return ABI.IsN32(); }
399 bool isABI_N64() const { return ABI.IsN64(); }
400 bool isABI_O32() const { return ABI.IsO32(); }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000401 bool isABI_FPXX() const { return STI.getFeatureBits()[Mips::FeatureFPXX]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000402
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000403 bool useOddSPReg() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000404 return !(STI.getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000405 }
406
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000407 bool inMicroMipsMode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000408 return STI.getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000409 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000410 bool hasMips1() const { return STI.getFeatureBits()[Mips::FeatureMips1]; }
411 bool hasMips2() const { return STI.getFeatureBits()[Mips::FeatureMips2]; }
412 bool hasMips3() const { return STI.getFeatureBits()[Mips::FeatureMips3]; }
413 bool hasMips4() const { return STI.getFeatureBits()[Mips::FeatureMips4]; }
414 bool hasMips5() const { return STI.getFeatureBits()[Mips::FeatureMips5]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000415 bool hasMips32() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000416 return STI.getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000417 }
418 bool hasMips64() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000419 return STI.getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000420 }
421 bool hasMips32r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000422 return STI.getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000423 }
424 bool hasMips64r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000425 return STI.getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000426 }
Daniel Sanders17793142015-02-18 16:24:50 +0000427 bool hasMips32r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000428 return (STI.getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000429 }
430 bool hasMips64r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000431 return (STI.getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000432 }
433 bool hasMips32r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000434 return (STI.getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000435 }
436 bool hasMips64r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000437 return (STI.getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000438 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000439 bool hasMips32r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000440 return STI.getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000441 }
442 bool hasMips64r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000443 return STI.getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000444 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000445
446 bool hasDSP() const { return STI.getFeatureBits()[Mips::FeatureDSP]; }
447 bool hasDSPR2() const { return STI.getFeatureBits()[Mips::FeatureDSPR2]; }
448 bool hasMSA() const { return STI.getFeatureBits()[Mips::FeatureMSA]; }
Kai Nackee0245392015-01-27 19:11:28 +0000449 bool hasCnMips() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000450 return (STI.getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000451 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000452
453 bool inMips16Mode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000454 return STI.getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000455 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000456
Eric Christophere8ae3e32015-05-07 23:10:21 +0000457 bool useSoftFloat() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000458 return STI.getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000459 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000460
Toma Tabacud9d344b2015-04-27 14:05:04 +0000461 /// Warn if RegIndex is the same as the current AT.
462 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000463
464 void warnIfNoMacro(SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000465};
466}
467
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000468namespace {
469
470/// MipsOperand - Instances of this class represent a parsed Mips machine
471/// instruction.
472class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000473public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000474 /// Broad categories of register classes
475 /// The exact class is finalized by the render method.
476 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000477 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000478 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000479 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000480 RegKind_FCC = 4, /// FCC
481 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
482 RegKind_MSACtrl = 16, /// MSA control registers
483 RegKind_COP2 = 32, /// COP2
484 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
485 /// context).
486 RegKind_CCR = 128, /// CCR
487 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000488 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000489
490 /// Potentially any (e.g. $1)
491 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
492 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000493 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000494 };
495
496private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000497 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000498 k_Immediate, /// An immediate (possibly involving symbol references)
499 k_Memory, /// Base + Offset Memory Address
500 k_PhysRegister, /// A physical register from the Mips namespace
501 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000502 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000503 k_RegList, /// A physical register list
504 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000505 } Kind;
506
David Blaikie960ea3f2014-06-08 16:18:35 +0000507public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000508 MipsOperand(KindTy K, MipsAsmParser &Parser)
509 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
510
David Blaikie960ea3f2014-06-08 16:18:35 +0000511private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000512 /// For diagnostics, and checking the assembler temporary
513 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000514
Eric Christopher8996c5d2013-03-15 00:42:55 +0000515 struct Token {
516 const char *Data;
517 unsigned Length;
518 };
519
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000520 struct PhysRegOp {
521 unsigned Num; /// Register Number
522 };
523
524 struct RegIdxOp {
525 unsigned Index; /// Index into the register class
526 RegKind Kind; /// Bitfield of the kinds it could possibly be
527 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000528 };
529
530 struct ImmOp {
531 const MCExpr *Val;
532 };
533
534 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000535 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000536 const MCExpr *Off;
537 };
538
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000539 struct RegListOp {
540 SmallVector<unsigned, 10> *List;
541 };
542
Jack Carterb4dbc172012-09-05 23:34:03 +0000543 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000544 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000545 struct PhysRegOp PhysReg;
546 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000547 struct ImmOp Imm;
548 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000549 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000550 };
551
552 SMLoc StartLoc, EndLoc;
553
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000554 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000555 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
556 const MCRegisterInfo *RegInfo,
557 SMLoc S, SMLoc E,
558 MipsAsmParser &Parser) {
559 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000560 Op->RegIdx.Index = Index;
561 Op->RegIdx.RegInfo = RegInfo;
562 Op->RegIdx.Kind = RegKind;
563 Op->StartLoc = S;
564 Op->EndLoc = E;
565 return Op;
566 }
567
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000568public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000569 /// Coerce the register to GPR32 and return the real register for the current
570 /// target.
571 unsigned getGPR32Reg() const {
572 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000573 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000574 unsigned ClassID = Mips::GPR32RegClassID;
575 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000576 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000577
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000578 /// Coerce the register to GPR32 and return the real register for the current
579 /// target.
580 unsigned getGPRMM16Reg() const {
581 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
582 unsigned ClassID = Mips::GPR32RegClassID;
583 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
584 }
585
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000586 /// Coerce the register to GPR64 and return the real register for the current
587 /// target.
588 unsigned getGPR64Reg() const {
589 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
590 unsigned ClassID = Mips::GPR64RegClassID;
591 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000592 }
593
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000594private:
595 /// Coerce the register to AFGR64 and return the real register for the current
596 /// target.
597 unsigned getAFGR64Reg() const {
598 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
599 if (RegIdx.Index % 2 != 0)
600 AsmParser.Warning(StartLoc, "Float register should be even.");
601 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
602 .getRegister(RegIdx.Index / 2);
603 }
604
605 /// Coerce the register to FGR64 and return the real register for the current
606 /// target.
607 unsigned getFGR64Reg() const {
608 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
609 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
610 .getRegister(RegIdx.Index);
611 }
612
613 /// Coerce the register to FGR32 and return the real register for the current
614 /// target.
615 unsigned getFGR32Reg() const {
616 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
617 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
618 .getRegister(RegIdx.Index);
619 }
620
621 /// Coerce the register to FGRH32 and return the real register for the current
622 /// target.
623 unsigned getFGRH32Reg() const {
624 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
625 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
626 .getRegister(RegIdx.Index);
627 }
628
629 /// Coerce the register to FCC and return the real register for the current
630 /// target.
631 unsigned getFCCReg() const {
632 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
633 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
634 .getRegister(RegIdx.Index);
635 }
636
637 /// Coerce the register to MSA128 and return the real register for the current
638 /// target.
639 unsigned getMSA128Reg() const {
640 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
641 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
642 // identical
643 unsigned ClassID = Mips::MSA128BRegClassID;
644 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
645 }
646
647 /// Coerce the register to MSACtrl and return the real register for the
648 /// current target.
649 unsigned getMSACtrlReg() const {
650 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
651 unsigned ClassID = Mips::MSACtrlRegClassID;
652 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
653 }
654
655 /// Coerce the register to COP2 and return the real register for the
656 /// current target.
657 unsigned getCOP2Reg() const {
658 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
659 unsigned ClassID = Mips::COP2RegClassID;
660 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
661 }
662
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000663 /// Coerce the register to COP3 and return the real register for the
664 /// current target.
665 unsigned getCOP3Reg() const {
666 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
667 unsigned ClassID = Mips::COP3RegClassID;
668 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
669 }
670
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000671 /// Coerce the register to ACC64DSP and return the real register for the
672 /// current target.
673 unsigned getACC64DSPReg() const {
674 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
675 unsigned ClassID = Mips::ACC64DSPRegClassID;
676 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
677 }
678
679 /// Coerce the register to HI32DSP and return the real register for the
680 /// current target.
681 unsigned getHI32DSPReg() const {
682 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
683 unsigned ClassID = Mips::HI32DSPRegClassID;
684 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
685 }
686
687 /// Coerce the register to LO32DSP and return the real register for the
688 /// current target.
689 unsigned getLO32DSPReg() const {
690 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
691 unsigned ClassID = Mips::LO32DSPRegClassID;
692 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
693 }
694
695 /// Coerce the register to CCR and return the real register for the
696 /// current target.
697 unsigned getCCRReg() const {
698 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
699 unsigned ClassID = Mips::CCRRegClassID;
700 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
701 }
702
703 /// Coerce the register to HWRegs and return the real register for the
704 /// current target.
705 unsigned getHWRegsReg() const {
706 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
707 unsigned ClassID = Mips::HWRegsRegClassID;
708 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
709 }
710
711public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000712 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000713 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000714 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000715 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000716 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000717 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000718 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000719 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000720 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000721
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000722 void addRegOperands(MCInst &Inst, unsigned N) const {
723 llvm_unreachable("Use a custom parser instead");
724 }
725
Daniel Sanders21bce302014-04-01 12:35:23 +0000726 /// Render the operand to an MCInst as a GPR32
727 /// Asserts if the wrong number of operands are requested, or the operand
728 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000729 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
730 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000731 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000732 }
733
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000734 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
735 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000736 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000737 }
738
Jozef Kolek1904fa22014-11-24 14:25:53 +0000739 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
740 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000741 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000742 }
743
Zoran Jovanovic41688672015-02-10 16:36:20 +0000744 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
745 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000746 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000747 }
748
Daniel Sanders21bce302014-04-01 12:35:23 +0000749 /// Render the operand to an MCInst as a GPR64
750 /// Asserts if the wrong number of operands are requested, or the operand
751 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000752 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
753 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000754 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000755 }
756
757 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
758 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000759 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000760 }
761
762 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
763 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000764 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000765 }
766
767 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
768 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000769 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000770 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000771 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000772 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
773 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000774 }
775
776 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
777 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000778 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000779 }
780
781 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
782 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000783 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000784 }
785
786 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
787 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000788 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000789 }
790
791 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
792 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000793 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000794 }
795
796 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
797 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000798 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000799 }
800
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000801 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
802 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000803 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000804 }
805
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000806 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
807 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000808 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000809 }
810
811 void addHI32DSPAsmRegOperands(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(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000814 }
815
816 void addLO32DSPAsmRegOperands(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(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000819 }
820
821 void addCCRAsmRegOperands(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(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000824 }
825
826 void addHWRegsAsmRegOperands(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(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000829 }
830
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000831 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000832 assert(N == 1 && "Invalid number of operands!");
833 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000834 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000835 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000836
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000837 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000838 assert(N == 2 && "Invalid number of operands!");
839
Jim Grosbache9119e42015-05-13 18:37:00 +0000840 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000841
842 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000843 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000844 }
845
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000846 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
847 assert(N == 2 && "Invalid number of operands!");
848
Jim Grosbache9119e42015-05-13 18:37:00 +0000849 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000850
851 const MCExpr *Expr = getMemOff();
852 addExpr(Inst, Expr);
853 }
854
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000855 void addRegListOperands(MCInst &Inst, unsigned N) const {
856 assert(N == 1 && "Invalid number of operands!");
857
858 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000859 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000860 }
861
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000862 void addRegPairOperands(MCInst &Inst, unsigned N) const {
863 assert(N == 2 && "Invalid number of operands!");
864 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +0000865 Inst.addOperand(MCOperand::createReg(RegNo++));
866 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000867 }
868
Zoran Jovanovic41688672015-02-10 16:36:20 +0000869 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
870 assert(N == 2 && "Invalid number of operands!");
871 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000872 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000873 }
874
Craig Topper56c590a2014-04-29 07:58:02 +0000875 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000876 // As a special case until we sort out the definition of div/divu, pretend
877 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
878 if (isGPRAsmReg() && RegIdx.Index == 0)
879 return true;
880
881 return Kind == k_PhysRegister;
882 }
883 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000884 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000885 bool isConstantImm() const {
886 return isImm() && dyn_cast<MCConstantExpr>(getImm());
887 }
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +0000888 template <unsigned Bits> bool isUImm() const {
889 return isImm() && isConstantImm() && isUInt<Bits>(getConstantImm());
890 }
Craig Topper56c590a2014-04-29 07:58:02 +0000891 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000892 // Note: It's not possible to pretend that other operand kinds are tokens.
893 // The matcher emitter checks tokens first.
894 return Kind == k_Token;
895 }
Craig Topper56c590a2014-04-29 07:58:02 +0000896 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000897 bool isConstantMemOff() const {
898 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
899 }
900 template <unsigned Bits> bool isMemWithSimmOffset() const {
901 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
902 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000903 bool isMemWithGRPMM16Base() const {
904 return isMem() && getMemBase()->isMM16AsmReg();
905 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000906 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
907 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
908 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
909 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000910 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
911 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
912 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
913 && (getMemBase()->getGPR32Reg() == Mips::SP);
914 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000915 bool isRegList16() const {
916 if (!isRegList())
917 return false;
918
919 int Size = RegList.List->size();
920 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
921 RegList.List->back() != Mips::RA)
922 return false;
923
924 int PrevReg = *RegList.List->begin();
925 for (int i = 1; i < Size - 1; i++) {
926 int Reg = (*(RegList.List))[i];
927 if ( Reg != PrevReg + 1)
928 return false;
929 PrevReg = Reg;
930 }
931
932 return true;
933 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000934 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000935 bool isLSAImm() const {
936 if (!isConstantImm())
937 return false;
938 int64_t Val = getConstantImm();
939 return 1 <= Val && Val <= 4;
940 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000941 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +0000942 bool isMovePRegPair() const {
943 if (Kind != k_RegList || RegList.List->size() != 2)
944 return false;
945
946 unsigned R0 = RegList.List->front();
947 unsigned R1 = RegList.List->back();
948
949 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
950 (R0 == Mips::A1 && R1 == Mips::A3) ||
951 (R0 == Mips::A2 && R1 == Mips::A3) ||
952 (R0 == Mips::A0 && R1 == Mips::S5) ||
953 (R0 == Mips::A0 && R1 == Mips::S6) ||
954 (R0 == Mips::A0 && R1 == Mips::A1) ||
955 (R0 == Mips::A0 && R1 == Mips::A2) ||
956 (R0 == Mips::A0 && R1 == Mips::A3))
957 return true;
958
959 return false;
960 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000961
962 StringRef getToken() const {
963 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000964 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000965 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000966 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000967
Craig Topper56c590a2014-04-29 07:58:02 +0000968 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000969 // As a special case until we sort out the definition of div/divu, pretend
970 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
971 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
972 RegIdx.Kind & RegKind_GPR)
973 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000974
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000975 assert(Kind == k_PhysRegister && "Invalid access!");
976 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000977 }
978
Jack Carterb4dbc172012-09-05 23:34:03 +0000979 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000980 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000981 return Imm.Val;
982 }
983
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000984 int64_t getConstantImm() const {
985 const MCExpr *Val = getImm();
986 return static_cast<const MCConstantExpr *>(Val)->getValue();
987 }
988
989 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000990 assert((Kind == k_Memory) && "Invalid access!");
991 return Mem.Base;
992 }
993
994 const MCExpr *getMemOff() const {
995 assert((Kind == k_Memory) && "Invalid access!");
996 return Mem.Off;
997 }
998
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000999 int64_t getConstantMemOff() const {
1000 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1001 }
1002
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001003 const SmallVectorImpl<unsigned> &getRegList() const {
1004 assert((Kind == k_RegList) && "Invalid access!");
1005 return *(RegList.List);
1006 }
1007
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001008 unsigned getRegPair() const {
1009 assert((Kind == k_RegPair) && "Invalid access!");
1010 return RegIdx.Index;
1011 }
1012
David Blaikie960ea3f2014-06-08 16:18:35 +00001013 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1014 MipsAsmParser &Parser) {
1015 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001016 Op->Tok.Data = Str.data();
1017 Op->Tok.Length = Str.size();
1018 Op->StartLoc = S;
1019 Op->EndLoc = S;
1020 return Op;
1021 }
1022
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001023 /// Create a numeric register (e.g. $1). The exact register remains
1024 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001025 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001026 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001027 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001028 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001029 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001030 }
1031
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001032 /// Create a register that is definitely a GPR.
1033 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001034 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001035 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001036 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001037 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001038 }
1039
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001040 /// Create a register that is definitely a FGR.
1041 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001042 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001043 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001044 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001045 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1046 }
1047
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001048 /// Create a register that is definitely a HWReg.
1049 /// This is typically only used for named registers such as $hwr_cpunum.
1050 static std::unique_ptr<MipsOperand>
1051 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1052 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1053 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1054 }
1055
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001056 /// Create a register that is definitely an FCC.
1057 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001058 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001059 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001060 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001061 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1062 }
1063
1064 /// Create a register that is definitely an ACC.
1065 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001066 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001067 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001068 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001069 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1070 }
1071
1072 /// Create a register that is definitely an MSA128.
1073 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001074 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001075 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001076 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001077 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1078 }
1079
1080 /// Create a register that is definitely an MSACtrl.
1081 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001082 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001083 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001084 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001085 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1086 }
1087
David Blaikie960ea3f2014-06-08 16:18:35 +00001088 static std::unique_ptr<MipsOperand>
1089 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1090 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001091 Op->Imm.Val = Val;
1092 Op->StartLoc = S;
1093 Op->EndLoc = E;
1094 return Op;
1095 }
1096
David Blaikie960ea3f2014-06-08 16:18:35 +00001097 static std::unique_ptr<MipsOperand>
1098 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1099 SMLoc E, MipsAsmParser &Parser) {
1100 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1101 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001102 Op->Mem.Off = Off;
1103 Op->StartLoc = S;
1104 Op->EndLoc = E;
1105 return Op;
1106 }
1107
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001108 static std::unique_ptr<MipsOperand>
1109 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1110 MipsAsmParser &Parser) {
1111 assert (Regs.size() > 0 && "Empty list not allowed");
1112
1113 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001114 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001115 Op->StartLoc = StartLoc;
1116 Op->EndLoc = EndLoc;
1117 return Op;
1118 }
1119
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001120 static std::unique_ptr<MipsOperand>
1121 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1122 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1123 Op->RegIdx.Index = RegNo;
1124 Op->StartLoc = S;
1125 Op->EndLoc = E;
1126 return Op;
1127 }
1128
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001129 bool isGPRAsmReg() const {
1130 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001131 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001132 bool isMM16AsmReg() const {
1133 if (!(isRegIdx() && RegIdx.Kind))
1134 return false;
1135 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1136 || RegIdx.Index == 16 || RegIdx.Index == 17);
1137 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001138 bool isMM16AsmRegZero() const {
1139 if (!(isRegIdx() && RegIdx.Kind))
1140 return false;
1141 return (RegIdx.Index == 0 ||
1142 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1143 RegIdx.Index == 17);
1144 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001145 bool isMM16AsmRegMoveP() const {
1146 if (!(isRegIdx() && RegIdx.Kind))
1147 return false;
1148 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1149 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1150 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001151 bool isFGRAsmReg() const {
1152 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1153 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001154 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001155 bool isHWRegsAsmReg() const {
1156 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001157 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001158 bool isCCRAsmReg() const {
1159 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001160 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001161 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001162 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1163 return false;
1164 if (!AsmParser.hasEightFccRegisters())
1165 return RegIdx.Index == 0;
1166 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001167 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001168 bool isACCAsmReg() const {
1169 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001170 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001171 bool isCOP2AsmReg() const {
1172 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001173 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001174 bool isCOP3AsmReg() const {
1175 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1176 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001177 bool isMSA128AsmReg() const {
1178 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001179 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001180 bool isMSACtrlAsmReg() const {
1181 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001182 }
1183
Jack Carterb4dbc172012-09-05 23:34:03 +00001184 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001185 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001186 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001187 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001188
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001189 virtual ~MipsOperand() {
1190 switch (Kind) {
1191 case k_Immediate:
1192 break;
1193 case k_Memory:
1194 delete Mem.Base;
1195 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001196 case k_RegList:
1197 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001198 case k_PhysRegister:
1199 case k_RegisterIndex:
1200 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001201 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001202 break;
1203 }
1204 }
1205
Craig Topper56c590a2014-04-29 07:58:02 +00001206 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001207 switch (Kind) {
1208 case k_Immediate:
1209 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001210 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001211 OS << ">";
1212 break;
1213 case k_Memory:
1214 OS << "Mem<";
1215 Mem.Base->print(OS);
1216 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001217 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001218 OS << ">";
1219 break;
1220 case k_PhysRegister:
1221 OS << "PhysReg<" << PhysReg.Num << ">";
1222 break;
1223 case k_RegisterIndex:
1224 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1225 break;
1226 case k_Token:
1227 OS << Tok.Data;
1228 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001229 case k_RegList:
1230 OS << "RegList< ";
1231 for (auto Reg : (*RegList.List))
1232 OS << Reg << " ";
1233 OS << ">";
1234 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001235 case k_RegPair:
1236 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1237 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001238 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001239 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001240}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001241} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001242
Jack Carter9e65aa32013-03-22 00:05:30 +00001243namespace llvm {
1244extern const MCInstrDesc MipsInsts[];
1245}
1246static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1247 return MipsInsts[Opcode];
1248}
1249
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001250static bool hasShortDelaySlot(unsigned Opcode) {
1251 switch (Opcode) {
1252 case Mips::JALS_MM:
1253 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001254 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001255 case Mips::BGEZALS_MM:
1256 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001257 return true;
1258 default:
1259 return false;
1260 }
1261}
1262
Jack Carter9e65aa32013-03-22 00:05:30 +00001263bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001264 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001265 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001266
Jack Carter9e65aa32013-03-22 00:05:30 +00001267 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001268
1269 if (MCID.isBranch() || MCID.isCall()) {
1270 const unsigned Opcode = Inst.getOpcode();
1271 MCOperand Offset;
1272
1273 switch (Opcode) {
1274 default:
1275 break;
Kai Nackee0245392015-01-27 19:11:28 +00001276 case Mips::BBIT0:
1277 case Mips::BBIT032:
1278 case Mips::BBIT1:
1279 case Mips::BBIT132:
1280 assert(hasCnMips() && "instruction only valid for octeon cpus");
1281 // Fall through
1282
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001283 case Mips::BEQ:
1284 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001285 case Mips::BEQ_MM:
1286 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001287 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001288 Offset = Inst.getOperand(2);
1289 if (!Offset.isImm())
1290 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001291 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001292 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001293 if (OffsetToAlignment(Offset.getImm(),
1294 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001295 return Error(IDLoc, "branch to misaligned address");
1296 break;
1297 case Mips::BGEZ:
1298 case Mips::BGTZ:
1299 case Mips::BLEZ:
1300 case Mips::BLTZ:
1301 case Mips::BGEZAL:
1302 case Mips::BLTZAL:
1303 case Mips::BC1F:
1304 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001305 case Mips::BGEZ_MM:
1306 case Mips::BGTZ_MM:
1307 case Mips::BLEZ_MM:
1308 case Mips::BLTZ_MM:
1309 case Mips::BGEZAL_MM:
1310 case Mips::BLTZAL_MM:
1311 case Mips::BC1F_MM:
1312 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001313 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001314 Offset = Inst.getOperand(1);
1315 if (!Offset.isImm())
1316 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001317 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001318 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001319 if (OffsetToAlignment(Offset.getImm(),
1320 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001321 return Error(IDLoc, "branch to misaligned address");
1322 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001323 case Mips::BEQZ16_MM:
1324 case Mips::BNEZ16_MM:
1325 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1326 Offset = Inst.getOperand(1);
1327 if (!Offset.isImm())
1328 break; // We'll deal with this situation later on when applying fixups.
1329 if (!isIntN(8, Offset.getImm()))
1330 return Error(IDLoc, "branch target out of range");
1331 if (OffsetToAlignment(Offset.getImm(), 2LL))
1332 return Error(IDLoc, "branch to misaligned address");
1333 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001334 }
1335 }
1336
Daniel Sandersa84989a2014-06-16 13:25:35 +00001337 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1338 // We still accept it but it is a normal nop.
1339 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1340 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1341 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1342 "nop instruction");
1343 }
1344
Kai Nackee0245392015-01-27 19:11:28 +00001345 if (hasCnMips()) {
1346 const unsigned Opcode = Inst.getOpcode();
1347 MCOperand Opnd;
1348 int Imm;
1349
1350 switch (Opcode) {
1351 default:
1352 break;
1353
1354 case Mips::BBIT0:
1355 case Mips::BBIT032:
1356 case Mips::BBIT1:
1357 case Mips::BBIT132:
1358 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1359 // The offset is handled above
1360 Opnd = Inst.getOperand(1);
1361 if (!Opnd.isImm())
1362 return Error(IDLoc, "expected immediate operand kind");
1363 Imm = Opnd.getImm();
1364 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1365 Opcode == Mips::BBIT1 ? 63 : 31))
1366 return Error(IDLoc, "immediate operand value out of range");
1367 if (Imm > 31) {
1368 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1369 : Mips::BBIT132);
1370 Inst.getOperand(1).setImm(Imm - 32);
1371 }
1372 break;
1373
1374 case Mips::CINS:
1375 case Mips::CINS32:
1376 case Mips::EXTS:
1377 case Mips::EXTS32:
1378 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1379 // Check length
1380 Opnd = Inst.getOperand(3);
1381 if (!Opnd.isImm())
1382 return Error(IDLoc, "expected immediate operand kind");
1383 Imm = Opnd.getImm();
1384 if (Imm < 0 || Imm > 31)
1385 return Error(IDLoc, "immediate operand value out of range");
1386 // Check position
1387 Opnd = Inst.getOperand(2);
1388 if (!Opnd.isImm())
1389 return Error(IDLoc, "expected immediate operand kind");
1390 Imm = Opnd.getImm();
1391 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1392 Opcode == Mips::EXTS ? 63 : 31))
1393 return Error(IDLoc, "immediate operand value out of range");
1394 if (Imm > 31) {
1395 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1396 Inst.getOperand(2).setImm(Imm - 32);
1397 }
1398 break;
1399
1400 case Mips::SEQi:
1401 case Mips::SNEi:
1402 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1403 Opnd = Inst.getOperand(2);
1404 if (!Opnd.isImm())
1405 return Error(IDLoc, "expected immediate operand kind");
1406 Imm = Opnd.getImm();
1407 if (!isInt<10>(Imm))
1408 return Error(IDLoc, "immediate operand value out of range");
1409 break;
1410 }
1411 }
1412
Jack Carter9e65aa32013-03-22 00:05:30 +00001413 if (MCID.mayLoad() || MCID.mayStore()) {
1414 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001415 // reference or immediate we may have to expand instructions.
1416 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001417 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001418 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1419 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001420 MCOperand &Op = Inst.getOperand(i);
1421 if (Op.isImm()) {
1422 int MemOffset = Op.getImm();
1423 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001424 // Offset can't exceed 16bit value.
1425 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001426 return false;
1427 }
1428 } else if (Op.isExpr()) {
1429 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001430 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001431 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001432 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001433 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001434 // Expand symbol.
1435 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001436 return false;
1437 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001438 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001439 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001440 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001441 }
1442 }
1443 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001444 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001445 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001446
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001447 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001448 if (MCID.mayLoad()) {
1449 // Try to create 16-bit GP relative load instruction.
1450 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1451 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1452 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1453 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1454 MCOperand &Op = Inst.getOperand(i);
1455 if (Op.isImm()) {
1456 int MemOffset = Op.getImm();
1457 MCOperand &DstReg = Inst.getOperand(0);
1458 MCOperand &BaseReg = Inst.getOperand(1);
1459 if (isIntN(9, MemOffset) && (MemOffset % 4 == 0) &&
1460 getContext().getRegisterInfo()->getRegClass(
1461 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
1462 BaseReg.getReg() == Mips::GP) {
1463 MCInst TmpInst;
1464 TmpInst.setLoc(IDLoc);
1465 TmpInst.setOpcode(Mips::LWGP_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00001466 TmpInst.addOperand(MCOperand::createReg(DstReg.getReg()));
1467 TmpInst.addOperand(MCOperand::createReg(Mips::GP));
1468 TmpInst.addOperand(MCOperand::createImm(MemOffset));
Jozef Koleke10a02e2015-01-28 17:27:26 +00001469 Instructions.push_back(TmpInst);
1470 return false;
1471 }
1472 }
1473 }
1474 } // for
1475 } // if load
1476
1477 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1478
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001479 MCOperand Opnd;
1480 int Imm;
1481
1482 switch (Inst.getOpcode()) {
1483 default:
1484 break;
1485 case Mips::ADDIUS5_MM:
1486 Opnd = Inst.getOperand(2);
1487 if (!Opnd.isImm())
1488 return Error(IDLoc, "expected immediate operand kind");
1489 Imm = Opnd.getImm();
1490 if (Imm < -8 || Imm > 7)
1491 return Error(IDLoc, "immediate operand value out of range");
1492 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001493 case Mips::ADDIUSP_MM:
1494 Opnd = Inst.getOperand(0);
1495 if (!Opnd.isImm())
1496 return Error(IDLoc, "expected immediate operand kind");
1497 Imm = Opnd.getImm();
1498 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1499 Imm % 4 != 0)
1500 return Error(IDLoc, "immediate operand value out of range");
1501 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001502 case Mips::SLL16_MM:
1503 case Mips::SRL16_MM:
1504 Opnd = Inst.getOperand(2);
1505 if (!Opnd.isImm())
1506 return Error(IDLoc, "expected immediate operand kind");
1507 Imm = Opnd.getImm();
1508 if (Imm < 1 || Imm > 8)
1509 return Error(IDLoc, "immediate operand value out of range");
1510 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001511 case Mips::LI16_MM:
1512 Opnd = Inst.getOperand(1);
1513 if (!Opnd.isImm())
1514 return Error(IDLoc, "expected immediate operand kind");
1515 Imm = Opnd.getImm();
1516 if (Imm < -1 || Imm > 126)
1517 return Error(IDLoc, "immediate operand value out of range");
1518 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001519 case Mips::ADDIUR2_MM:
1520 Opnd = Inst.getOperand(2);
1521 if (!Opnd.isImm())
1522 return Error(IDLoc, "expected immediate operand kind");
1523 Imm = Opnd.getImm();
1524 if (!(Imm == 1 || Imm == -1 ||
1525 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1526 return Error(IDLoc, "immediate operand value out of range");
1527 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001528 case Mips::ADDIUR1SP_MM:
1529 Opnd = Inst.getOperand(1);
1530 if (!Opnd.isImm())
1531 return Error(IDLoc, "expected immediate operand kind");
1532 Imm = Opnd.getImm();
1533 if (OffsetToAlignment(Imm, 4LL))
1534 return Error(IDLoc, "misaligned immediate operand value");
1535 if (Imm < 0 || Imm > 255)
1536 return Error(IDLoc, "immediate operand value out of range");
1537 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001538 case Mips::ANDI16_MM:
1539 Opnd = Inst.getOperand(2);
1540 if (!Opnd.isImm())
1541 return Error(IDLoc, "expected immediate operand kind");
1542 Imm = Opnd.getImm();
1543 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1544 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1545 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1546 return Error(IDLoc, "immediate operand value out of range");
1547 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001548 case Mips::LBU16_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 > 14)
1554 return Error(IDLoc, "immediate operand value out of range");
1555 break;
1556 case Mips::SB16_MM:
1557 Opnd = Inst.getOperand(2);
1558 if (!Opnd.isImm())
1559 return Error(IDLoc, "expected immediate operand kind");
1560 Imm = Opnd.getImm();
1561 if (Imm < 0 || Imm > 15)
1562 return Error(IDLoc, "immediate operand value out of range");
1563 break;
1564 case Mips::LHU16_MM:
1565 case Mips::SH16_MM:
1566 Opnd = Inst.getOperand(2);
1567 if (!Opnd.isImm())
1568 return Error(IDLoc, "expected immediate operand kind");
1569 Imm = Opnd.getImm();
1570 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1571 return Error(IDLoc, "immediate operand value out of range");
1572 break;
1573 case Mips::LW16_MM:
1574 case Mips::SW16_MM:
1575 Opnd = Inst.getOperand(2);
1576 if (!Opnd.isImm())
1577 return Error(IDLoc, "expected immediate operand kind");
1578 Imm = Opnd.getImm();
1579 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1580 return Error(IDLoc, "immediate operand value out of range");
1581 break;
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001582 case Mips::CACHE:
1583 case Mips::PREF:
1584 Opnd = Inst.getOperand(2);
1585 if (!Opnd.isImm())
1586 return Error(IDLoc, "expected immediate operand kind");
1587 Imm = Opnd.getImm();
1588 if (!isUInt<5>(Imm))
1589 return Error(IDLoc, "immediate operand value out of range");
1590 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001591 case Mips::ADDIUPC_MM:
1592 MCOperand Opnd = Inst.getOperand(1);
1593 if (!Opnd.isImm())
1594 return Error(IDLoc, "expected immediate operand kind");
1595 int Imm = Opnd.getImm();
1596 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1597 return Error(IDLoc, "immediate operand value out of range");
1598 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001599 }
1600 }
1601
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001602 if (needsExpansion(Inst)) {
1603 if (expandInstruction(Inst, IDLoc, Instructions))
1604 return true;
1605 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001606 Instructions.push_back(Inst);
1607
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001608 // If this instruction has a delay slot and .set reorder is active,
1609 // emit a NOP after it.
1610 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1611 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1612
Jack Carter9e65aa32013-03-22 00:05:30 +00001613 return false;
1614}
1615
Jack Carter30a59822012-10-04 04:03:53 +00001616bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1617
Jack Carterd0bd6422013-04-18 00:41:53 +00001618 switch (Inst.getOpcode()) {
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001619 case Mips::LoadImm32:
1620 case Mips::LoadImm64:
1621 case Mips::LoadAddrImm32:
1622 case Mips::LoadAddrReg32:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001623 case Mips::B_MM_Pseudo:
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001624 case Mips::LWM_MM:
1625 case Mips::SWM_MM:
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001626 case Mips::JalOneReg:
1627 case Mips::JalTwoReg:
Toma Tabacue1e460d2015-06-11 10:36:10 +00001628 case Mips::BneImm:
1629 case Mips::BeqImm:
Toma Tabacu1a108322015-06-17 13:20:24 +00001630 case Mips::BLT:
1631 case Mips::BLE:
1632 case Mips::BGE:
1633 case Mips::BGT:
1634 case Mips::BLTU:
1635 case Mips::BLEU:
1636 case Mips::BGEU:
1637 case Mips::BGTU:
Jack Carterd0bd6422013-04-18 00:41:53 +00001638 return true;
1639 default:
1640 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001641 }
1642}
Jack Carter92995f12012-10-06 00:53:28 +00001643
Matheus Almeida3813d572014-06-19 14:39:14 +00001644bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001645 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001646 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001647 default: llvm_unreachable("unimplemented expansion");
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001648 case Mips::LoadImm32:
Toma Tabacu00e98672015-05-01 12:19:27 +00001649 return expandLoadImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001650 case Mips::LoadImm64:
Toma Tabacu00e98672015-05-01 12:19:27 +00001651 return expandLoadImm(Inst, false, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001652 case Mips::LoadAddrImm32:
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001653 return expandLoadAddressImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001654 case Mips::LoadAddrReg32:
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001655 return expandLoadAddressReg(Inst, true, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001656 case Mips::B_MM_Pseudo:
1657 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001658 case Mips::SWM_MM:
1659 case Mips::LWM_MM:
1660 return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001661 case Mips::JalOneReg:
1662 case Mips::JalTwoReg:
1663 return expandJalWithRegs(Inst, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00001664 case Mips::BneImm:
1665 case Mips::BeqImm:
1666 return expandBranchImm(Inst, IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00001667 case Mips::BLT:
1668 case Mips::BLE:
1669 case Mips::BGE:
1670 case Mips::BGT:
1671 case Mips::BLTU:
1672 case Mips::BLEU:
1673 case Mips::BGEU:
1674 case Mips::BGTU:
1675 return expandCondBranches(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001676 }
Jack Carter30a59822012-10-04 04:03:53 +00001677}
Jack Carter92995f12012-10-06 00:53:28 +00001678
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001679namespace {
Toma Tabacua2861db2015-05-01 10:26:47 +00001680template <unsigned ShiftAmount>
Toma Tabacu61145652015-04-28 13:16:06 +00001681void createLShiftOri(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001682 SmallVectorImpl<MCInst> &Instructions) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001683 MCInst tmpInst;
Toma Tabacua2861db2015-05-01 10:26:47 +00001684 if (ShiftAmount >= 32) {
1685 tmpInst.setOpcode(Mips::DSLL32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001686 tmpInst.addOperand(MCOperand::createReg(RegNo));
1687 tmpInst.addOperand(MCOperand::createReg(RegNo));
1688 tmpInst.addOperand(MCOperand::createImm(ShiftAmount - 32));
Toma Tabacua2861db2015-05-01 10:26:47 +00001689 tmpInst.setLoc(IDLoc);
1690 Instructions.push_back(tmpInst);
1691 tmpInst.clear();
1692 } else if (ShiftAmount > 0) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001693 tmpInst.setOpcode(Mips::DSLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00001694 tmpInst.addOperand(MCOperand::createReg(RegNo));
1695 tmpInst.addOperand(MCOperand::createReg(RegNo));
1696 tmpInst.addOperand(MCOperand::createImm(ShiftAmount));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001697 tmpInst.setLoc(IDLoc);
1698 Instructions.push_back(tmpInst);
1699 tmpInst.clear();
1700 }
Toma Tabacu7dea2e32015-04-28 14:06:35 +00001701 // There's no need for an ORi if the immediate is 0.
1702 if (Operand.isImm() && Operand.getImm() == 0)
1703 return;
1704
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001705 tmpInst.setOpcode(Mips::ORi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001706 tmpInst.addOperand(MCOperand::createReg(RegNo));
1707 tmpInst.addOperand(MCOperand::createReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001708 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001709 tmpInst.setLoc(IDLoc);
1710 Instructions.push_back(tmpInst);
1711}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001712
Toma Tabacua2861db2015-05-01 10:26:47 +00001713template <unsigned ShiftAmount>
Toma Tabacu61145652015-04-28 13:16:06 +00001714void createLShiftOri(int64_t Value, unsigned RegNo, SMLoc IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001715 SmallVectorImpl<MCInst> &Instructions) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001716 createLShiftOri<ShiftAmount>(MCOperand::createImm(Value), RegNo, IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001717 Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001718}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001719}
1720
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001721bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
1722 SmallVectorImpl<MCInst> &Instructions) {
1723 // Create a JALR instruction which is going to replace the pseudo-JAL.
1724 MCInst JalrInst;
1725 JalrInst.setLoc(IDLoc);
1726 const MCOperand FirstRegOp = Inst.getOperand(0);
1727 const unsigned Opcode = Inst.getOpcode();
1728
1729 if (Opcode == Mips::JalOneReg) {
1730 // jal $rs => jalr $rs
1731 if (inMicroMipsMode()) {
1732 JalrInst.setOpcode(Mips::JALR16_MM);
1733 JalrInst.addOperand(FirstRegOp);
1734 } else {
1735 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00001736 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001737 JalrInst.addOperand(FirstRegOp);
1738 }
1739 } else if (Opcode == Mips::JalTwoReg) {
1740 // jal $rd, $rs => jalr $rd, $rs
1741 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
1742 JalrInst.addOperand(FirstRegOp);
1743 const MCOperand SecondRegOp = Inst.getOperand(1);
1744 JalrInst.addOperand(SecondRegOp);
1745 }
1746 Instructions.push_back(JalrInst);
1747
1748 // If .set reorder is active, emit a NOP after it.
1749 if (AssemblerOptions.back()->isReorder()) {
1750 // This is a 32-bit NOP because these 2 pseudo-instructions
1751 // do not have a short delay slot.
1752 MCInst NopInst;
1753 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00001754 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
1755 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
1756 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001757 Instructions.push_back(NopInst);
1758 }
1759
1760 return false;
1761}
1762
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001763bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
1764 unsigned SrcReg, bool Is32BitImm, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001765 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00001766 if (!Is32BitImm && !isGP64bit()) {
1767 Error(IDLoc, "instruction requires a 64-bit architecture");
1768 return true;
1769 }
1770
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001771 bool UseSrcReg = false;
1772 if (SrcReg != Mips::NoRegister)
1773 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00001774
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001775 MCInst tmpInst;
1776
Jack Carter92995f12012-10-06 00:53:28 +00001777 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001778 // FIXME: gas has a special case for values that are 000...1111, which
1779 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001780 if (0 <= ImmValue && ImmValue <= 65535) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001781 // For unsigned and positive signed 16-bit values (0 <= j <= 65535):
Jack Carter30a59822012-10-04 04:03:53 +00001782 // li d,j => ori d,$zero,j
Toma Tabacudf7fd462015-05-13 16:02:41 +00001783 if (!UseSrcReg)
1784 SrcReg = isGP64bit() ? Mips::ZERO_64 : Mips::ZERO;
Jack Carter873c7242013-01-12 01:03:14 +00001785 tmpInst.setOpcode(Mips::ORi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001786 tmpInst.addOperand(MCOperand::createReg(DstReg));
1787 tmpInst.addOperand(MCOperand::createReg(SrcReg));
1788 tmpInst.addOperand(MCOperand::createImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001789 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001790 } else if (ImmValue < 0 && ImmValue >= -32768) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001791 // For negative signed 16-bit values (-32768 <= j < 0):
Jack Carter30a59822012-10-04 04:03:53 +00001792 // li d,j => addiu d,$zero,j
Toma Tabacudf7fd462015-05-13 16:02:41 +00001793 if (!UseSrcReg)
1794 SrcReg = Mips::ZERO;
Jack Carter873c7242013-01-12 01:03:14 +00001795 tmpInst.setOpcode(Mips::ADDiu);
Jim Grosbache9119e42015-05-13 18:37:00 +00001796 tmpInst.addOperand(MCOperand::createReg(DstReg));
1797 tmpInst.addOperand(MCOperand::createReg(SrcReg));
1798 tmpInst.addOperand(MCOperand::createImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001799 Instructions.push_back(tmpInst);
Toma Tabacua3d056f2015-05-15 09:42:11 +00001800 } else if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00001801 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00001802
Toma Tabacuae47f932015-04-10 13:28:16 +00001803 // For all other values which are representable as a 32-bit integer:
Jack Carter30a59822012-10-04 04:03:53 +00001804 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001805 // ori d,d,lo16(j)
Toma Tabacu79588102015-04-29 10:19:56 +00001806 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1807 uint16_t Bits15To0 = ImmValue & 0xffff;
1808
Toma Tabacua3d056f2015-05-15 09:42:11 +00001809 if (!Is32BitImm && !isInt<32>(ImmValue)) {
1810 // For DLI, expand to an ORi instead of a LUi to avoid sign-extending the
1811 // upper 32 bits.
1812 tmpInst.setOpcode(Mips::ORi);
1813 tmpInst.addOperand(MCOperand::createReg(DstReg));
1814 tmpInst.addOperand(MCOperand::createReg(Mips::ZERO));
1815 tmpInst.addOperand(MCOperand::createImm(Bits31To16));
1816 tmpInst.setLoc(IDLoc);
1817 Instructions.push_back(tmpInst);
1818 // Move the value to the upper 16 bits by doing a 16-bit left shift.
1819 createLShiftOri<16>(0, DstReg, IDLoc, Instructions);
1820 } else {
1821 tmpInst.setOpcode(Mips::LUi);
1822 tmpInst.addOperand(MCOperand::createReg(DstReg));
1823 tmpInst.addOperand(MCOperand::createImm(Bits31To16));
1824 Instructions.push_back(tmpInst);
1825 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001826 createLShiftOri<0>(Bits15To0, DstReg, IDLoc, Instructions);
1827
1828 if (UseSrcReg)
1829 createAddu(DstReg, DstReg, SrcReg, Instructions);
1830
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001831 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Toma Tabacu00e98672015-05-01 12:19:27 +00001832 if (Is32BitImm) {
1833 Error(IDLoc, "instruction requires a 32-bit immediate");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001834 return true;
1835 }
Toma Tabacu81496c12015-05-20 08:54:45 +00001836 warnIfNoMacro(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001837
1838 // <------- lo32 ------>
1839 // <------- hi32 ------>
1840 // <- hi16 -> <- lo16 ->
1841 // _________________________________
1842 // | | | |
Toma Tabacubda745f2015-04-27 15:21:38 +00001843 // | 16-bits | 16-bits | 16-bits |
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001844 // |__________|__________|__________|
1845 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001846 // For any 64-bit value that is representable as a 48-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001847 // li d,j => lui d,hi16(j)
1848 // ori d,d,hi16(lo32(j))
1849 // dsll d,d,16
1850 // ori d,d,lo16(lo32(j))
Toma Tabacu79588102015-04-29 10:19:56 +00001851 uint16_t Bits47To32 = (ImmValue >> 32) & 0xffff;
1852 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1853 uint16_t Bits15To0 = ImmValue & 0xffff;
1854
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001855 tmpInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001856 tmpInst.addOperand(MCOperand::createReg(DstReg));
1857 tmpInst.addOperand(MCOperand::createImm(Bits47To32));
Jack Carter30a59822012-10-04 04:03:53 +00001858 Instructions.push_back(tmpInst);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001859 createLShiftOri<0>(Bits31To16, DstReg, IDLoc, Instructions);
1860 createLShiftOri<16>(Bits15To0, DstReg, IDLoc, Instructions);
1861
1862 if (UseSrcReg)
1863 createAddu(DstReg, DstReg, SrcReg, Instructions);
1864
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001865 } else {
Toma Tabacu00e98672015-05-01 12:19:27 +00001866 if (Is32BitImm) {
1867 Error(IDLoc, "instruction requires a 32-bit immediate");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001868 return true;
1869 }
Toma Tabacu81496c12015-05-20 08:54:45 +00001870 warnIfNoMacro(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001871
1872 // <------- hi32 ------> <------- lo32 ------>
1873 // <- hi16 -> <- lo16 ->
1874 // ___________________________________________
1875 // | | | | |
Toma Tabacubda745f2015-04-27 15:21:38 +00001876 // | 16-bits | 16-bits | 16-bits | 16-bits |
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001877 // |__________|__________|__________|__________|
1878 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001879 // For all other values which are representable as a 64-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001880 // li d,j => lui d,hi16(j)
1881 // ori d,d,lo16(hi32(j))
1882 // dsll d,d,16
1883 // ori d,d,hi16(lo32(j))
1884 // dsll d,d,16
1885 // ori d,d,lo16(lo32(j))
Toma Tabacu79588102015-04-29 10:19:56 +00001886 uint16_t Bits63To48 = (ImmValue >> 48) & 0xffff;
1887 uint16_t Bits47To32 = (ImmValue >> 32) & 0xffff;
1888 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1889 uint16_t Bits15To0 = ImmValue & 0xffff;
1890
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001891 tmpInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001892 tmpInst.addOperand(MCOperand::createReg(DstReg));
1893 tmpInst.addOperand(MCOperand::createImm(Bits63To48));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001894 Instructions.push_back(tmpInst);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001895 createLShiftOri<0>(Bits47To32, DstReg, IDLoc, Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001896
1897 // When Bits31To16 is 0, do a left shift of 32 bits instead of doing
1898 // two left shifts of 16 bits.
1899 if (Bits31To16 == 0) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001900 createLShiftOri<32>(Bits15To0, DstReg, IDLoc, Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001901 } else {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001902 createLShiftOri<16>(Bits31To16, DstReg, IDLoc, Instructions);
1903 createLShiftOri<16>(Bits15To0, DstReg, IDLoc, Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001904 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001905
1906 if (UseSrcReg)
1907 createAddu(DstReg, DstReg, SrcReg, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001908 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001909 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001910}
Jack Carter92995f12012-10-06 00:53:28 +00001911
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001912bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
1913 SmallVectorImpl<MCInst> &Instructions) {
1914 const MCOperand &ImmOp = Inst.getOperand(1);
1915 assert(ImmOp.isImm() && "expected immediate operand kind");
1916 const MCOperand &DstRegOp = Inst.getOperand(0);
1917 assert(DstRegOp.isReg() && "expected register operand kind");
1918
1919 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
1920 Is32BitImm, IDLoc, Instructions))
1921 return true;
1922
1923 return false;
1924}
1925
Matheus Almeida3813d572014-06-19 14:39:14 +00001926bool
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001927MipsAsmParser::expandLoadAddressReg(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001928 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacub5592ee2015-05-14 10:02:58 +00001929 const MCOperand &DstRegOp = Inst.getOperand(0);
1930 assert(DstRegOp.isReg() && "expected register operand kind");
1931
Jack Carter543fdf82012-10-09 23:29:45 +00001932 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001933 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1934 "expected immediate operand kind");
1935 if (!ImmOp.isImm()) {
Toma Tabacu674825c2015-06-16 12:16:24 +00001936 if (loadSymbolAddress(ImmOp.getExpr(), DstRegOp.getReg(), Is32BitImm, IDLoc,
1937 Instructions))
1938 return true;
1939
Toma Tabacu0d64b202014-08-14 10:29:17 +00001940 return false;
1941 }
Jack Carter543fdf82012-10-09 23:29:45 +00001942 const MCOperand &SrcRegOp = Inst.getOperand(1);
1943 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001944
1945 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), SrcRegOp.getReg(),
1946 Is32BitImm, IDLoc, Instructions))
1947 return true;
1948
Matheus Almeida3813d572014-06-19 14:39:14 +00001949 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001950}
1951
Matheus Almeida3813d572014-06-19 14:39:14 +00001952bool
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001953MipsAsmParser::expandLoadAddressImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001954 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacub5592ee2015-05-14 10:02:58 +00001955 const MCOperand &DstRegOp = Inst.getOperand(0);
1956 assert(DstRegOp.isReg() && "expected register operand kind");
1957
Jack Carter543fdf82012-10-09 23:29:45 +00001958 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001959 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1960 "expected immediate operand kind");
1961 if (!ImmOp.isImm()) {
Toma Tabacu674825c2015-06-16 12:16:24 +00001962 if (loadSymbolAddress(ImmOp.getExpr(), DstRegOp.getReg(), Is32BitImm, IDLoc,
1963 Instructions))
1964 return true;
1965
Toma Tabacu0d64b202014-08-14 10:29:17 +00001966 return false;
1967 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001968
1969 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
1970 Is32BitImm, IDLoc, Instructions))
1971 return true;
1972
Matheus Almeida3813d572014-06-19 14:39:14 +00001973 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001974}
1975
Toma Tabacu674825c2015-06-16 12:16:24 +00001976bool MipsAsmParser::loadSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
1977 bool Is32BitSym, SMLoc IDLoc,
1978 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00001979 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00001980
Toma Tabacuec1de822015-05-14 10:53:40 +00001981 if (Is32BitSym && isABI_N64())
1982 Warning(IDLoc, "instruction loads the 32-bit address of a 64-bit symbol");
1983
Toma Tabacu0d64b202014-08-14 10:29:17 +00001984 MCInst tmpInst;
Toma Tabacu674825c2015-06-16 12:16:24 +00001985 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymExpr);
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00001986 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::create(
1987 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1988 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::create(
1989 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1990
Toma Tabacuec1de822015-05-14 10:53:40 +00001991 if (!Is32BitSym) {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001992 // If it's a 64-bit architecture, expand to:
1993 // la d,sym => lui d,highest(sym)
1994 // ori d,d,higher(sym)
1995 // dsll d,d,16
1996 // ori d,d,hi16(sym)
1997 // dsll d,d,16
1998 // ori d,d,lo16(sym)
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00001999 const MCSymbolRefExpr *HighestExpr = MCSymbolRefExpr::create(
2000 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
2001 const MCSymbolRefExpr *HigherExpr = MCSymbolRefExpr::create(
2002 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
Toma Tabacu0d64b202014-08-14 10:29:17 +00002003
2004 tmpInst.setOpcode(Mips::LUi);
Toma Tabacu674825c2015-06-16 12:16:24 +00002005 tmpInst.addOperand(MCOperand::createReg(DstReg));
Jim Grosbache9119e42015-05-13 18:37:00 +00002006 tmpInst.addOperand(MCOperand::createExpr(HighestExpr));
Toma Tabacu0d64b202014-08-14 10:29:17 +00002007 Instructions.push_back(tmpInst);
2008
Toma Tabacu674825c2015-06-16 12:16:24 +00002009 createLShiftOri<0>(MCOperand::createExpr(HigherExpr), DstReg, SMLoc(),
Toma Tabacua2861db2015-05-01 10:26:47 +00002010 Instructions);
Toma Tabacu674825c2015-06-16 12:16:24 +00002011 createLShiftOri<16>(MCOperand::createExpr(HiExpr), DstReg, SMLoc(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00002012 Instructions);
Toma Tabacu674825c2015-06-16 12:16:24 +00002013 createLShiftOri<16>(MCOperand::createExpr(LoExpr), DstReg, SMLoc(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00002014 Instructions);
2015 } else {
2016 // Otherwise, expand to:
2017 // la d,sym => lui d,hi16(sym)
2018 // ori d,d,lo16(sym)
2019 tmpInst.setOpcode(Mips::LUi);
Toma Tabacu674825c2015-06-16 12:16:24 +00002020 tmpInst.addOperand(MCOperand::createReg(DstReg));
Jim Grosbache9119e42015-05-13 18:37:00 +00002021 tmpInst.addOperand(MCOperand::createExpr(HiExpr));
Toma Tabacu0d64b202014-08-14 10:29:17 +00002022 Instructions.push_back(tmpInst);
2023
Toma Tabacu674825c2015-06-16 12:16:24 +00002024 createLShiftOri<0>(MCOperand::createExpr(LoExpr), DstReg, SMLoc(),
Toma Tabacua2861db2015-05-01 10:26:47 +00002025 Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00002026 }
Toma Tabacu674825c2015-06-16 12:16:24 +00002027 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002028}
2029
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002030bool MipsAsmParser::expandUncondBranchMMPseudo(
2031 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002032 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2033 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002034
2035 MCOperand Offset = Inst.getOperand(0);
2036 if (Offset.isExpr()) {
2037 Inst.clear();
2038 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002039 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2040 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2041 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002042 } else {
2043 assert(Offset.isImm() && "expected immediate operand kind");
2044 if (isIntN(11, Offset.getImm())) {
2045 // If offset fits into 11 bits then this instruction becomes microMIPS
2046 // 16-bit unconditional branch instruction.
2047 Inst.setOpcode(Mips::B16_MM);
2048 } else {
2049 if (!isIntN(17, Offset.getImm()))
2050 Error(IDLoc, "branch target out of range");
2051 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2052 Error(IDLoc, "branch to misaligned address");
2053 Inst.clear();
2054 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002055 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2056 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2057 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002058 }
2059 }
2060 Instructions.push_back(Inst);
2061
Toma Tabacu234482a2015-03-16 12:03:39 +00002062 // If .set reorder is active, emit a NOP after the branch instruction.
2063 if (AssemblerOptions.back()->isReorder())
2064 createNop(true, IDLoc, Instructions);
2065
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002066 return false;
2067}
2068
Toma Tabacue1e460d2015-06-11 10:36:10 +00002069bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2070 SmallVectorImpl<MCInst> &Instructions) {
2071 const MCOperand &DstRegOp = Inst.getOperand(0);
2072 assert(DstRegOp.isReg() && "expected register operand kind");
2073
2074 const MCOperand &ImmOp = Inst.getOperand(1);
2075 assert(ImmOp.isImm() && "expected immediate operand kind");
2076
2077 const MCOperand &MemOffsetOp = Inst.getOperand(2);
2078 assert(MemOffsetOp.isImm() && "expected immediate operand kind");
2079
2080 unsigned OpCode = 0;
2081 switch(Inst.getOpcode()) {
2082 case Mips::BneImm:
2083 OpCode = Mips::BNE;
2084 break;
2085 case Mips::BeqImm:
2086 OpCode = Mips::BEQ;
2087 break;
2088 default:
2089 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2090 break;
2091 }
2092
2093 int64_t ImmValue = ImmOp.getImm();
2094 if (ImmValue == 0) {
2095 MCInst BranchInst;
2096 BranchInst.setOpcode(OpCode);
2097 BranchInst.addOperand(DstRegOp);
2098 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2099 BranchInst.addOperand(MemOffsetOp);
2100 Instructions.push_back(BranchInst);
2101 } else {
2102 warnIfNoMacro(IDLoc);
2103
2104 unsigned ATReg = getATReg(IDLoc);
2105 if (!ATReg)
2106 return true;
2107
2108 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), IDLoc,
2109 Instructions))
2110 return true;
2111
2112 MCInst BranchInst;
2113 BranchInst.setOpcode(OpCode);
2114 BranchInst.addOperand(DstRegOp);
2115 BranchInst.addOperand(MCOperand::createReg(ATReg));
2116 BranchInst.addOperand(MemOffsetOp);
2117 Instructions.push_back(BranchInst);
2118 }
2119 return false;
2120}
2121
Jack Carter9e65aa32013-03-22 00:05:30 +00002122void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002123 SmallVectorImpl<MCInst> &Instructions,
2124 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002125 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00002126 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002127 const MCExpr *ExprOffset;
2128 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002129 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002130 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2131 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002132 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002133 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2134 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002135 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002136 if (isImmOpnd) {
2137 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2138 ImmOffset = Inst.getOperand(2).getImm();
2139 LoOffset = ImmOffset & 0x0000ffff;
2140 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002141 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002142 if (LoOffset & 0x8000)
2143 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002144 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002145 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002146 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002147 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002148 // These are some of the types of expansions we perform here:
2149 // 1) lw $8, sym => lui $8, %hi(sym)
2150 // lw $8, %lo(sym)($8)
2151 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2152 // add $8, $8, $9
2153 // lw $8, %lo(offset)($9)
2154 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2155 // add $at, $at, $8
2156 // lw $8, %lo(offset)($at)
2157 // 4) sw $8, sym => lui $at, %hi(sym)
2158 // sw $8, %lo(sym)($at)
2159 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2160 // add $at, $at, $8
2161 // sw $8, %lo(offset)($at)
2162 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2163 // ldc1 $f0, %lo(sym)($at)
2164 //
2165 // For load instructions we can use the destination register as a temporary
2166 // if base and dst are different (examples 1 and 2) and if the base register
2167 // is general purpose otherwise we must use $at (example 6) and error if it's
2168 // not available. For stores we must use $at (examples 4 and 5) because we
2169 // must not clobber the source register setting up the offset.
2170 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2171 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2172 unsigned RegClassIDOp0 =
2173 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2174 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2175 (RegClassIDOp0 == Mips::GPR64RegClassID);
2176 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002177 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002178 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002179 // At this point we need AT to perform the expansions and we exit if it is
2180 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002181 TmpRegNum = getATReg(IDLoc);
2182 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002183 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002184 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002185
Jack Carter9e65aa32013-03-22 00:05:30 +00002186 TempInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00002187 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002188 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002189 TempInst.addOperand(MCOperand::createImm(HiOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002190 else {
Toma Tabacu07c97b32015-06-17 10:43:45 +00002191 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
2192 TempInst.addOperand(MCOperand::createExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002193 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002194 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002195 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002196 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002197 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002198 // Add temp register to base.
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002199 if (BaseRegNum != Mips::ZERO) {
2200 TempInst.setOpcode(Mips::ADDu);
Jim Grosbache9119e42015-05-13 18:37:00 +00002201 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2202 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2203 TempInst.addOperand(MCOperand::createReg(BaseRegNum));
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002204 Instructions.push_back(TempInst);
2205 TempInst.clear();
2206 }
Alp Tokercb402912014-01-24 17:20:08 +00002207 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002208 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002209 TempInst.setOpcode(Inst.getOpcode());
Jim Grosbache9119e42015-05-13 18:37:00 +00002210 TempInst.addOperand(MCOperand::createReg(RegOpNum));
2211 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002212 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002213 TempInst.addOperand(MCOperand::createImm(LoOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002214 else {
Toma Tabacu07c97b32015-06-17 10:43:45 +00002215 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
2216 TempInst.addOperand(MCOperand::createExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002217 }
2218 Instructions.push_back(TempInst);
2219 TempInst.clear();
2220}
2221
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002222bool
2223MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2224 SmallVectorImpl<MCInst> &Instructions) {
2225 unsigned OpNum = Inst.getNumOperands();
2226 unsigned Opcode = Inst.getOpcode();
2227 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2228
2229 assert (Inst.getOperand(OpNum - 1).isImm() &&
2230 Inst.getOperand(OpNum - 2).isReg() &&
2231 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2232
2233 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2234 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2235 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2236 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2237 // It can be implemented as SWM16 or LWM16 instruction.
2238 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2239
2240 Inst.setOpcode(NewOpcode);
2241 Instructions.push_back(Inst);
2242 return false;
2243}
2244
Toma Tabacu1a108322015-06-17 13:20:24 +00002245bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2246 SmallVectorImpl<MCInst> &Instructions) {
2247 unsigned PseudoOpcode = Inst.getOpcode();
2248 unsigned SrcReg = Inst.getOperand(0).getReg();
2249 unsigned TrgReg = Inst.getOperand(1).getReg();
2250 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2251
2252 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
2253 bool ReverseOrderSLT, IsUnsigned, AcceptsEquality;
2254
2255 switch (PseudoOpcode) {
2256 case Mips::BLT:
2257 case Mips::BLTU:
2258 AcceptsEquality = false;
2259 ReverseOrderSLT = false;
2260 IsUnsigned = (PseudoOpcode == Mips::BLTU);
2261 ZeroSrcOpcode = Mips::BGTZ;
2262 ZeroTrgOpcode = Mips::BLTZ;
2263 break;
2264 case Mips::BLE:
2265 case Mips::BLEU:
2266 AcceptsEquality = true;
2267 ReverseOrderSLT = true;
2268 IsUnsigned = (PseudoOpcode == Mips::BLEU);
2269 ZeroSrcOpcode = Mips::BGEZ;
2270 ZeroTrgOpcode = Mips::BLEZ;
2271 break;
2272 case Mips::BGE:
2273 case Mips::BGEU:
2274 AcceptsEquality = true;
2275 ReverseOrderSLT = false;
2276 IsUnsigned = (PseudoOpcode == Mips::BGEU);
2277 ZeroSrcOpcode = Mips::BLEZ;
2278 ZeroTrgOpcode = Mips::BGEZ;
2279 break;
2280 case Mips::BGT:
2281 case Mips::BGTU:
2282 AcceptsEquality = false;
2283 ReverseOrderSLT = true;
2284 IsUnsigned = (PseudoOpcode == Mips::BGTU);
2285 ZeroSrcOpcode = Mips::BLTZ;
2286 ZeroTrgOpcode = Mips::BGTZ;
2287 break;
2288 default:
2289 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2290 }
2291
2292 MCInst BranchInst;
2293 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2294 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2295 if (IsSrcRegZero && IsTrgRegZero) {
2296 // FIXME: All of these Opcode-specific if's are needed for compatibility
2297 // with GAS' behaviour. However, they may not generate the most efficient
2298 // code in some circumstances.
2299 if (PseudoOpcode == Mips::BLT) {
2300 BranchInst.setOpcode(Mips::BLTZ);
2301 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2302 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2303 Instructions.push_back(BranchInst);
2304 return false;
2305 }
2306 if (PseudoOpcode == Mips::BLE) {
2307 BranchInst.setOpcode(Mips::BLEZ);
2308 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2309 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2310 Instructions.push_back(BranchInst);
2311 Warning(IDLoc, "branch is always taken");
2312 return false;
2313 }
2314 if (PseudoOpcode == Mips::BGE) {
2315 BranchInst.setOpcode(Mips::BGEZ);
2316 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2317 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2318 Instructions.push_back(BranchInst);
2319 Warning(IDLoc, "branch is always taken");
2320 return false;
2321 }
2322 if (PseudoOpcode == Mips::BGT) {
2323 BranchInst.setOpcode(Mips::BGTZ);
2324 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2325 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2326 Instructions.push_back(BranchInst);
2327 return false;
2328 }
2329 if (PseudoOpcode == Mips::BGTU) {
2330 BranchInst.setOpcode(Mips::BNE);
2331 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2332 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2333 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2334 Instructions.push_back(BranchInst);
2335 return false;
2336 }
2337 if (AcceptsEquality) {
2338 // If both registers are $0 and the pseudo-branch accepts equality, it
2339 // will always be taken, so we emit an unconditional branch.
2340 BranchInst.setOpcode(Mips::BEQ);
2341 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2342 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2343 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2344 Instructions.push_back(BranchInst);
2345 Warning(IDLoc, "branch is always taken");
2346 return false;
2347 }
2348 // If both registers are $0 and the pseudo-branch does not accept
2349 // equality, it will never be taken, so we don't have to emit anything.
2350 return false;
2351 }
2352 if (IsSrcRegZero || IsTrgRegZero) {
2353 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2354 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2355 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2356 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2357 // the pseudo-branch will never be taken, so we don't emit anything.
2358 // This only applies to unsigned pseudo-branches.
2359 return false;
2360 }
2361 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2362 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2363 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2364 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2365 // the pseudo-branch will always be taken, so we emit an unconditional
2366 // branch.
2367 // This only applies to unsigned pseudo-branches.
2368 BranchInst.setOpcode(Mips::BEQ);
2369 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2370 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2371 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2372 Instructions.push_back(BranchInst);
2373 Warning(IDLoc, "branch is always taken");
2374 return false;
2375 }
2376 if (IsUnsigned) {
2377 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2378 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2379 // the pseudo-branch will be taken only when the non-zero register is
2380 // different from 0, so we emit a BNEZ.
2381 //
2382 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2383 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2384 // the pseudo-branch will be taken only when the non-zero register is
2385 // equal to 0, so we emit a BEQZ.
2386 //
2387 // Because only BLEU and BGEU branch on equality, we can use the
2388 // AcceptsEquality variable to decide when to emit the BEQZ.
2389 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQ : Mips::BNE);
2390 BranchInst.addOperand(
2391 MCOperand::createReg(IsSrcRegZero ? TrgReg : SrcReg));
2392 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2393 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2394 Instructions.push_back(BranchInst);
2395 return false;
2396 }
2397 // If we have a signed pseudo-branch and one of the registers is $0,
2398 // we can use an appropriate compare-to-zero branch. We select which one
2399 // to use in the switch statement above.
2400 BranchInst.setOpcode(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode);
2401 BranchInst.addOperand(MCOperand::createReg(IsSrcRegZero ? TrgReg : SrcReg));
2402 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2403 Instructions.push_back(BranchInst);
2404 return false;
2405 }
2406
2407 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2408 // expansions. If it is not available, we return.
2409 unsigned ATRegNum = getATReg(IDLoc);
2410 if (!ATRegNum)
2411 return true;
2412
2413 warnIfNoMacro(IDLoc);
2414
2415 // SLT fits well with 2 of our 4 pseudo-branches:
2416 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2417 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2418 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2419 // This is accomplished by using a BNEZ with the result of the SLT.
2420 //
2421 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2422 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2423 // Because only BGE and BLE branch on equality, we can use the
2424 // AcceptsEquality variable to decide when to emit the BEQZ.
2425 // Note that the order of the SLT arguments doesn't change between
2426 // opposites.
2427 //
2428 // The same applies to the unsigned variants, except that SLTu is used
2429 // instead of SLT.
2430 MCInst SetInst;
2431 SetInst.setOpcode(IsUnsigned ? Mips::SLTu : Mips::SLT);
2432 SetInst.addOperand(MCOperand::createReg(ATRegNum));
2433 SetInst.addOperand(MCOperand::createReg(ReverseOrderSLT ? TrgReg : SrcReg));
2434 SetInst.addOperand(MCOperand::createReg(ReverseOrderSLT ? SrcReg : TrgReg));
2435 Instructions.push_back(SetInst);
2436
2437 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQ : Mips::BNE);
2438 BranchInst.addOperand(MCOperand::createReg(ATRegNum));
2439 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2440 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2441 Instructions.push_back(BranchInst);
2442 return false;
2443}
2444
Toma Tabacu234482a2015-03-16 12:03:39 +00002445void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
2446 SmallVectorImpl<MCInst> &Instructions) {
2447 MCInst NopInst;
2448 if (hasShortDelaySlot) {
2449 NopInst.setOpcode(Mips::MOVE16_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002450 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2451 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
Toma Tabacu234482a2015-03-16 12:03:39 +00002452 } else {
2453 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00002454 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2455 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2456 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu234482a2015-03-16 12:03:39 +00002457 }
2458 Instructions.push_back(NopInst);
2459}
2460
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002461void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
2462 unsigned TrgReg,
2463 SmallVectorImpl<MCInst> &Instructions) {
2464 MCInst AdduInst;
2465 AdduInst.setOpcode(Mips::ADDu);
Jim Grosbache9119e42015-05-13 18:37:00 +00002466 AdduInst.addOperand(MCOperand::createReg(DstReg));
2467 AdduInst.addOperand(MCOperand::createReg(SrcReg));
2468 AdduInst.addOperand(MCOperand::createReg(TrgReg));
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002469 Instructions.push_back(AdduInst);
2470}
2471
Matheus Almeida595fcab2014-06-11 15:05:56 +00002472unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
2473 // As described by the Mips32r2 spec, the registers Rd and Rs for
2474 // jalr.hb must be different.
2475 unsigned Opcode = Inst.getOpcode();
2476
2477 if (Opcode == Mips::JALR_HB &&
2478 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
2479 return Match_RequiresDifferentSrcAndDst;
2480
2481 return Match_Success;
2482}
2483
David Blaikie960ea3f2014-06-08 16:18:35 +00002484bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
2485 OperandVector &Operands,
2486 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00002487 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00002488 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00002489
Jack Carterb4dbc172012-09-05 23:34:03 +00002490 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00002491 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00002492 unsigned MatchResult =
2493 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00002494
2495 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002496 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002497 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00002498 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00002499 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00002500 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00002501 return false;
2502 }
2503 case Match_MissingFeature:
2504 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
2505 return true;
2506 case Match_InvalidOperand: {
2507 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00002508 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002509 if (ErrorInfo >= Operands.size())
2510 return Error(IDLoc, "too few operands for instruction");
2511
David Blaikie960ea3f2014-06-08 16:18:35 +00002512 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00002513 if (ErrorLoc == SMLoc())
2514 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00002515 }
2516
2517 return Error(ErrorLoc, "invalid operand for instruction");
2518 }
2519 case Match_MnemonicFail:
2520 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00002521 case Match_RequiresDifferentSrcAndDst:
2522 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00002523 }
Craig Topper589ceee2015-01-03 08:16:34 +00002524
2525 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00002526}
2527
Toma Tabacud9d344b2015-04-27 14:05:04 +00002528void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
2529 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
2530 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
2531 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002532}
2533
Toma Tabacu81496c12015-05-20 08:54:45 +00002534void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
2535 if (!AssemblerOptions.back()->isMacro())
2536 Warning(Loc, "macro instruction expanded into multiple instructions");
2537}
2538
Daniel Sandersef638fe2014-10-03 15:37:37 +00002539void
2540MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
2541 SMRange Range, bool ShowColors) {
2542 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00002543 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00002544 ShowColors);
2545}
2546
Jack Carter1ac53222013-02-20 23:11:17 +00002547int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002548 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002549
Vladimir Medic4c299852013-11-06 11:27:05 +00002550 CC = StringSwitch<unsigned>(Name)
2551 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002552 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00002553 .Case("a0", 4)
2554 .Case("a1", 5)
2555 .Case("a2", 6)
2556 .Case("a3", 7)
2557 .Case("v0", 2)
2558 .Case("v1", 3)
2559 .Case("s0", 16)
2560 .Case("s1", 17)
2561 .Case("s2", 18)
2562 .Case("s3", 19)
2563 .Case("s4", 20)
2564 .Case("s5", 21)
2565 .Case("s6", 22)
2566 .Case("s7", 23)
2567 .Case("k0", 26)
2568 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002569 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00002570 .Case("sp", 29)
2571 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002572 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00002573 .Case("ra", 31)
2574 .Case("t0", 8)
2575 .Case("t1", 9)
2576 .Case("t2", 10)
2577 .Case("t3", 11)
2578 .Case("t4", 12)
2579 .Case("t5", 13)
2580 .Case("t6", 14)
2581 .Case("t7", 15)
2582 .Case("t8", 24)
2583 .Case("t9", 25)
2584 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002585
Toma Tabacufda445c2014-09-15 15:33:01 +00002586 if (!(isABI_N32() || isABI_N64()))
2587 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002588
Daniel Sandersef638fe2014-10-03 15:37:37 +00002589 if (12 <= CC && CC <= 15) {
2590 // Name is one of t4-t7
2591 AsmToken RegTok = getLexer().peekTok();
2592 SMRange RegRange = RegTok.getLocRange();
2593
2594 StringRef FixedName = StringSwitch<StringRef>(Name)
2595 .Case("t4", "t0")
2596 .Case("t5", "t1")
2597 .Case("t6", "t2")
2598 .Case("t7", "t3")
2599 .Default("");
2600 assert(FixedName != "" && "Register name is not one of t4-t7.");
2601
2602 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
2603 "Did you mean $" + FixedName + "?", RegRange);
2604 }
2605
Toma Tabacufda445c2014-09-15 15:33:01 +00002606 // Although SGI documentation just cuts out t0-t3 for n32/n64,
2607 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
2608 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
2609 if (8 <= CC && CC <= 11)
2610 CC += 4;
2611
2612 if (CC == -1)
2613 CC = StringSwitch<unsigned>(Name)
2614 .Case("a4", 8)
2615 .Case("a5", 9)
2616 .Case("a6", 10)
2617 .Case("a7", 11)
2618 .Case("kt0", 26)
2619 .Case("kt1", 27)
2620 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002621
2622 return CC;
2623}
Jack Carterd0bd6422013-04-18 00:41:53 +00002624
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002625int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
2626 int CC;
2627
2628 CC = StringSwitch<unsigned>(Name)
2629 .Case("hwr_cpunum", 0)
2630 .Case("hwr_synci_step", 1)
2631 .Case("hwr_cc", 2)
2632 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00002633 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002634 .Default(-1);
2635
2636 return CC;
2637}
2638
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002639int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002640
Jack Cartera63b16a2012-09-07 00:23:42 +00002641 if (Name[0] == 'f') {
2642 StringRef NumString = Name.substr(1);
2643 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002644 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002645 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002646 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00002647 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002648 return IntVal;
2649 }
2650 return -1;
2651}
Jack Cartera63b16a2012-09-07 00:23:42 +00002652
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002653int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
2654
2655 if (Name.startswith("fcc")) {
2656 StringRef NumString = Name.substr(3);
2657 unsigned IntVal;
2658 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002659 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002660 if (IntVal > 7) // There are only 8 fcc registers.
2661 return -1;
2662 return IntVal;
2663 }
2664 return -1;
2665}
2666
2667int MipsAsmParser::matchACRegisterName(StringRef Name) {
2668
Akira Hatanaka274d24c2013-08-14 01:15:52 +00002669 if (Name.startswith("ac")) {
2670 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002671 unsigned IntVal;
2672 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002673 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002674 if (IntVal > 3) // There are only 3 acc registers.
2675 return -1;
2676 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00002677 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002678 return -1;
2679}
Jack Carterd0bd6422013-04-18 00:41:53 +00002680
Jack Carter5dc8ac92013-09-25 23:50:44 +00002681int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
2682 unsigned IntVal;
2683
2684 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2685 return -1;
2686
2687 if (IntVal > 31)
2688 return -1;
2689
2690 return IntVal;
2691}
2692
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002693int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
2694 int CC;
2695
2696 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00002697 .Case("msair", 0)
2698 .Case("msacsr", 1)
2699 .Case("msaaccess", 2)
2700 .Case("msasave", 3)
2701 .Case("msamodify", 4)
2702 .Case("msarequest", 5)
2703 .Case("msamap", 6)
2704 .Case("msaunmap", 7)
2705 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002706
2707 return CC;
2708}
2709
Toma Tabacu89a712b2015-04-15 10:48:56 +00002710unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00002711 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00002712 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002713 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00002714 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00002715 return 0;
2716 }
2717 unsigned AT = getReg(
2718 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00002719 return AT;
2720}
Jack Carter0b744b32012-10-04 02:29:46 +00002721
Jack Carterd0bd6422013-04-18 00:41:53 +00002722unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00002723 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00002724}
2725
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002726unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002727 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00002728 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002729}
2730
Jack Carter873c7242013-01-12 01:03:14 +00002731int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002732 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00002733 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00002734 return -1;
2735
Jack Carter873c7242013-01-12 01:03:14 +00002736 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00002737}
2738
Toma Tabacu13964452014-09-04 13:23:44 +00002739bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002740 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002741 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002742
Jack Carter30a59822012-10-04 04:03:53 +00002743 // Check if the current operand has a custom associated parser, if so, try to
2744 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00002745 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2746 if (ResTy == MatchOperand_Success)
2747 return false;
2748 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2749 // there was a match, but an error occurred, in which case, just return that
2750 // the operand parsing failed.
2751 if (ResTy == MatchOperand_ParseFail)
2752 return true;
2753
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002754 DEBUG(dbgs() << ".. Generic Parser\n");
2755
Jack Carterb4dbc172012-09-05 23:34:03 +00002756 switch (getLexer().getKind()) {
2757 default:
2758 Error(Parser.getTok().getLoc(), "unexpected token in operand");
2759 return true;
2760 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002761 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00002762 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00002763
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002764 // Almost all registers have been parsed by custom parsers. There is only
2765 // one exception to this. $zero (and it's alias $0) will reach this point
2766 // for div, divu, and similar instructions because it is not an operand
2767 // to the instruction definition but an explicit register. Special case
2768 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00002769 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00002770 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002771
Jack Carterd0bd6422013-04-18 00:41:53 +00002772 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00002773 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002774 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00002775 return true;
2776
Jack Carter873c7242013-01-12 01:03:14 +00002777 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00002778 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00002779 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00002780 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002781 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00002782
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002783 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002784 return false;
2785 }
Vladimir Medic4c299852013-11-06 11:27:05 +00002786 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00002787 case AsmToken::LParen:
2788 case AsmToken::Minus:
2789 case AsmToken::Plus:
2790 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002791 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00002792 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002793 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002794 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002795 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00002796 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00002797 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002798 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002799 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002800 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00002801 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00002802 return true;
2803
Jack Carter873c7242013-01-12 01:03:14 +00002804 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2805
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002806 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00002807 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002808 } // case AsmToken::Percent
2809 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00002810 return true;
2811}
2812
Vladimir Medic4c299852013-11-06 11:27:05 +00002813const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00002814 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00002815 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00002816 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002817 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00002818 // It's a constant, evaluate reloc value.
2819 int16_t Val;
2820 switch (getVariantKind(RelocStr)) {
2821 case MCSymbolRefExpr::VK_Mips_ABS_LO:
2822 // Get the 1st 16-bits.
2823 Val = MCE->getValue() & 0xffff;
2824 break;
2825 case MCSymbolRefExpr::VK_Mips_ABS_HI:
2826 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2827 // 16 bits being negative.
2828 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2829 break;
2830 case MCSymbolRefExpr::VK_Mips_HIGHER:
2831 // Get the 3rd 16-bits.
2832 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2833 break;
2834 case MCSymbolRefExpr::VK_Mips_HIGHEST:
2835 // Get the 4th 16-bits.
2836 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2837 break;
2838 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00002839 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00002840 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00002841 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002842 }
2843
Jack Carterb5cf5902013-04-17 00:18:04 +00002844 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002845 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00002846 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00002847 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00002848 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002849 return Res;
2850 }
2851
2852 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00002853 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2854
Sasa Stankovic06c47802014-04-03 10:37:45 +00002855 // Try to create target expression.
2856 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00002857 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002858
Jack Carterd0bd6422013-04-18 00:41:53 +00002859 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2860 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00002861 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002862 return Res;
2863 }
2864
2865 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002866 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00002867 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00002868 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002869 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002870 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002871 return Expr;
2872}
2873
2874bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2875
2876 switch (Expr->getKind()) {
2877 case MCExpr::Constant:
2878 return true;
2879 case MCExpr::SymbolRef:
2880 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2881 case MCExpr::Binary:
2882 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2883 if (!isEvaluated(BE->getLHS()))
2884 return false;
2885 return isEvaluated(BE->getRHS());
2886 }
2887 case MCExpr::Unary:
2888 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002889 case MCExpr::Target:
2890 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002891 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002892 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002893}
Jack Carterd0bd6422013-04-18 00:41:53 +00002894
Jack Carterb5cf5902013-04-17 00:18:04 +00002895bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002896 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00002897 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002898 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002899 if (Tok.isNot(AsmToken::Identifier))
2900 return true;
2901
Yaron Keren075759a2015-03-30 15:42:36 +00002902 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00002903
Jack Carterd0bd6422013-04-18 00:41:53 +00002904 Parser.Lex(); // Eat the identifier.
2905 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002906 const MCExpr *IdVal;
2907 SMLoc EndLoc;
2908
2909 if (getLexer().getKind() == AsmToken::LParen) {
2910 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002911 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002912 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002913 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002914 const AsmToken &nextTok = Parser.getTok();
2915 if (nextTok.isNot(AsmToken::Identifier))
2916 return true;
2917 Str += "(%";
2918 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002919 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002920 if (getLexer().getKind() != AsmToken::LParen)
2921 return true;
2922 } else
2923 break;
2924 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002925 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002926 return true;
2927
2928 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002929 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002930
2931 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002932 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002933
Jack Carterd0bd6422013-04-18 00:41:53 +00002934 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002935 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002936}
2937
Jack Carterb4dbc172012-09-05 23:34:03 +00002938bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2939 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002940 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002941 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002942 if (ResTy == MatchOperand_Success) {
2943 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002944 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002945 StartLoc = Operand.getStartLoc();
2946 EndLoc = Operand.getEndLoc();
2947
2948 // AFAIK, we only support numeric registers and named GPR's in CFI
2949 // directives.
2950 // Don't worry about eating tokens before failing. Using an unrecognised
2951 // register is a parse error.
2952 if (Operand.isGPRAsmReg()) {
2953 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002954 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002955 }
2956
2957 return (RegNo == (unsigned)-1);
2958 }
2959
2960 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002961 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002962}
2963
Jack Carterb5cf5902013-04-17 00:18:04 +00002964bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002965 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00002966 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002967 bool Result = true;
2968
2969 while (getLexer().getKind() == AsmToken::LParen)
2970 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002971
Jack Carterd0bd6422013-04-18 00:41:53 +00002972 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002973 default:
2974 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002975 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002976 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002977 case AsmToken::Integer:
2978 case AsmToken::Minus:
2979 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002980 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002981 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002982 else
2983 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002984 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002985 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002986 break;
Jack Carter873c7242013-01-12 01:03:14 +00002987 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002988 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002989 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002990 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002991}
2992
David Blaikie960ea3f2014-06-08 16:18:35 +00002993MipsAsmParser::OperandMatchResultTy
2994MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002995 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002996 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002997 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002998 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002999 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003000 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00003001 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00003002 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00003003
Jack Carterb5cf5902013-04-17 00:18:04 +00003004 if (getLexer().getKind() == AsmToken::LParen) {
3005 Parser.Lex();
3006 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003007 }
3008
Jack Carterb5cf5902013-04-17 00:18:04 +00003009 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003010 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00003011 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003012
Jack Carterd0bd6422013-04-18 00:41:53 +00003013 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003014 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003015 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
3016 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003017 SMLoc E =
3018 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003019 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003020 return MatchOperand_Success;
3021 }
3022 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003023 SMLoc E =
3024 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00003025
Jack Carterd0bd6422013-04-18 00:41:53 +00003026 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003027 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00003028 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003029 S, E, *this);
3030 Operands.push_back(
3031 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003032 return MatchOperand_Success;
3033 }
3034 Error(Parser.getTok().getLoc(), "'(' expected");
3035 return MatchOperand_ParseFail;
3036 }
3037
Jack Carterd0bd6422013-04-18 00:41:53 +00003038 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003039 }
3040
Toma Tabacu13964452014-09-04 13:23:44 +00003041 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003042 if (Res != MatchOperand_Success)
3043 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003044
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003045 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003046 Error(Parser.getTok().getLoc(), "')' expected");
3047 return MatchOperand_ParseFail;
3048 }
3049
Jack Carter873c7242013-01-12 01:03:14 +00003050 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3051
Jack Carterd0bd6422013-04-18 00:41:53 +00003052 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003053
Craig Topper062a2ba2014-04-25 05:30:21 +00003054 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003055 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003056
Jack Carterd0bd6422013-04-18 00:41:53 +00003057 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00003058 std::unique_ptr<MipsOperand> op(
3059 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00003060 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003061 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003062 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00003063 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003064 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
3065 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003066 if (IdVal->evaluateAsAbsolute(Imm))
3067 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003068 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003069 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00003070 getContext());
3071 }
3072
David Blaikie960ea3f2014-06-08 16:18:35 +00003073 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003074 return MatchOperand_Success;
3075}
3076
David Blaikie960ea3f2014-06-08 16:18:35 +00003077bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003078 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00003079 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00003080 if (Sym) {
3081 SMLoc S = Parser.getTok().getLoc();
3082 const MCExpr *Expr;
3083 if (Sym->isVariable())
3084 Expr = Sym->getVariableValue();
3085 else
3086 return false;
3087 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003088 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00003089 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00003090 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003091 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003092 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00003093 if (ResTy == MatchOperand_Success) {
3094 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00003095 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00003096 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003097 llvm_unreachable("Should never ParseFail");
3098 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00003099 }
3100 } else if (Expr->getKind() == MCExpr::Constant) {
3101 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00003102 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00003103 Operands.push_back(
3104 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00003105 return true;
3106 }
3107 }
3108 return false;
3109}
Jack Carterd0bd6422013-04-18 00:41:53 +00003110
Jack Carter873c7242013-01-12 01:03:14 +00003111MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003112MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00003113 StringRef Identifier,
3114 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003115 int Index = matchCPURegisterName(Identifier);
3116 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003117 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003118 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3119 return MatchOperand_Success;
3120 }
3121
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003122 Index = matchHWRegsRegisterName(Identifier);
3123 if (Index != -1) {
3124 Operands.push_back(MipsOperand::createHWRegsReg(
3125 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3126 return MatchOperand_Success;
3127 }
3128
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003129 Index = matchFPURegisterName(Identifier);
3130 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003131 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003132 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3133 return MatchOperand_Success;
3134 }
3135
3136 Index = matchFCCRegisterName(Identifier);
3137 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003138 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003139 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3140 return MatchOperand_Success;
3141 }
3142
3143 Index = matchACRegisterName(Identifier);
3144 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003145 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003146 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3147 return MatchOperand_Success;
3148 }
3149
3150 Index = matchMSA128RegisterName(Identifier);
3151 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003152 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003153 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3154 return MatchOperand_Success;
3155 }
3156
3157 Index = matchMSA128CtrlRegisterName(Identifier);
3158 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003159 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003160 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3161 return MatchOperand_Success;
3162 }
3163
3164 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00003165}
3166
3167MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003168MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003169 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00003170 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003171
3172 if (Token.is(AsmToken::Identifier)) {
3173 DEBUG(dbgs() << ".. identifier\n");
3174 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00003175 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003176 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00003177 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003178 } else if (Token.is(AsmToken::Integer)) {
3179 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003180 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003181 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
3182 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003183 return MatchOperand_Success;
3184 }
3185
3186 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
3187
3188 return MatchOperand_NoMatch;
3189}
3190
David Blaikie960ea3f2014-06-08 16:18:35 +00003191MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003192MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003193 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003194 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003195
3196 auto Token = Parser.getTok();
3197
3198 SMLoc S = Token.getLoc();
3199
3200 if (Token.isNot(AsmToken::Dollar)) {
3201 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
3202 if (Token.is(AsmToken::Identifier)) {
3203 if (searchSymbolAlias(Operands))
3204 return MatchOperand_Success;
3205 }
3206 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
3207 return MatchOperand_NoMatch;
3208 }
3209 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003210
Toma Tabacu13964452014-09-04 13:23:44 +00003211 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00003212 if (ResTy == MatchOperand_Success) {
3213 Parser.Lex(); // $
3214 Parser.Lex(); // identifier
3215 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003216 return ResTy;
3217}
3218
3219MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003220MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003221 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003222 switch (getLexer().getKind()) {
3223 default:
3224 return MatchOperand_NoMatch;
3225 case AsmToken::LParen:
3226 case AsmToken::Minus:
3227 case AsmToken::Plus:
3228 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003229 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003230 case AsmToken::String:
3231 break;
3232 }
3233
3234 const MCExpr *IdVal;
3235 SMLoc S = Parser.getTok().getLoc();
3236 if (getParser().parseExpression(IdVal))
3237 return MatchOperand_ParseFail;
3238
3239 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3240 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
3241 return MatchOperand_Success;
3242}
3243
David Blaikie960ea3f2014-06-08 16:18:35 +00003244MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003245MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003246 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003247 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003248
3249 SMLoc S = getLexer().getLoc();
3250
3251 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00003252 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003253 if (ResTy != MatchOperand_NoMatch)
3254 return ResTy;
3255
Daniel Sanders315386c2014-04-01 10:40:14 +00003256 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00003257 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00003258 if (ResTy != MatchOperand_NoMatch)
3259 return ResTy;
3260
Daniel Sandersffd84362014-04-01 10:41:48 +00003261 const MCExpr *Expr = nullptr;
3262 if (Parser.parseExpression(Expr)) {
3263 // We have no way of knowing if a symbol was consumed so we must ParseFail
3264 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003265 }
Daniel Sandersffd84362014-04-01 10:41:48 +00003266 Operands.push_back(
3267 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003268 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00003269}
3270
Vladimir Medic2b953d02013-10-01 09:48:56 +00003271MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00003272MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003273 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00003274 const MCExpr *IdVal;
3275 // If the first token is '$' we may have register operand.
3276 if (Parser.getTok().is(AsmToken::Dollar))
3277 return MatchOperand_NoMatch;
3278 SMLoc S = Parser.getTok().getLoc();
3279 if (getParser().parseExpression(IdVal))
3280 return MatchOperand_ParseFail;
3281 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00003282 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00003283 int64_t Val = MCE->getValue();
3284 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3285 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003286 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00003287 return MatchOperand_Success;
3288}
3289
Matheus Almeida779c5932013-11-18 12:32:49 +00003290MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003291MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003292 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00003293 switch (getLexer().getKind()) {
3294 default:
3295 return MatchOperand_NoMatch;
3296 case AsmToken::LParen:
3297 case AsmToken::Plus:
3298 case AsmToken::Minus:
3299 case AsmToken::Integer:
3300 break;
3301 }
3302
3303 const MCExpr *Expr;
3304 SMLoc S = Parser.getTok().getLoc();
3305
3306 if (getParser().parseExpression(Expr))
3307 return MatchOperand_ParseFail;
3308
3309 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003310 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00003311 Error(S, "expected immediate value");
3312 return MatchOperand_ParseFail;
3313 }
3314
3315 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
3316 // and because the CPU always adds one to the immediate field, the allowed
3317 // range becomes 1..4. We'll only check the range here and will deal
3318 // with the addition/subtraction when actually decoding/encoding
3319 // the instruction.
3320 if (Val < 1 || Val > 4) {
3321 Error(S, "immediate not in range (1..4)");
3322 return MatchOperand_ParseFail;
3323 }
3324
Jack Carter3b2c96e2014-01-22 23:31:38 +00003325 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003326 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00003327 return MatchOperand_Success;
3328}
3329
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00003330MipsAsmParser::OperandMatchResultTy
3331MipsAsmParser::parseRegisterList(OperandVector &Operands) {
3332 MCAsmParser &Parser = getParser();
3333 SmallVector<unsigned, 10> Regs;
3334 unsigned RegNo;
3335 unsigned PrevReg = Mips::NoRegister;
3336 bool RegRange = false;
3337 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3338
3339 if (Parser.getTok().isNot(AsmToken::Dollar))
3340 return MatchOperand_ParseFail;
3341
3342 SMLoc S = Parser.getTok().getLoc();
3343 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
3344 SMLoc E = getLexer().getLoc();
3345 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
3346 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
3347 if (RegRange) {
3348 // Remove last register operand because registers from register range
3349 // should be inserted first.
3350 if (RegNo == Mips::RA) {
3351 Regs.push_back(RegNo);
3352 } else {
3353 unsigned TmpReg = PrevReg + 1;
3354 while (TmpReg <= RegNo) {
3355 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
3356 Error(E, "invalid register operand");
3357 return MatchOperand_ParseFail;
3358 }
3359
3360 PrevReg = TmpReg;
3361 Regs.push_back(TmpReg++);
3362 }
3363 }
3364
3365 RegRange = false;
3366 } else {
3367 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
3368 (RegNo != Mips::RA)) {
3369 Error(E, "$16 or $31 expected");
3370 return MatchOperand_ParseFail;
3371 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
3372 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3373 Error(E, "invalid register operand");
3374 return MatchOperand_ParseFail;
3375 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
3376 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3377 Error(E, "consecutive register numbers expected");
3378 return MatchOperand_ParseFail;
3379 }
3380
3381 Regs.push_back(RegNo);
3382 }
3383
3384 if (Parser.getTok().is(AsmToken::Minus))
3385 RegRange = true;
3386
3387 if (!Parser.getTok().isNot(AsmToken::Minus) &&
3388 !Parser.getTok().isNot(AsmToken::Comma)) {
3389 Error(E, "',' or '-' expected");
3390 return MatchOperand_ParseFail;
3391 }
3392
3393 Lex(); // Consume comma or minus
3394 if (Parser.getTok().isNot(AsmToken::Dollar))
3395 break;
3396
3397 PrevReg = RegNo;
3398 }
3399
3400 SMLoc E = Parser.getTok().getLoc();
3401 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3402 parseMemOperand(Operands);
3403 return MatchOperand_Success;
3404}
3405
Zoran Jovanovic2deca342014-12-16 14:59:10 +00003406MipsAsmParser::OperandMatchResultTy
3407MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
3408 MCAsmParser &Parser = getParser();
3409
3410 SMLoc S = Parser.getTok().getLoc();
3411 if (parseAnyRegister(Operands) != MatchOperand_Success)
3412 return MatchOperand_ParseFail;
3413
3414 SMLoc E = Parser.getTok().getLoc();
3415 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
3416 unsigned Reg = Op.getGPR32Reg();
3417 Operands.pop_back();
3418 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
3419 return MatchOperand_Success;
3420}
3421
Zoran Jovanovic41688672015-02-10 16:36:20 +00003422MipsAsmParser::OperandMatchResultTy
3423MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
3424 MCAsmParser &Parser = getParser();
3425 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3426 SmallVector<unsigned, 10> Regs;
3427
3428 if (Parser.getTok().isNot(AsmToken::Dollar))
3429 return MatchOperand_ParseFail;
3430
3431 SMLoc S = Parser.getTok().getLoc();
3432
3433 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3434 return MatchOperand_ParseFail;
3435
3436 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3437 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3438 Regs.push_back(RegNo);
3439
3440 SMLoc E = Parser.getTok().getLoc();
3441 if (Parser.getTok().isNot(AsmToken::Comma)) {
3442 Error(E, "',' expected");
3443 return MatchOperand_ParseFail;
3444 }
3445
3446 // Remove comma.
3447 Parser.Lex();
3448
3449 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3450 return MatchOperand_ParseFail;
3451
3452 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3453 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3454 Regs.push_back(RegNo);
3455
3456 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3457
3458 return MatchOperand_Success;
3459}
3460
Jack Carterdc1e35d2012-09-06 20:00:02 +00003461MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
3462
Vladimir Medic4c299852013-11-06 11:27:05 +00003463 MCSymbolRefExpr::VariantKind VK =
3464 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
3465 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
3466 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
3467 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
3468 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
3469 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
3470 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
3471 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
3472 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
3473 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
3474 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
3475 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
3476 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
3477 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
3478 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
3479 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
3480 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
3481 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00003482 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
3483 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
3484 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
3485 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
3486 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
3487 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00003488 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
3489 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00003490 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003491
Matheus Almeida2852af82014-04-22 10:15:54 +00003492 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00003493
Jack Carterdc1e35d2012-09-06 20:00:02 +00003494 return VK;
3495}
Jack Cartera63b16a2012-09-07 00:23:42 +00003496
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003497/// Sometimes (i.e. load/stores) the operand may be followed immediately by
3498/// either this.
3499/// ::= '(', register, ')'
3500/// handle it before we iterate so we don't get tripped up by the lack of
3501/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003502bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003503 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003504 if (getLexer().is(AsmToken::LParen)) {
3505 Operands.push_back(
3506 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
3507 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003508 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003509 SMLoc Loc = getLexer().getLoc();
3510 Parser.eatToEndOfStatement();
3511 return Error(Loc, "unexpected token in argument list");
3512 }
3513 if (Parser.getTok().isNot(AsmToken::RParen)) {
3514 SMLoc Loc = getLexer().getLoc();
3515 Parser.eatToEndOfStatement();
3516 return Error(Loc, "unexpected token, expected ')'");
3517 }
3518 Operands.push_back(
3519 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
3520 Parser.Lex();
3521 }
3522 return false;
3523}
3524
3525/// Sometimes (i.e. in MSA) the operand may be followed immediately by
3526/// either one of these.
3527/// ::= '[', register, ']'
3528/// ::= '[', integer, ']'
3529/// handle it before we iterate so we don't get tripped up by the lack of
3530/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003531bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00003532 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003533 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003534 if (getLexer().is(AsmToken::LBrac)) {
3535 Operands.push_back(
3536 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
3537 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003538 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003539 SMLoc Loc = getLexer().getLoc();
3540 Parser.eatToEndOfStatement();
3541 return Error(Loc, "unexpected token in argument list");
3542 }
3543 if (Parser.getTok().isNot(AsmToken::RBrac)) {
3544 SMLoc Loc = getLexer().getLoc();
3545 Parser.eatToEndOfStatement();
3546 return Error(Loc, "unexpected token, expected ']'");
3547 }
3548 Operands.push_back(
3549 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
3550 Parser.Lex();
3551 }
3552 return false;
3553}
3554
David Blaikie960ea3f2014-06-08 16:18:35 +00003555bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
3556 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003557 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003558 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003559
3560 // We have reached first instruction, module directive are now forbidden.
3561 getTargetStreamer().forbidModuleDirective();
3562
Vladimir Medic74593e62013-07-17 15:00:42 +00003563 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00003564 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00003565 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00003566 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00003567 }
Vladimir Medic64828a12013-07-16 10:07:14 +00003568 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003569 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003570
3571 // Read the remaining operands.
3572 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3573 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003574 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003575 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003576 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003577 return Error(Loc, "unexpected token in argument list");
3578 }
Toma Tabacu13964452014-09-04 13:23:44 +00003579 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003580 return true;
3581 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00003582
Jack Carterd0bd6422013-04-18 00:41:53 +00003583 while (getLexer().is(AsmToken::Comma)) {
3584 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00003585 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003586 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003587 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003588 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003589 return Error(Loc, "unexpected token in argument list");
3590 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003591 // Parse bracket and parenthesis suffixes before we iterate
3592 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00003593 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003594 return true;
3595 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00003596 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003597 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003598 }
3599 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003600 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3601 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003602 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003603 return Error(Loc, "unexpected token in argument list");
3604 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003605 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00003606 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00003607}
3608
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003609bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003610 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003611 SMLoc Loc = getLexer().getLoc();
3612 Parser.eatToEndOfStatement();
3613 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00003614}
3615
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003616bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003617 return Error(Loc, ErrorMsg);
3618}
3619
Jack Carter0b744b32012-10-04 02:29:46 +00003620bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003621 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003622 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00003623
3624 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00003625 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00003626
3627 Parser.Lex(); // Eat "noat".
3628
Jack Carterd0bd6422013-04-18 00:41:53 +00003629 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003630 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003631 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003632 return false;
3633 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003634
3635 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003636 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003637 return false;
3638}
Jack Carterd0bd6422013-04-18 00:41:53 +00003639
Jack Carter0b744b32012-10-04 02:29:46 +00003640bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00003641 // Line can be: ".set at", which sets $at to $1
3642 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00003643 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00003644 Parser.Lex(); // Eat "at".
3645
Jack Carter0b744b32012-10-04 02:29:46 +00003646 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003647 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00003648 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00003649
3650 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003651 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003652 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00003653 }
3654
3655 if (getLexer().isNot(AsmToken::Equal)) {
3656 reportParseError("unexpected token, expected equals sign");
3657 return false;
3658 }
3659 Parser.Lex(); // Eat "=".
3660
3661 if (getLexer().isNot(AsmToken::Dollar)) {
3662 if (getLexer().is(AsmToken::EndOfStatement)) {
3663 reportParseError("no register specified");
3664 return false;
3665 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00003666 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00003667 return false;
3668 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003669 }
3670 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00003671
Toma Tabacu16a74492015-02-13 10:30:57 +00003672 // Find out what "reg" is.
3673 unsigned AtRegNo;
3674 const AsmToken &Reg = Parser.getTok();
3675 if (Reg.is(AsmToken::Identifier)) {
3676 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
3677 } else if (Reg.is(AsmToken::Integer)) {
3678 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00003679 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00003680 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00003681 return false;
3682 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003683
3684 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00003685 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003686 reportParseError("invalid register");
3687 return false;
3688 }
3689 Parser.Lex(); // Eat "reg".
3690
3691 // If this is not the end of the statement, report an error.
3692 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3693 reportParseError("unexpected token, expected end of statement");
3694 return false;
3695 }
3696
3697 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
3698
3699 Parser.Lex(); // Consume the EndOfStatement.
3700 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003701}
3702
3703bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003704 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003705 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003706 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003707 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003708 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003709 return false;
3710 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003711 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00003712 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003713 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003714 return false;
3715}
3716
3717bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003718 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003719 Parser.Lex();
3720 // If this is not the end of the statement, report an error.
3721 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003722 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003723 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003724 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003725 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00003726 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003727 Parser.Lex(); // Consume the EndOfStatement.
3728 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003729}
3730
3731bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003732 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003733 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003734 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003735 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003736 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003737 return false;
3738 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003739 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00003740 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003741 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003742 return false;
3743}
3744
3745bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003746 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003747 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003748 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003749 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003750 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003751 return false;
3752 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003753 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00003754 reportParseError("`noreorder' must be set before `nomacro'");
3755 return false;
3756 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003757 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00003758 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003759 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003760 return false;
3761}
Jack Carterd76b2372013-03-21 21:44:16 +00003762
Daniel Sanders44934432014-08-07 12:03:36 +00003763bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003764 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003765 Parser.Lex();
3766
3767 // If this is not the end of the statement, report an error.
3768 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003769 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003770
3771 setFeatureBits(Mips::FeatureMSA, "msa");
3772 getTargetStreamer().emitDirectiveSetMsa();
3773 return false;
3774}
3775
3776bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003777 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003778 Parser.Lex();
3779
3780 // If this is not the end of the statement, report an error.
3781 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003782 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003783
3784 clearFeatureBits(Mips::FeatureMSA, "msa");
3785 getTargetStreamer().emitDirectiveSetNoMsa();
3786 return false;
3787}
3788
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003789bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003790 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003791 Parser.Lex(); // Eat "nodsp".
3792
3793 // If this is not the end of the statement, report an error.
3794 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3795 reportParseError("unexpected token, expected end of statement");
3796 return false;
3797 }
3798
3799 clearFeatureBits(Mips::FeatureDSP, "dsp");
3800 getTargetStreamer().emitDirectiveSetNoDsp();
3801 return false;
3802}
3803
Toma Tabacucc2502d2014-11-04 17:18:07 +00003804bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003805 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003806 Parser.Lex(); // Eat "mips16".
3807
Jack Carter39536722014-01-22 23:08:42 +00003808 // If this is not the end of the statement, report an error.
3809 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003810 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00003811 return false;
3812 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00003813
3814 setFeatureBits(Mips::FeatureMips16, "mips16");
3815 getTargetStreamer().emitDirectiveSetMips16();
3816 Parser.Lex(); // Consume the EndOfStatement.
3817 return false;
3818}
3819
3820bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003821 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003822 Parser.Lex(); // Eat "nomips16".
3823
3824 // If this is not the end of the statement, report an error.
3825 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3826 reportParseError("unexpected token, expected end of statement");
3827 return false;
3828 }
3829
3830 clearFeatureBits(Mips::FeatureMips16, "mips16");
3831 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00003832 Parser.Lex(); // Consume the EndOfStatement.
3833 return false;
3834}
3835
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003836bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003837 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003838 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003839 // Line can be: .set fp=32
3840 // .set fp=xx
3841 // .set fp=64
3842 Parser.Lex(); // Eat fp token
3843 AsmToken Tok = Parser.getTok();
3844 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003845 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003846 return false;
3847 }
3848 Parser.Lex(); // Eat '=' token.
3849 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003850
3851 if (!parseFpABIValue(FpAbiVal, ".set"))
3852 return false;
3853
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003854 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003855 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003856 return false;
3857 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003858 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003859 Parser.Lex(); // Consume the EndOfStatement.
3860 return false;
3861}
3862
Toma Tabacu9db22db2014-09-09 10:15:38 +00003863bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003864 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003865 SMLoc Loc = getLexer().getLoc();
3866
3867 Parser.Lex();
3868 if (getLexer().isNot(AsmToken::EndOfStatement))
3869 return reportParseError("unexpected token, expected end of statement");
3870
3871 // Always keep an element on the options "stack" to prevent the user
3872 // from changing the initial options. This is how we remember them.
3873 if (AssemblerOptions.size() == 2)
3874 return reportParseError(Loc, ".set pop with no .set push");
3875
3876 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00003877 setAvailableFeatures(
3878 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
3879 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00003880
3881 getTargetStreamer().emitDirectiveSetPop();
3882 return false;
3883}
3884
3885bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003886 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003887 Parser.Lex();
3888 if (getLexer().isNot(AsmToken::EndOfStatement))
3889 return reportParseError("unexpected token, expected end of statement");
3890
3891 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00003892 AssemblerOptions.push_back(
3893 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00003894
3895 getTargetStreamer().emitDirectiveSetPush();
3896 return false;
3897}
3898
Toma Tabacu29696502015-06-02 09:48:04 +00003899bool MipsAsmParser::parseSetSoftFloatDirective() {
3900 MCAsmParser &Parser = getParser();
3901 Parser.Lex();
3902 if (getLexer().isNot(AsmToken::EndOfStatement))
3903 return reportParseError("unexpected token, expected end of statement");
3904
3905 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
3906 getTargetStreamer().emitDirectiveSetSoftFloat();
3907 return false;
3908}
3909
3910bool MipsAsmParser::parseSetHardFloatDirective() {
3911 MCAsmParser &Parser = getParser();
3912 Parser.Lex();
3913 if (getLexer().isNot(AsmToken::EndOfStatement))
3914 return reportParseError("unexpected token, expected end of statement");
3915
3916 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
3917 getTargetStreamer().emitDirectiveSetHardFloat();
3918 return false;
3919}
3920
Jack Carterd76b2372013-03-21 21:44:16 +00003921bool MipsAsmParser::parseSetAssignment() {
3922 StringRef Name;
3923 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00003924 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00003925
3926 if (Parser.parseIdentifier(Name))
3927 reportParseError("expected identifier after .set");
3928
3929 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003930 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00003931 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00003932
Jack Carter3b2c96e2014-01-22 23:31:38 +00003933 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00003934 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00003935
Jim Grosbach6f482002015-05-18 18:43:14 +00003936 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00003937 Sym->setVariableValue(Value);
3938
3939 return false;
3940}
Jack Carterd0bd6422013-04-18 00:41:53 +00003941
Toma Tabacu26647792014-09-09 12:52:14 +00003942bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003943 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00003944 Parser.Lex();
3945 if (getLexer().isNot(AsmToken::EndOfStatement))
3946 return reportParseError("unexpected token, expected end of statement");
3947
3948 // Reset assembler options to their initial values.
Toma Tabacu465acfd2015-06-09 13:33:26 +00003949 setAvailableFeatures(
3950 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
3951 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00003952 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
3953
3954 getTargetStreamer().emitDirectiveSetMips0();
3955 return false;
3956}
3957
Toma Tabacu85618b32014-08-19 14:22:52 +00003958bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003959 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00003960 Parser.Lex();
3961 if (getLexer().isNot(AsmToken::Equal))
3962 return reportParseError("unexpected token, expected equals sign");
3963
3964 Parser.Lex();
3965 StringRef Arch;
3966 if (Parser.parseIdentifier(Arch))
3967 return reportParseError("expected arch identifier");
3968
3969 StringRef ArchFeatureName =
3970 StringSwitch<StringRef>(Arch)
3971 .Case("mips1", "mips1")
3972 .Case("mips2", "mips2")
3973 .Case("mips3", "mips3")
3974 .Case("mips4", "mips4")
3975 .Case("mips5", "mips5")
3976 .Case("mips32", "mips32")
3977 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003978 .Case("mips32r3", "mips32r3")
3979 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003980 .Case("mips32r6", "mips32r6")
3981 .Case("mips64", "mips64")
3982 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003983 .Case("mips64r3", "mips64r3")
3984 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003985 .Case("mips64r6", "mips64r6")
3986 .Case("cnmips", "cnmips")
3987 .Case("r4000", "mips3") // This is an implementation of Mips3.
3988 .Default("");
3989
3990 if (ArchFeatureName.empty())
3991 return reportParseError("unsupported architecture");
3992
3993 selectArch(ArchFeatureName);
3994 getTargetStreamer().emitDirectiveSetArch(Arch);
3995 return false;
3996}
3997
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003998bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003999 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004000 Parser.Lex();
4001 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004002 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004003
Matheus Almeida2852af82014-04-22 10:15:54 +00004004 switch (Feature) {
4005 default:
4006 llvm_unreachable("Unimplemented feature");
4007 case Mips::FeatureDSP:
4008 setFeatureBits(Mips::FeatureDSP, "dsp");
4009 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004010 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004011 case Mips::FeatureMicroMips:
4012 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004013 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004014 case Mips::FeatureMips1:
4015 selectArch("mips1");
4016 getTargetStreamer().emitDirectiveSetMips1();
4017 break;
4018 case Mips::FeatureMips2:
4019 selectArch("mips2");
4020 getTargetStreamer().emitDirectiveSetMips2();
4021 break;
4022 case Mips::FeatureMips3:
4023 selectArch("mips3");
4024 getTargetStreamer().emitDirectiveSetMips3();
4025 break;
4026 case Mips::FeatureMips4:
4027 selectArch("mips4");
4028 getTargetStreamer().emitDirectiveSetMips4();
4029 break;
4030 case Mips::FeatureMips5:
4031 selectArch("mips5");
4032 getTargetStreamer().emitDirectiveSetMips5();
4033 break;
4034 case Mips::FeatureMips32:
4035 selectArch("mips32");
4036 getTargetStreamer().emitDirectiveSetMips32();
4037 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004038 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004039 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004040 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004041 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004042 case Mips::FeatureMips32r3:
4043 selectArch("mips32r3");
4044 getTargetStreamer().emitDirectiveSetMips32R3();
4045 break;
4046 case Mips::FeatureMips32r5:
4047 selectArch("mips32r5");
4048 getTargetStreamer().emitDirectiveSetMips32R5();
4049 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004050 case Mips::FeatureMips32r6:
4051 selectArch("mips32r6");
4052 getTargetStreamer().emitDirectiveSetMips32R6();
4053 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004054 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004055 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00004056 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00004057 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004058 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004059 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004060 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00004061 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004062 case Mips::FeatureMips64r3:
4063 selectArch("mips64r3");
4064 getTargetStreamer().emitDirectiveSetMips64R3();
4065 break;
4066 case Mips::FeatureMips64r5:
4067 selectArch("mips64r5");
4068 getTargetStreamer().emitDirectiveSetMips64R5();
4069 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004070 case Mips::FeatureMips64r6:
4071 selectArch("mips64r6");
4072 getTargetStreamer().emitDirectiveSetMips64R6();
4073 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004074 }
4075 return false;
4076}
4077
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004078bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004079 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004080 if (getLexer().isNot(AsmToken::Comma)) {
4081 SMLoc Loc = getLexer().getLoc();
4082 Parser.eatToEndOfStatement();
4083 return Error(Loc, ErrorStr);
4084 }
4085
Matheus Almeida2852af82014-04-22 10:15:54 +00004086 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004087 return true;
4088}
4089
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004090bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00004091 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00004092 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004093
Toma Tabacudde4c462014-11-06 10:02:45 +00004094 if (inMips16Mode()) {
4095 reportParseError(".cpload is not supported in Mips16 mode");
4096 return false;
4097 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004098
David Blaikie960ea3f2014-06-08 16:18:35 +00004099 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00004100 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004101 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4102 reportParseError("expected register containing function address");
4103 return false;
4104 }
4105
David Blaikie960ea3f2014-06-08 16:18:35 +00004106 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
4107 if (!RegOpnd.isGPRAsmReg()) {
4108 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004109 return false;
4110 }
4111
Toma Tabacudde4c462014-11-06 10:02:45 +00004112 // If this is not the end of the statement, report an error.
4113 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4114 reportParseError("unexpected token, expected end of statement");
4115 return false;
4116 }
4117
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004118 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004119 return false;
4120}
4121
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004122bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004123 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004124 unsigned FuncReg;
4125 unsigned Save;
4126 bool SaveIsReg = true;
4127
Matheus Almeida7e815762014-06-18 13:08:59 +00004128 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004129 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00004130 if (ResTy == MatchOperand_NoMatch) {
4131 reportParseError("expected register containing function address");
4132 Parser.eatToEndOfStatement();
4133 return false;
4134 }
4135
4136 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4137 if (!FuncRegOpnd.isGPRAsmReg()) {
4138 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
4139 Parser.eatToEndOfStatement();
4140 return false;
4141 }
4142
4143 FuncReg = FuncRegOpnd.getGPR32Reg();
4144 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004145
Toma Tabacu65f10572014-09-16 15:00:52 +00004146 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004147 return true;
4148
Toma Tabacu13964452014-09-04 13:23:44 +00004149 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00004150 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004151 const AsmToken &Tok = Parser.getTok();
4152 if (Tok.is(AsmToken::Integer)) {
4153 Save = Tok.getIntVal();
4154 SaveIsReg = false;
4155 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00004156 } else {
4157 reportParseError("expected save register or stack offset");
4158 Parser.eatToEndOfStatement();
4159 return false;
4160 }
4161 } else {
4162 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4163 if (!SaveOpnd.isGPRAsmReg()) {
4164 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
4165 Parser.eatToEndOfStatement();
4166 return false;
4167 }
4168 Save = SaveOpnd.getGPR32Reg();
4169 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004170
Toma Tabacu65f10572014-09-16 15:00:52 +00004171 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004172 return true;
4173
Toma Tabacu8874eac2015-02-18 13:46:53 +00004174 const MCExpr *Expr;
4175 if (Parser.parseExpression(Expr)) {
4176 reportParseError("expected expression");
4177 return false;
4178 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004179
Toma Tabacu8874eac2015-02-18 13:46:53 +00004180 if (Expr->getKind() != MCExpr::SymbolRef) {
4181 reportParseError("expected symbol");
4182 return false;
4183 }
4184 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
4185
4186 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
4187 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004188 return false;
4189}
4190
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004191bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004192 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004193 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4194 const AsmToken &Tok = Parser.getTok();
4195
4196 if (Tok.getString() == "2008") {
4197 Parser.Lex();
4198 getTargetStreamer().emitDirectiveNaN2008();
4199 return false;
4200 } else if (Tok.getString() == "legacy") {
4201 Parser.Lex();
4202 getTargetStreamer().emitDirectiveNaNLegacy();
4203 return false;
4204 }
4205 }
4206 // If we don't recognize the option passed to the .nan
4207 // directive (e.g. no option or unknown option), emit an error.
4208 reportParseError("invalid option in .nan directive");
4209 return false;
4210}
4211
Jack Carter0b744b32012-10-04 02:29:46 +00004212bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004213 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004214 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00004215 const AsmToken &Tok = Parser.getTok();
4216
4217 if (Tok.getString() == "noat") {
4218 return parseSetNoAtDirective();
4219 } else if (Tok.getString() == "at") {
4220 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00004221 } else if (Tok.getString() == "arch") {
4222 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004223 } else if (Tok.getString() == "fp") {
4224 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004225 } else if (Tok.getString() == "pop") {
4226 return parseSetPopDirective();
4227 } else if (Tok.getString() == "push") {
4228 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00004229 } else if (Tok.getString() == "reorder") {
4230 return parseSetReorderDirective();
4231 } else if (Tok.getString() == "noreorder") {
4232 return parseSetNoReorderDirective();
4233 } else if (Tok.getString() == "macro") {
4234 return parseSetMacroDirective();
4235 } else if (Tok.getString() == "nomacro") {
4236 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00004237 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00004238 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00004239 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00004240 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00004241 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00004242 getTargetStreamer().emitDirectiveSetNoMicroMips();
4243 Parser.eatToEndOfStatement();
4244 return false;
4245 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004246 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00004247 } else if (Tok.getString() == "mips0") {
4248 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00004249 } else if (Tok.getString() == "mips1") {
4250 return parseSetFeature(Mips::FeatureMips1);
4251 } else if (Tok.getString() == "mips2") {
4252 return parseSetFeature(Mips::FeatureMips2);
4253 } else if (Tok.getString() == "mips3") {
4254 return parseSetFeature(Mips::FeatureMips3);
4255 } else if (Tok.getString() == "mips4") {
4256 return parseSetFeature(Mips::FeatureMips4);
4257 } else if (Tok.getString() == "mips5") {
4258 return parseSetFeature(Mips::FeatureMips5);
4259 } else if (Tok.getString() == "mips32") {
4260 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00004261 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004262 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00004263 } else if (Tok.getString() == "mips32r3") {
4264 return parseSetFeature(Mips::FeatureMips32r3);
4265 } else if (Tok.getString() == "mips32r5") {
4266 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00004267 } else if (Tok.getString() == "mips32r6") {
4268 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00004269 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004270 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00004271 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004272 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00004273 } else if (Tok.getString() == "mips64r3") {
4274 return parseSetFeature(Mips::FeatureMips64r3);
4275 } else if (Tok.getString() == "mips64r5") {
4276 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00004277 } else if (Tok.getString() == "mips64r6") {
4278 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00004279 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004280 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004281 } else if (Tok.getString() == "nodsp") {
4282 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00004283 } else if (Tok.getString() == "msa") {
4284 return parseSetMsaDirective();
4285 } else if (Tok.getString() == "nomsa") {
4286 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00004287 } else if (Tok.getString() == "softfloat") {
4288 return parseSetSoftFloatDirective();
4289 } else if (Tok.getString() == "hardfloat") {
4290 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00004291 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00004292 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00004293 parseSetAssignment();
4294 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004295 }
Jack Carter07c818d2013-01-25 01:31:34 +00004296
Jack Carter0b744b32012-10-04 02:29:46 +00004297 return true;
4298}
4299
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004300/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00004301/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004302bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004303 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004304 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4305 for (;;) {
4306 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004307 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00004308 return true;
4309
4310 getParser().getStreamer().EmitValue(Value, Size);
4311
4312 if (getLexer().is(AsmToken::EndOfStatement))
4313 break;
4314
Jack Carter07c818d2013-01-25 01:31:34 +00004315 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004316 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00004317 Parser.Lex();
4318 }
4319 }
4320
4321 Parser.Lex();
4322 return false;
4323}
4324
Vladimir Medic4c299852013-11-06 11:27:05 +00004325/// parseDirectiveGpWord
4326/// ::= .gpword local_sym
4327bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004328 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004329 const MCExpr *Value;
4330 // EmitGPRel32Value requires an expression, so we are using base class
4331 // method to evaluate the expression.
4332 if (getParser().parseExpression(Value))
4333 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00004334 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00004335
Vladimir Medice10c1122013-11-13 13:18:04 +00004336 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004337 return Error(getLexer().getLoc(),
4338 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00004339 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00004340 return false;
4341}
4342
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004343/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00004344/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004345bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004346 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004347 const MCExpr *Value;
4348 // EmitGPRel64Value requires an expression, so we are using base class
4349 // method to evaluate the expression.
4350 if (getParser().parseExpression(Value))
4351 return true;
4352 getParser().getStreamer().EmitGPRel64Value(Value);
4353
4354 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004355 return Error(getLexer().getLoc(),
4356 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00004357 Parser.Lex(); // Eat EndOfStatement token.
4358 return false;
4359}
4360
Jack Carter0cd3c192014-01-06 23:27:31 +00004361bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004362 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00004363 // Get the option token.
4364 AsmToken Tok = Parser.getTok();
4365 // At the moment only identifiers are supported.
4366 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004367 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00004368 Parser.eatToEndOfStatement();
4369 return false;
4370 }
4371
4372 StringRef Option = Tok.getIdentifier();
4373
4374 if (Option == "pic0") {
4375 getTargetStreamer().emitDirectiveOptionPic0();
4376 Parser.Lex();
4377 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4378 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004379 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004380 Parser.eatToEndOfStatement();
4381 }
4382 return false;
4383 }
4384
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004385 if (Option == "pic2") {
4386 getTargetStreamer().emitDirectiveOptionPic2();
4387 Parser.Lex();
4388 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4389 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004390 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004391 Parser.eatToEndOfStatement();
4392 }
4393 return false;
4394 }
4395
Jack Carter0cd3c192014-01-06 23:27:31 +00004396 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00004397 Warning(Parser.getTok().getLoc(),
4398 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00004399 Parser.eatToEndOfStatement();
4400 return false;
4401}
4402
Toma Tabacu9ca50962015-04-16 09:53:47 +00004403/// parseInsnDirective
4404/// ::= .insn
4405bool MipsAsmParser::parseInsnDirective() {
4406 // If this is not the end of the statement, report an error.
4407 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4408 reportParseError("unexpected token, expected end of statement");
4409 return false;
4410 }
4411
4412 // The actual label marking happens in
4413 // MipsELFStreamer::createPendingLabelRelocs().
4414 getTargetStreamer().emitDirectiveInsn();
4415
4416 getParser().Lex(); // Eat EndOfStatement token.
4417 return false;
4418}
4419
Daniel Sanders7e527422014-07-10 13:38:23 +00004420/// parseDirectiveModule
4421/// ::= .module oddspreg
4422/// ::= .module nooddspreg
4423/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004424bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004425 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004426 MCAsmLexer &Lexer = getLexer();
4427 SMLoc L = Lexer.getLoc();
4428
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004429 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004430 // TODO : get a better message.
4431 reportParseError(".module directive must appear before any code");
4432 return false;
4433 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004434
Toma Tabacuc405c822015-01-23 10:40:19 +00004435 StringRef Option;
4436 if (Parser.parseIdentifier(Option)) {
4437 reportParseError("expected .module option identifier");
4438 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004439 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004440
Toma Tabacuc405c822015-01-23 10:40:19 +00004441 if (Option == "oddspreg") {
4442 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
4443 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4444
4445 // If this is not the end of the statement, report an error.
4446 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4447 reportParseError("unexpected token, expected end of statement");
4448 return false;
4449 }
4450
4451 return false; // parseDirectiveModule has finished successfully.
4452 } else if (Option == "nooddspreg") {
4453 if (!isABI_O32()) {
4454 Error(L, "'.module nooddspreg' requires the O32 ABI");
4455 return false;
4456 }
4457
4458 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
4459 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4460
4461 // If this is not the end of the statement, report an error.
4462 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4463 reportParseError("unexpected token, expected end of statement");
4464 return false;
4465 }
4466
4467 return false; // parseDirectiveModule has finished successfully.
4468 } else if (Option == "fp") {
4469 return parseDirectiveModuleFP();
4470 } else {
4471 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
4472 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004473}
4474
4475/// parseDirectiveModuleFP
4476/// ::= =32
4477/// ::= =xx
4478/// ::= =64
4479bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004480 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004481 MCAsmLexer &Lexer = getLexer();
4482
4483 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004484 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004485 return false;
4486 }
4487 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004488
Daniel Sanders7e527422014-07-10 13:38:23 +00004489 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004490 if (!parseFpABIValue(FpABI, ".module"))
4491 return false;
4492
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004493 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004494 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004495 return false;
4496 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004497
Daniel Sanders7201a3e2014-07-08 10:35:52 +00004498 // Emit appropriate flags.
4499 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00004500 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004501 return false;
4502}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004503
Daniel Sanders7e527422014-07-10 13:38:23 +00004504bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004505 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004506 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004507 MCAsmLexer &Lexer = getLexer();
4508
4509 if (Lexer.is(AsmToken::Identifier)) {
4510 StringRef Value = Parser.getTok().getString();
4511 Parser.Lex();
4512
4513 if (Value != "xx") {
4514 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4515 return false;
4516 }
4517
4518 if (!isABI_O32()) {
4519 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
4520 return false;
4521 }
4522
Daniel Sanders7e527422014-07-10 13:38:23 +00004523 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004524 return true;
4525 }
4526
4527 if (Lexer.is(AsmToken::Integer)) {
4528 unsigned Value = Parser.getTok().getIntVal();
4529 Parser.Lex();
4530
4531 if (Value != 32 && Value != 64) {
4532 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4533 return false;
4534 }
4535
4536 if (Value == 32) {
4537 if (!isABI_O32()) {
4538 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
4539 return false;
4540 }
4541
Daniel Sanders7e527422014-07-10 13:38:23 +00004542 FpABI = MipsABIFlagsSection::FpABIKind::S32;
4543 } else
4544 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004545
Daniel Sanders7e527422014-07-10 13:38:23 +00004546 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004547 }
4548
4549 return false;
4550}
4551
Jack Carter0b744b32012-10-04 02:29:46 +00004552bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004553 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004554 StringRef IDVal = DirectiveID.getString();
4555
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004556 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004557 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00004558 if (IDVal == ".dword") {
4559 parseDataDirective(8, DirectiveID.getLoc());
4560 return false;
4561 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004562 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004563 StringRef SymbolName;
4564
4565 if (Parser.parseIdentifier(SymbolName)) {
4566 reportParseError("expected identifier after .ent");
4567 return false;
4568 }
4569
4570 // There's an undocumented extension that allows an integer to
4571 // follow the name of the procedure which AFAICS is ignored by GAS.
4572 // Example: .ent foo,2
4573 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4574 if (getLexer().isNot(AsmToken::Comma)) {
4575 // Even though we accept this undocumented extension for compatibility
4576 // reasons, the additional integer argument does not actually change
4577 // the behaviour of the '.ent' directive, so we would like to discourage
4578 // its use. We do this by not referring to the extended version in
4579 // error messages which are not directly related to its use.
4580 reportParseError("unexpected token, expected end of statement");
4581 return false;
4582 }
4583 Parser.Lex(); // Eat the comma.
4584 const MCExpr *DummyNumber;
4585 int64_t DummyNumberVal;
4586 // If the user was explicitly trying to use the extended version,
4587 // we still give helpful extension-related error messages.
4588 if (Parser.parseExpression(DummyNumber)) {
4589 reportParseError("expected number after comma");
4590 return false;
4591 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00004592 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004593 reportParseError("expected an absolute expression after comma");
4594 return false;
4595 }
4596 }
4597
4598 // If this is not the end of the statement, report an error.
4599 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4600 reportParseError("unexpected token, expected end of statement");
4601 return false;
4602 }
4603
Jim Grosbach6f482002015-05-18 18:43:14 +00004604 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004605
4606 getTargetStreamer().emitDirectiveEnt(*Sym);
4607 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00004608 return false;
4609 }
4610
Jack Carter07c818d2013-01-25 01:31:34 +00004611 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004612 StringRef SymbolName;
4613
4614 if (Parser.parseIdentifier(SymbolName)) {
4615 reportParseError("expected identifier after .end");
4616 return false;
4617 }
4618
4619 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4620 reportParseError("unexpected token, expected end of statement");
4621 return false;
4622 }
4623
4624 if (CurrentFn == nullptr) {
4625 reportParseError(".end used without .ent");
4626 return false;
4627 }
4628
4629 if ((SymbolName != CurrentFn->getName())) {
4630 reportParseError(".end symbol does not match .ent symbol");
4631 return false;
4632 }
4633
4634 getTargetStreamer().emitDirectiveEnd(SymbolName);
4635 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00004636 return false;
4637 }
4638
Jack Carter07c818d2013-01-25 01:31:34 +00004639 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004640 // .frame $stack_reg, frame_size_in_bytes, $return_reg
4641 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004642 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004643 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4644 reportParseError("expected stack register");
4645 return false;
4646 }
4647
4648 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4649 if (!StackRegOpnd.isGPRAsmReg()) {
4650 reportParseError(StackRegOpnd.getStartLoc(),
4651 "expected general purpose register");
4652 return false;
4653 }
4654 unsigned StackReg = StackRegOpnd.getGPR32Reg();
4655
4656 if (Parser.getTok().is(AsmToken::Comma))
4657 Parser.Lex();
4658 else {
4659 reportParseError("unexpected token, expected comma");
4660 return false;
4661 }
4662
4663 // Parse the frame size.
4664 const MCExpr *FrameSize;
4665 int64_t FrameSizeVal;
4666
4667 if (Parser.parseExpression(FrameSize)) {
4668 reportParseError("expected frame size value");
4669 return false;
4670 }
4671
Jim Grosbach13760bd2015-05-30 01:25:56 +00004672 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004673 reportParseError("frame size not an absolute expression");
4674 return false;
4675 }
4676
4677 if (Parser.getTok().is(AsmToken::Comma))
4678 Parser.Lex();
4679 else {
4680 reportParseError("unexpected token, expected comma");
4681 return false;
4682 }
4683
4684 // Parse the return register.
4685 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00004686 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004687 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4688 reportParseError("expected return register");
4689 return false;
4690 }
4691
4692 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4693 if (!ReturnRegOpnd.isGPRAsmReg()) {
4694 reportParseError(ReturnRegOpnd.getStartLoc(),
4695 "expected general purpose register");
4696 return false;
4697 }
4698
4699 // If this is not the end of the statement, report an error.
4700 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4701 reportParseError("unexpected token, expected end of statement");
4702 return false;
4703 }
4704
4705 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
4706 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00004707 return false;
4708 }
4709
Jack Carter07c818d2013-01-25 01:31:34 +00004710 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00004711 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00004712 }
4713
Daniel Sandersd97a6342014-08-13 10:07:34 +00004714 if (IDVal == ".mask" || IDVal == ".fmask") {
4715 // .mask bitmask, frame_offset
4716 // bitmask: One bit for each register used.
4717 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
4718 // first register is expected to be saved.
4719 // Examples:
4720 // .mask 0x80000000, -4
4721 // .fmask 0x80000000, -4
4722 //
Jack Carterbe332172012-09-07 00:48:02 +00004723
Daniel Sandersd97a6342014-08-13 10:07:34 +00004724 // Parse the bitmask
4725 const MCExpr *BitMask;
4726 int64_t BitMaskVal;
4727
4728 if (Parser.parseExpression(BitMask)) {
4729 reportParseError("expected bitmask value");
4730 return false;
4731 }
4732
Jim Grosbach13760bd2015-05-30 01:25:56 +00004733 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004734 reportParseError("bitmask not an absolute expression");
4735 return false;
4736 }
4737
4738 if (Parser.getTok().is(AsmToken::Comma))
4739 Parser.Lex();
4740 else {
4741 reportParseError("unexpected token, expected comma");
4742 return false;
4743 }
4744
4745 // Parse the frame_offset
4746 const MCExpr *FrameOffset;
4747 int64_t FrameOffsetVal;
4748
4749 if (Parser.parseExpression(FrameOffset)) {
4750 reportParseError("expected frame offset value");
4751 return false;
4752 }
4753
Jim Grosbach13760bd2015-05-30 01:25:56 +00004754 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004755 reportParseError("frame offset not an absolute expression");
4756 return false;
4757 }
4758
4759 // If this is not the end of the statement, report an error.
4760 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4761 reportParseError("unexpected token, expected end of statement");
4762 return false;
4763 }
4764
4765 if (IDVal == ".mask")
4766 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
4767 else
4768 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00004769 return false;
4770 }
4771
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004772 if (IDVal == ".nan")
4773 return parseDirectiveNaN();
4774
Jack Carter07c818d2013-01-25 01:31:34 +00004775 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004776 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00004777 return false;
4778 }
4779
Rafael Espindolab59fb732014-03-28 18:50:26 +00004780 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004781 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004782 return false;
4783 }
4784
Jack Carter07c818d2013-01-25 01:31:34 +00004785 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004786 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00004787 return false;
4788 }
4789
Jack Carter0cd3c192014-01-06 23:27:31 +00004790 if (IDVal == ".option")
4791 return parseDirectiveOption();
4792
4793 if (IDVal == ".abicalls") {
4794 getTargetStreamer().emitDirectiveAbiCalls();
4795 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004796 Error(Parser.getTok().getLoc(),
4797 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004798 // Clear line
4799 Parser.eatToEndOfStatement();
4800 }
4801 return false;
4802 }
4803
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004804 if (IDVal == ".cpsetup")
4805 return parseDirectiveCPSetup();
4806
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004807 if (IDVal == ".module")
4808 return parseDirectiveModule();
4809
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004810 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
4811 return parseInternalDirectiveReallowModule();
4812
Toma Tabacu9ca50962015-04-16 09:53:47 +00004813 if (IDVal == ".insn")
4814 return parseInsnDirective();
4815
Rafael Espindola870c4e92012-01-11 03:56:41 +00004816 return true;
4817}
4818
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004819bool MipsAsmParser::parseInternalDirectiveReallowModule() {
4820 // If this is not the end of the statement, report an error.
4821 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4822 reportParseError("unexpected token, expected end of statement");
4823 return false;
4824 }
4825
4826 getTargetStreamer().reallowModuleDirective();
4827
4828 getParser().Lex(); // Eat EndOfStatement token.
4829 return false;
4830}
4831
Rafael Espindola870c4e92012-01-11 03:56:41 +00004832extern "C" void LLVMInitializeMipsAsmParser() {
4833 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
4834 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
4835 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
4836 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
4837}
Jack Carterb4dbc172012-09-05 23:34:03 +00004838
4839#define GET_REGISTER_MATCHER
4840#define GET_MATCHER_IMPLEMENTATION
4841#include "MipsGenAsmMatcher.inc"