blob: 71e962c74d483227baefc55e08bc2201fd532960 [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 Tabacu9db22db2014-09-09 10:15:38 +000046 MipsAssemblerOptions(uint64_t Features_) :
47 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 Tabacu9db22db2014-09-09 10:15:38 +000073 uint64_t getFeatures() const { return Features; }
74 void setFeatures(uint64_t Features_) { Features = Features_; }
75
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 Kupersteinc3434b32015-05-13 10:28:46 +000081 static const uint64_t AllArchRelatedMask =
82 Mips::FeatureMips1 | Mips::FeatureMips2 | Mips::FeatureMips3 |
83 Mips::FeatureMips3_32 | Mips::FeatureMips3_32r2 | Mips::FeatureMips4 |
84 Mips::FeatureMips4_32 | Mips::FeatureMips4_32r2 | Mips::FeatureMips5 |
85 Mips::FeatureMips5_32r2 | Mips::FeatureMips32 | Mips::FeatureMips32r2 |
86 Mips::FeatureMips32r3 | Mips::FeatureMips32r5 | Mips::FeatureMips32r6 |
87 Mips::FeatureMips64 | Mips::FeatureMips64r2 | Mips::FeatureMips64r3 |
88 Mips::FeatureMips64r5 | Mips::FeatureMips64r6 | Mips::FeatureCnMips |
89 Mips::FeatureFP64Bit | Mips::FeatureGP64Bit | Mips::FeatureNaN2008;
Daniel Sandersf0df2212014-08-04 12:20:00 +000090
Jack Carter0b744b32012-10-04 02:29:46 +000091private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000092 unsigned ATReg;
93 bool Reorder;
94 bool Macro;
Toma Tabacu9db22db2014-09-09 10:15:38 +000095 uint64_t Features;
Jack Carter0b744b32012-10-04 02:29:46 +000096};
97}
98
99namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +0000100class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000101 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000102 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000103 return static_cast<MipsTargetStreamer &>(TS);
104 }
105
Jack Carterb4dbc172012-09-05 23:34:03 +0000106 MCSubtargetInfo &STI;
Eric Christophera5762812015-01-26 17:33:46 +0000107 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000108 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000109 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
110 // nullptr, which indicates that no function is currently
111 // selected. This usually happens after an '.end func'
112 // directive.
Jack Carter0b744b32012-10-04 02:29:46 +0000113
Daniel Sandersef638fe2014-10-03 15:37:37 +0000114 // Print a warning along with its fix-it message at the given range.
115 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
116 SMRange Range, bool ShowColors = true);
117
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000118#define GET_ASSEMBLER_HEADER
119#include "MipsGenAsmMatcher.inc"
120
Matheus Almeida595fcab2014-06-11 15:05:56 +0000121 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
122
Chad Rosier49963552012-10-13 00:26:04 +0000123 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000124 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000125 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000126 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000127
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000128 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000129 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000130
Toma Tabacu13964452014-09-04 13:23:44 +0000131 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000132
Toma Tabacu13964452014-09-04 13:23:44 +0000133 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000134
David Blaikie960ea3f2014-06-08 16:18:35 +0000135 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
136 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000137
Craig Topper56c590a2014-04-29 07:58:02 +0000138 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000139
David Blaikie960ea3f2014-06-08 16:18:35 +0000140 MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000141
142 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000143 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000144 StringRef Identifier, SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000145
Jack Carter873c7242013-01-12 01:03:14 +0000146 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000147 matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
Jack Carter873c7242013-01-12 01:03:14 +0000148
Toma Tabacu13964452014-09-04 13:23:44 +0000149 MipsAsmParser::OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000150
Toma Tabacu13964452014-09-04 13:23:44 +0000151 MipsAsmParser::OperandMatchResultTy parseImm(OperandVector &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000152
Toma Tabacu13964452014-09-04 13:23:44 +0000153 MipsAsmParser::OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000154
David Blaikie960ea3f2014-06-08 16:18:35 +0000155 MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000156
Toma Tabacu13964452014-09-04 13:23:44 +0000157 MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000158
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000159 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000160 parseRegisterPair (OperandVector &Operands);
161
162 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +0000163 parseMovePRegPair(OperandVector &Operands);
164
165 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000166 parseRegisterList (OperandVector &Operands);
167
David Blaikie960ea3f2014-06-08 16:18:35 +0000168 bool searchSymbolAlias(OperandVector &Operands);
169
Toma Tabacu13964452014-09-04 13:23:44 +0000170 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000171
Jack Carter30a59822012-10-04 04:03:53 +0000172 bool needsExpansion(MCInst &Inst);
173
Matheus Almeida3813d572014-06-19 14:39:14 +0000174 // Expands assembly pseudo instructions.
175 // Returns false on success, true otherwise.
176 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000177 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000178
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000179 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
180 SmallVectorImpl<MCInst> &Instructions);
181
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000182 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
183 bool Is32BitImm, SMLoc IDLoc,
184 SmallVectorImpl<MCInst> &Instructions);
185
Toma Tabacu00e98672015-05-01 12:19:27 +0000186 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000187 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000188
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000189 bool expandLoadAddressImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000190 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000191
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000192 bool expandLoadAddressReg(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000193 SmallVectorImpl<MCInst> &Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000194 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
195 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000196
Toma Tabacub5592ee2015-05-14 10:02:58 +0000197 void expandLoadAddressSym(const MCOperand &DstRegOp, const MCOperand &SymOp,
Toma Tabacuec1de822015-05-14 10:53:40 +0000198 bool Is32BitSym, SMLoc IDLoc,
199 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +0000200
Jack Carter9e65aa32013-03-22 00:05:30 +0000201 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000202 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
203 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000204
205 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
206 SmallVectorImpl<MCInst> &Instructions);
207
Toma Tabacu234482a2015-03-16 12:03:39 +0000208 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
209 SmallVectorImpl<MCInst> &Instructions);
210
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000211 void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
212 SmallVectorImpl<MCInst> &Instructions);
213
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000214 bool reportParseError(Twine ErrorMsg);
215 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000216
Jack Carterb5cf5902013-04-17 00:18:04 +0000217 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000218 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000219
Vladimir Medic4c299852013-11-06 11:27:05 +0000220 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000221
222 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000223 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000224 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000225 bool parseSetFeature(uint64_t Feature);
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000226 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000227 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000228 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000229 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000230 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000231 bool parseInsnDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000232
233 bool parseSetAtDirective();
234 bool parseSetNoAtDirective();
235 bool parseSetMacroDirective();
236 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000237 bool parseSetMsaDirective();
238 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000239 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000240 bool parseSetReorderDirective();
241 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000242 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000243 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000244 bool parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000245 bool parseSetPopDirective();
246 bool parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000247
Jack Carterd76b2372013-03-21 21:44:16 +0000248 bool parseSetAssignment();
249
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000250 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000251 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000252 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000253 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000254 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000255 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
256 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000257
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000258 bool parseInternalDirectiveReallowModule();
259
Jack Carterdc1e35d2012-09-06 20:00:02 +0000260 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000261
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000262 bool eatComma(StringRef ErrorStr);
263
Jack Carter1ac53222013-02-20 23:11:17 +0000264 int matchCPURegisterName(StringRef Symbol);
265
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000266 int matchHWRegsRegisterName(StringRef Symbol);
267
Jack Carter873c7242013-01-12 01:03:14 +0000268 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000269
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000270 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000271
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000272 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000273
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000274 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000275
Jack Carter5dc8ac92013-09-25 23:50:44 +0000276 int matchMSA128RegisterName(StringRef Name);
277
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000278 int matchMSA128CtrlRegisterName(StringRef Name);
279
Jack Carterd0bd6422013-04-18 00:41:53 +0000280 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000281
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000282 unsigned getGPR(int RegNo);
283
Toma Tabacu89a712b2015-04-15 10:48:56 +0000284 /// Returns the internal register number for the current AT. Also checks if
285 /// the current AT is unavailable (set to $0) and gives an error if it is.
286 /// This should be used in pseudo-instruction expansions which need AT.
287 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000288
289 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000290 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000291
292 // Helper function that checks if the value of a vector index is within the
293 // boundaries of accepted values for each RegisterKind
294 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
295 bool validateMSAIndex(int Val, int RegKind);
296
Daniel Sandersf0df2212014-08-04 12:20:00 +0000297 // Selects a new architecture by updating the FeatureBits with the necessary
298 // info including implied dependencies.
299 // Internally, it clears all the feature bits related to *any* architecture
300 // and selects the new one using the ToggleFeature functionality of the
301 // MCSubtargetInfo object that handles implied dependencies. The reason we
302 // clear all the arch related bits manually is because ToggleFeature only
303 // clears the features that imply the feature being cleared and not the
304 // features implied by the feature being cleared. This is easier to see
305 // with an example:
306 // --------------------------------------------------
307 // | Feature | Implies |
308 // | -------------------------------------------------|
309 // | FeatureMips1 | None |
310 // | FeatureMips2 | FeatureMips1 |
311 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
312 // | FeatureMips4 | FeatureMips3 |
313 // | ... | |
314 // --------------------------------------------------
315 //
316 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
317 // FeatureMipsGP64 | FeatureMips1)
318 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
319 void selectArch(StringRef ArchFeature) {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000320 uint64_t FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000321 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
322 STI.setFeatureBits(FeatureBits);
323 setAvailableFeatures(
324 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000325 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000326 }
327
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000328 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000329 if (!(STI.getFeatureBits() & Feature)) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000330 setAvailableFeatures(
331 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000332 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000333 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000334 }
335
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000336 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000337 if (STI.getFeatureBits() & Feature) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000338 setAvailableFeatures(
339 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000340 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000341 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000342 }
343
Rafael Espindola870c4e92012-01-11 03:56:41 +0000344public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000345 enum MipsMatchResultTy {
346 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
347#define GET_OPERAND_DIAGNOSTIC_TYPES
348#include "MipsGenAsmMatcher.inc"
349#undef GET_OPERAND_DIAGNOSTIC_TYPES
350
351 };
352
Joey Gouly0e76fa72013-09-12 10:28:05 +0000353 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000354 const MCInstrInfo &MII, const MCTargetOptions &Options)
Eric Christophera5762812015-01-26 17:33:46 +0000355 : MCTargetAsmParser(), STI(sti),
356 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
357 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000358 MCAsmParserExtension::Initialize(parser);
359
Toma Tabacu11e14a92015-04-21 11:50:52 +0000360 parser.addAliasForDirective(".asciiz", ".asciz");
361
Jack Carterb4dbc172012-09-05 23:34:03 +0000362 // Initialize the set of available features.
363 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000364
365 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000366 AssemblerOptions.push_back(
367 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000368
369 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000370 AssemblerOptions.push_back(
371 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000372
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000373 getTargetStreamer().updateABIInfo(*this);
374
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000375 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000376 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000377
378 CurrentFn = nullptr;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000379 }
380
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000381 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
382 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
383
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000384 bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; }
385 bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; }
Eric Christophera5762812015-01-26 17:33:46 +0000386 const MipsABIInfo &getABI() const { return ABI; }
387 bool isABI_N32() const { return ABI.IsN32(); }
388 bool isABI_N64() const { return ABI.IsN64(); }
389 bool isABI_O32() const { return ABI.IsO32(); }
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000390 bool isABI_FPXX() const { return STI.getFeatureBits() & Mips::FeatureFPXX; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000391
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000392 bool useOddSPReg() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000393 return !(STI.getFeatureBits() & Mips::FeatureNoOddSPReg);
Daniel Sanders7e527422014-07-10 13:38:23 +0000394 }
395
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000396 bool inMicroMipsMode() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000397 return STI.getFeatureBits() & Mips::FeatureMicroMips;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000398 }
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000399 bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; }
400 bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; }
401 bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; }
402 bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
403 bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000404 bool hasMips32() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000405 return (STI.getFeatureBits() & Mips::FeatureMips32);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000406 }
407 bool hasMips64() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000408 return (STI.getFeatureBits() & Mips::FeatureMips64);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000409 }
410 bool hasMips32r2() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000411 return (STI.getFeatureBits() & Mips::FeatureMips32r2);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000412 }
413 bool hasMips64r2() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000414 return (STI.getFeatureBits() & Mips::FeatureMips64r2);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000415 }
Daniel Sanders17793142015-02-18 16:24:50 +0000416 bool hasMips32r3() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000417 return (STI.getFeatureBits() & Mips::FeatureMips32r3);
Daniel Sanders17793142015-02-18 16:24:50 +0000418 }
419 bool hasMips64r3() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000420 return (STI.getFeatureBits() & Mips::FeatureMips64r3);
Daniel Sanders17793142015-02-18 16:24:50 +0000421 }
422 bool hasMips32r5() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000423 return (STI.getFeatureBits() & Mips::FeatureMips32r5);
Daniel Sanders17793142015-02-18 16:24:50 +0000424 }
425 bool hasMips64r5() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000426 return (STI.getFeatureBits() & Mips::FeatureMips64r5);
Daniel Sanders17793142015-02-18 16:24:50 +0000427 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000428 bool hasMips32r6() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000429 return (STI.getFeatureBits() & Mips::FeatureMips32r6);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000430 }
431 bool hasMips64r6() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000432 return (STI.getFeatureBits() & Mips::FeatureMips64r6);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000433 }
Kai Nackee0245392015-01-27 19:11:28 +0000434 bool hasCnMips() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000435 return (STI.getFeatureBits() & Mips::FeatureCnMips);
Kai Nackee0245392015-01-27 19:11:28 +0000436 }
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000437 bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
438 bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
439 bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000440
441 bool inMips16Mode() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000442 return STI.getFeatureBits() & Mips::FeatureMips16;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000443 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000444
Eric Christophere8ae3e32015-05-07 23:10:21 +0000445 bool useSoftFloat() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000446 return (STI.getFeatureBits() & Mips::FeatureSoftFloat);
Toma Tabacu506cfd02015-05-07 10:29:52 +0000447 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000448
Toma Tabacud9d344b2015-04-27 14:05:04 +0000449 /// Warn if RegIndex is the same as the current AT.
450 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000451};
452}
453
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000454namespace {
455
456/// MipsOperand - Instances of this class represent a parsed Mips machine
457/// instruction.
458class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000459public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000460 /// Broad categories of register classes
461 /// The exact class is finalized by the render method.
462 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000463 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000464 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000465 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000466 RegKind_FCC = 4, /// FCC
467 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
468 RegKind_MSACtrl = 16, /// MSA control registers
469 RegKind_COP2 = 32, /// COP2
470 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
471 /// context).
472 RegKind_CCR = 128, /// CCR
473 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000474 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000475
476 /// Potentially any (e.g. $1)
477 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
478 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000479 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000480 };
481
482private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000483 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000484 k_Immediate, /// An immediate (possibly involving symbol references)
485 k_Memory, /// Base + Offset Memory Address
486 k_PhysRegister, /// A physical register from the Mips namespace
487 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000488 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000489 k_RegList, /// A physical register list
490 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000491 } Kind;
492
David Blaikie960ea3f2014-06-08 16:18:35 +0000493public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000494 MipsOperand(KindTy K, MipsAsmParser &Parser)
495 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
496
David Blaikie960ea3f2014-06-08 16:18:35 +0000497private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000498 /// For diagnostics, and checking the assembler temporary
499 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000500
Eric Christopher8996c5d2013-03-15 00:42:55 +0000501 struct Token {
502 const char *Data;
503 unsigned Length;
504 };
505
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000506 struct PhysRegOp {
507 unsigned Num; /// Register Number
508 };
509
510 struct RegIdxOp {
511 unsigned Index; /// Index into the register class
512 RegKind Kind; /// Bitfield of the kinds it could possibly be
513 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000514 };
515
516 struct ImmOp {
517 const MCExpr *Val;
518 };
519
520 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000521 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000522 const MCExpr *Off;
523 };
524
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000525 struct RegListOp {
526 SmallVector<unsigned, 10> *List;
527 };
528
Jack Carterb4dbc172012-09-05 23:34:03 +0000529 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000530 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000531 struct PhysRegOp PhysReg;
532 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000533 struct ImmOp Imm;
534 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000535 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000536 };
537
538 SMLoc StartLoc, EndLoc;
539
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000540 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000541 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
542 const MCRegisterInfo *RegInfo,
543 SMLoc S, SMLoc E,
544 MipsAsmParser &Parser) {
545 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000546 Op->RegIdx.Index = Index;
547 Op->RegIdx.RegInfo = RegInfo;
548 Op->RegIdx.Kind = RegKind;
549 Op->StartLoc = S;
550 Op->EndLoc = E;
551 return Op;
552 }
553
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000554public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000555 /// Coerce the register to GPR32 and return the real register for the current
556 /// target.
557 unsigned getGPR32Reg() const {
558 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000559 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000560 unsigned ClassID = Mips::GPR32RegClassID;
561 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000562 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000563
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000564 /// Coerce the register to GPR32 and return the real register for the current
565 /// target.
566 unsigned getGPRMM16Reg() const {
567 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
568 unsigned ClassID = Mips::GPR32RegClassID;
569 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
570 }
571
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000572 /// Coerce the register to GPR64 and return the real register for the current
573 /// target.
574 unsigned getGPR64Reg() const {
575 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
576 unsigned ClassID = Mips::GPR64RegClassID;
577 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000578 }
579
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000580private:
581 /// Coerce the register to AFGR64 and return the real register for the current
582 /// target.
583 unsigned getAFGR64Reg() const {
584 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
585 if (RegIdx.Index % 2 != 0)
586 AsmParser.Warning(StartLoc, "Float register should be even.");
587 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
588 .getRegister(RegIdx.Index / 2);
589 }
590
591 /// Coerce the register to FGR64 and return the real register for the current
592 /// target.
593 unsigned getFGR64Reg() const {
594 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
595 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
596 .getRegister(RegIdx.Index);
597 }
598
599 /// Coerce the register to FGR32 and return the real register for the current
600 /// target.
601 unsigned getFGR32Reg() const {
602 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
603 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
604 .getRegister(RegIdx.Index);
605 }
606
607 /// Coerce the register to FGRH32 and return the real register for the current
608 /// target.
609 unsigned getFGRH32Reg() const {
610 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
611 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
612 .getRegister(RegIdx.Index);
613 }
614
615 /// Coerce the register to FCC and return the real register for the current
616 /// target.
617 unsigned getFCCReg() const {
618 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
619 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
620 .getRegister(RegIdx.Index);
621 }
622
623 /// Coerce the register to MSA128 and return the real register for the current
624 /// target.
625 unsigned getMSA128Reg() const {
626 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
627 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
628 // identical
629 unsigned ClassID = Mips::MSA128BRegClassID;
630 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
631 }
632
633 /// Coerce the register to MSACtrl and return the real register for the
634 /// current target.
635 unsigned getMSACtrlReg() const {
636 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
637 unsigned ClassID = Mips::MSACtrlRegClassID;
638 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
639 }
640
641 /// Coerce the register to COP2 and return the real register for the
642 /// current target.
643 unsigned getCOP2Reg() const {
644 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
645 unsigned ClassID = Mips::COP2RegClassID;
646 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
647 }
648
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000649 /// Coerce the register to COP3 and return the real register for the
650 /// current target.
651 unsigned getCOP3Reg() const {
652 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
653 unsigned ClassID = Mips::COP3RegClassID;
654 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
655 }
656
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000657 /// Coerce the register to ACC64DSP and return the real register for the
658 /// current target.
659 unsigned getACC64DSPReg() const {
660 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
661 unsigned ClassID = Mips::ACC64DSPRegClassID;
662 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
663 }
664
665 /// Coerce the register to HI32DSP and return the real register for the
666 /// current target.
667 unsigned getHI32DSPReg() const {
668 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
669 unsigned ClassID = Mips::HI32DSPRegClassID;
670 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
671 }
672
673 /// Coerce the register to LO32DSP and return the real register for the
674 /// current target.
675 unsigned getLO32DSPReg() const {
676 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
677 unsigned ClassID = Mips::LO32DSPRegClassID;
678 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
679 }
680
681 /// Coerce the register to CCR and return the real register for the
682 /// current target.
683 unsigned getCCRReg() const {
684 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
685 unsigned ClassID = Mips::CCRRegClassID;
686 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
687 }
688
689 /// Coerce the register to HWRegs and return the real register for the
690 /// current target.
691 unsigned getHWRegsReg() const {
692 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
693 unsigned ClassID = Mips::HWRegsRegClassID;
694 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
695 }
696
697public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000698 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000699 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000700 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000701 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000702 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000703 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000704 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000705 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000706 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000707
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000708 void addRegOperands(MCInst &Inst, unsigned N) const {
709 llvm_unreachable("Use a custom parser instead");
710 }
711
Daniel Sanders21bce302014-04-01 12:35:23 +0000712 /// Render the operand to an MCInst as a GPR32
713 /// Asserts if the wrong number of operands are requested, or the operand
714 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000715 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
716 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000717 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000718 }
719
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000720 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
721 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000722 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000723 }
724
Jozef Kolek1904fa22014-11-24 14:25:53 +0000725 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
726 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000727 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000728 }
729
Zoran Jovanovic41688672015-02-10 16:36:20 +0000730 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
731 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000732 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000733 }
734
Daniel Sanders21bce302014-04-01 12:35:23 +0000735 /// Render the operand to an MCInst as a GPR64
736 /// Asserts if the wrong number of operands are requested, or the operand
737 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000738 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
739 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000740 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000741 }
742
743 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
744 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000745 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000746 }
747
748 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
749 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000750 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000751 }
752
753 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
754 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000755 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000756 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000757 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000758 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
759 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000760 }
761
762 void addFGRH32AsmRegOperands(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(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000765 }
766
767 void addFCCAsmRegOperands(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(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000770 }
771
772 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
773 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000774 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000775 }
776
777 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
778 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000779 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000780 }
781
782 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
783 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000784 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000785 }
786
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000787 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
788 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000789 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000790 }
791
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000792 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
793 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000794 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000795 }
796
797 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
798 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000799 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000800 }
801
802 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
803 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000804 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000805 }
806
807 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
808 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000809 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000810 }
811
812 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
813 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000814 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000815 }
816
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000817 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000818 assert(N == 1 && "Invalid number of operands!");
819 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000820 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000821 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000822
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000823 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000824 assert(N == 2 && "Invalid number of operands!");
825
Jim Grosbache9119e42015-05-13 18:37:00 +0000826 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000827
828 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000829 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000830 }
831
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000832 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
833 assert(N == 2 && "Invalid number of operands!");
834
Jim Grosbache9119e42015-05-13 18:37:00 +0000835 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000836
837 const MCExpr *Expr = getMemOff();
838 addExpr(Inst, Expr);
839 }
840
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000841 void addRegListOperands(MCInst &Inst, unsigned N) const {
842 assert(N == 1 && "Invalid number of operands!");
843
844 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000845 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000846 }
847
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000848 void addRegPairOperands(MCInst &Inst, unsigned N) const {
849 assert(N == 2 && "Invalid number of operands!");
850 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +0000851 Inst.addOperand(MCOperand::createReg(RegNo++));
852 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000853 }
854
Zoran Jovanovic41688672015-02-10 16:36:20 +0000855 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
856 assert(N == 2 && "Invalid number of operands!");
857 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000858 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000859 }
860
Craig Topper56c590a2014-04-29 07:58:02 +0000861 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000862 // As a special case until we sort out the definition of div/divu, pretend
863 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
864 if (isGPRAsmReg() && RegIdx.Index == 0)
865 return true;
866
867 return Kind == k_PhysRegister;
868 }
869 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000870 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000871 bool isConstantImm() const {
872 return isImm() && dyn_cast<MCConstantExpr>(getImm());
873 }
Craig Topper56c590a2014-04-29 07:58:02 +0000874 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000875 // Note: It's not possible to pretend that other operand kinds are tokens.
876 // The matcher emitter checks tokens first.
877 return Kind == k_Token;
878 }
Craig Topper56c590a2014-04-29 07:58:02 +0000879 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000880 bool isConstantMemOff() const {
881 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
882 }
883 template <unsigned Bits> bool isMemWithSimmOffset() const {
884 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
885 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000886 bool isMemWithGRPMM16Base() const {
887 return isMem() && getMemBase()->isMM16AsmReg();
888 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000889 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
890 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
891 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
892 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000893 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
894 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
895 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
896 && (getMemBase()->getGPR32Reg() == Mips::SP);
897 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000898 bool isRegList16() const {
899 if (!isRegList())
900 return false;
901
902 int Size = RegList.List->size();
903 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
904 RegList.List->back() != Mips::RA)
905 return false;
906
907 int PrevReg = *RegList.List->begin();
908 for (int i = 1; i < Size - 1; i++) {
909 int Reg = (*(RegList.List))[i];
910 if ( Reg != PrevReg + 1)
911 return false;
912 PrevReg = Reg;
913 }
914
915 return true;
916 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000917 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000918 bool isLSAImm() const {
919 if (!isConstantImm())
920 return false;
921 int64_t Val = getConstantImm();
922 return 1 <= Val && Val <= 4;
923 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000924 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +0000925 bool isMovePRegPair() const {
926 if (Kind != k_RegList || RegList.List->size() != 2)
927 return false;
928
929 unsigned R0 = RegList.List->front();
930 unsigned R1 = RegList.List->back();
931
932 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
933 (R0 == Mips::A1 && R1 == Mips::A3) ||
934 (R0 == Mips::A2 && R1 == Mips::A3) ||
935 (R0 == Mips::A0 && R1 == Mips::S5) ||
936 (R0 == Mips::A0 && R1 == Mips::S6) ||
937 (R0 == Mips::A0 && R1 == Mips::A1) ||
938 (R0 == Mips::A0 && R1 == Mips::A2) ||
939 (R0 == Mips::A0 && R1 == Mips::A3))
940 return true;
941
942 return false;
943 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000944
945 StringRef getToken() const {
946 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000947 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000948 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000949 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000950
Craig Topper56c590a2014-04-29 07:58:02 +0000951 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000952 // As a special case until we sort out the definition of div/divu, pretend
953 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
954 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
955 RegIdx.Kind & RegKind_GPR)
956 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000957
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000958 assert(Kind == k_PhysRegister && "Invalid access!");
959 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000960 }
961
Jack Carterb4dbc172012-09-05 23:34:03 +0000962 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000963 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000964 return Imm.Val;
965 }
966
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000967 int64_t getConstantImm() const {
968 const MCExpr *Val = getImm();
969 return static_cast<const MCConstantExpr *>(Val)->getValue();
970 }
971
972 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000973 assert((Kind == k_Memory) && "Invalid access!");
974 return Mem.Base;
975 }
976
977 const MCExpr *getMemOff() const {
978 assert((Kind == k_Memory) && "Invalid access!");
979 return Mem.Off;
980 }
981
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000982 int64_t getConstantMemOff() const {
983 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
984 }
985
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000986 const SmallVectorImpl<unsigned> &getRegList() const {
987 assert((Kind == k_RegList) && "Invalid access!");
988 return *(RegList.List);
989 }
990
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000991 unsigned getRegPair() const {
992 assert((Kind == k_RegPair) && "Invalid access!");
993 return RegIdx.Index;
994 }
995
David Blaikie960ea3f2014-06-08 16:18:35 +0000996 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
997 MipsAsmParser &Parser) {
998 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000999 Op->Tok.Data = Str.data();
1000 Op->Tok.Length = Str.size();
1001 Op->StartLoc = S;
1002 Op->EndLoc = S;
1003 return Op;
1004 }
1005
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001006 /// Create a numeric register (e.g. $1). The exact register remains
1007 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001008 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001009 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001010 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001011 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001012 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001013 }
1014
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001015 /// Create a register that is definitely a GPR.
1016 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001017 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001018 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001019 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001020 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001021 }
1022
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001023 /// Create a register that is definitely a FGR.
1024 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001025 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001026 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001027 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001028 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1029 }
1030
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001031 /// Create a register that is definitely a HWReg.
1032 /// This is typically only used for named registers such as $hwr_cpunum.
1033 static std::unique_ptr<MipsOperand>
1034 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1035 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1036 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1037 }
1038
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001039 /// Create a register that is definitely an FCC.
1040 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001041 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001042 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001043 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001044 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1045 }
1046
1047 /// Create a register that is definitely an ACC.
1048 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001049 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001050 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001051 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001052 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1053 }
1054
1055 /// Create a register that is definitely an MSA128.
1056 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001057 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001058 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001059 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001060 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1061 }
1062
1063 /// Create a register that is definitely an MSACtrl.
1064 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001065 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001066 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001067 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001068 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1069 }
1070
David Blaikie960ea3f2014-06-08 16:18:35 +00001071 static std::unique_ptr<MipsOperand>
1072 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1073 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001074 Op->Imm.Val = Val;
1075 Op->StartLoc = S;
1076 Op->EndLoc = E;
1077 return Op;
1078 }
1079
David Blaikie960ea3f2014-06-08 16:18:35 +00001080 static std::unique_ptr<MipsOperand>
1081 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1082 SMLoc E, MipsAsmParser &Parser) {
1083 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1084 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001085 Op->Mem.Off = Off;
1086 Op->StartLoc = S;
1087 Op->EndLoc = E;
1088 return Op;
1089 }
1090
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001091 static std::unique_ptr<MipsOperand>
1092 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1093 MipsAsmParser &Parser) {
1094 assert (Regs.size() > 0 && "Empty list not allowed");
1095
1096 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001097 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001098 Op->StartLoc = StartLoc;
1099 Op->EndLoc = EndLoc;
1100 return Op;
1101 }
1102
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001103 static std::unique_ptr<MipsOperand>
1104 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1105 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1106 Op->RegIdx.Index = RegNo;
1107 Op->StartLoc = S;
1108 Op->EndLoc = E;
1109 return Op;
1110 }
1111
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001112 bool isGPRAsmReg() const {
1113 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001114 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001115 bool isMM16AsmReg() const {
1116 if (!(isRegIdx() && RegIdx.Kind))
1117 return false;
1118 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1119 || RegIdx.Index == 16 || RegIdx.Index == 17);
1120 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001121 bool isMM16AsmRegZero() const {
1122 if (!(isRegIdx() && RegIdx.Kind))
1123 return false;
1124 return (RegIdx.Index == 0 ||
1125 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1126 RegIdx.Index == 17);
1127 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001128 bool isMM16AsmRegMoveP() const {
1129 if (!(isRegIdx() && RegIdx.Kind))
1130 return false;
1131 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1132 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1133 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001134 bool isFGRAsmReg() const {
1135 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1136 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001137 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001138 bool isHWRegsAsmReg() const {
1139 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001140 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001141 bool isCCRAsmReg() const {
1142 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001143 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001144 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001145 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1146 return false;
1147 if (!AsmParser.hasEightFccRegisters())
1148 return RegIdx.Index == 0;
1149 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001150 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001151 bool isACCAsmReg() const {
1152 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001153 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001154 bool isCOP2AsmReg() const {
1155 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001156 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001157 bool isCOP3AsmReg() const {
1158 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1159 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001160 bool isMSA128AsmReg() const {
1161 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001162 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001163 bool isMSACtrlAsmReg() const {
1164 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001165 }
1166
Jack Carterb4dbc172012-09-05 23:34:03 +00001167 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001168 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001169 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001170 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001171
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001172 virtual ~MipsOperand() {
1173 switch (Kind) {
1174 case k_Immediate:
1175 break;
1176 case k_Memory:
1177 delete Mem.Base;
1178 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001179 case k_RegList:
1180 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001181 case k_PhysRegister:
1182 case k_RegisterIndex:
1183 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001184 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001185 break;
1186 }
1187 }
1188
Craig Topper56c590a2014-04-29 07:58:02 +00001189 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001190 switch (Kind) {
1191 case k_Immediate:
1192 OS << "Imm<";
1193 Imm.Val->print(OS);
1194 OS << ">";
1195 break;
1196 case k_Memory:
1197 OS << "Mem<";
1198 Mem.Base->print(OS);
1199 OS << ", ";
1200 Mem.Off->print(OS);
1201 OS << ">";
1202 break;
1203 case k_PhysRegister:
1204 OS << "PhysReg<" << PhysReg.Num << ">";
1205 break;
1206 case k_RegisterIndex:
1207 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1208 break;
1209 case k_Token:
1210 OS << Tok.Data;
1211 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001212 case k_RegList:
1213 OS << "RegList< ";
1214 for (auto Reg : (*RegList.List))
1215 OS << Reg << " ";
1216 OS << ">";
1217 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001218 case k_RegPair:
1219 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1220 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001221 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001222 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001223}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001224} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001225
Jack Carter9e65aa32013-03-22 00:05:30 +00001226namespace llvm {
1227extern const MCInstrDesc MipsInsts[];
1228}
1229static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1230 return MipsInsts[Opcode];
1231}
1232
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001233static bool hasShortDelaySlot(unsigned Opcode) {
1234 switch (Opcode) {
1235 case Mips::JALS_MM:
1236 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001237 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001238 case Mips::BGEZALS_MM:
1239 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001240 return true;
1241 default:
1242 return false;
1243 }
1244}
1245
Jack Carter9e65aa32013-03-22 00:05:30 +00001246bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001247 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001248 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001249
Jack Carter9e65aa32013-03-22 00:05:30 +00001250 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001251
1252 if (MCID.isBranch() || MCID.isCall()) {
1253 const unsigned Opcode = Inst.getOpcode();
1254 MCOperand Offset;
1255
1256 switch (Opcode) {
1257 default:
1258 break;
Kai Nackee0245392015-01-27 19:11:28 +00001259 case Mips::BBIT0:
1260 case Mips::BBIT032:
1261 case Mips::BBIT1:
1262 case Mips::BBIT132:
1263 assert(hasCnMips() && "instruction only valid for octeon cpus");
1264 // Fall through
1265
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001266 case Mips::BEQ:
1267 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001268 case Mips::BEQ_MM:
1269 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001270 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001271 Offset = Inst.getOperand(2);
1272 if (!Offset.isImm())
1273 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001274 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001275 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001276 if (OffsetToAlignment(Offset.getImm(),
1277 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001278 return Error(IDLoc, "branch to misaligned address");
1279 break;
1280 case Mips::BGEZ:
1281 case Mips::BGTZ:
1282 case Mips::BLEZ:
1283 case Mips::BLTZ:
1284 case Mips::BGEZAL:
1285 case Mips::BLTZAL:
1286 case Mips::BC1F:
1287 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001288 case Mips::BGEZ_MM:
1289 case Mips::BGTZ_MM:
1290 case Mips::BLEZ_MM:
1291 case Mips::BLTZ_MM:
1292 case Mips::BGEZAL_MM:
1293 case Mips::BLTZAL_MM:
1294 case Mips::BC1F_MM:
1295 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001296 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001297 Offset = Inst.getOperand(1);
1298 if (!Offset.isImm())
1299 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001300 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001301 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001302 if (OffsetToAlignment(Offset.getImm(),
1303 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001304 return Error(IDLoc, "branch to misaligned address");
1305 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001306 case Mips::BEQZ16_MM:
1307 case Mips::BNEZ16_MM:
1308 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1309 Offset = Inst.getOperand(1);
1310 if (!Offset.isImm())
1311 break; // We'll deal with this situation later on when applying fixups.
1312 if (!isIntN(8, Offset.getImm()))
1313 return Error(IDLoc, "branch target out of range");
1314 if (OffsetToAlignment(Offset.getImm(), 2LL))
1315 return Error(IDLoc, "branch to misaligned address");
1316 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001317 }
1318 }
1319
Daniel Sandersa84989a2014-06-16 13:25:35 +00001320 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1321 // We still accept it but it is a normal nop.
1322 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1323 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1324 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1325 "nop instruction");
1326 }
1327
Kai Nackee0245392015-01-27 19:11:28 +00001328 if (hasCnMips()) {
1329 const unsigned Opcode = Inst.getOpcode();
1330 MCOperand Opnd;
1331 int Imm;
1332
1333 switch (Opcode) {
1334 default:
1335 break;
1336
1337 case Mips::BBIT0:
1338 case Mips::BBIT032:
1339 case Mips::BBIT1:
1340 case Mips::BBIT132:
1341 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1342 // The offset is handled above
1343 Opnd = Inst.getOperand(1);
1344 if (!Opnd.isImm())
1345 return Error(IDLoc, "expected immediate operand kind");
1346 Imm = Opnd.getImm();
1347 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1348 Opcode == Mips::BBIT1 ? 63 : 31))
1349 return Error(IDLoc, "immediate operand value out of range");
1350 if (Imm > 31) {
1351 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1352 : Mips::BBIT132);
1353 Inst.getOperand(1).setImm(Imm - 32);
1354 }
1355 break;
1356
1357 case Mips::CINS:
1358 case Mips::CINS32:
1359 case Mips::EXTS:
1360 case Mips::EXTS32:
1361 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1362 // Check length
1363 Opnd = Inst.getOperand(3);
1364 if (!Opnd.isImm())
1365 return Error(IDLoc, "expected immediate operand kind");
1366 Imm = Opnd.getImm();
1367 if (Imm < 0 || Imm > 31)
1368 return Error(IDLoc, "immediate operand value out of range");
1369 // Check position
1370 Opnd = Inst.getOperand(2);
1371 if (!Opnd.isImm())
1372 return Error(IDLoc, "expected immediate operand kind");
1373 Imm = Opnd.getImm();
1374 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1375 Opcode == Mips::EXTS ? 63 : 31))
1376 return Error(IDLoc, "immediate operand value out of range");
1377 if (Imm > 31) {
1378 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1379 Inst.getOperand(2).setImm(Imm - 32);
1380 }
1381 break;
1382
1383 case Mips::SEQi:
1384 case Mips::SNEi:
1385 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1386 Opnd = Inst.getOperand(2);
1387 if (!Opnd.isImm())
1388 return Error(IDLoc, "expected immediate operand kind");
1389 Imm = Opnd.getImm();
1390 if (!isInt<10>(Imm))
1391 return Error(IDLoc, "immediate operand value out of range");
1392 break;
1393 }
1394 }
1395
Jack Carter9e65aa32013-03-22 00:05:30 +00001396 if (MCID.mayLoad() || MCID.mayStore()) {
1397 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001398 // reference or immediate we may have to expand instructions.
1399 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001400 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001401 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1402 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001403 MCOperand &Op = Inst.getOperand(i);
1404 if (Op.isImm()) {
1405 int MemOffset = Op.getImm();
1406 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001407 // Offset can't exceed 16bit value.
1408 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001409 return false;
1410 }
1411 } else if (Op.isExpr()) {
1412 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001413 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001414 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001415 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001416 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001417 // Expand symbol.
1418 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001419 return false;
1420 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001421 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001422 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001423 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001424 }
1425 }
1426 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001427 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001428 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001429
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001430 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001431 if (MCID.mayLoad()) {
1432 // Try to create 16-bit GP relative load instruction.
1433 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1434 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1435 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1436 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1437 MCOperand &Op = Inst.getOperand(i);
1438 if (Op.isImm()) {
1439 int MemOffset = Op.getImm();
1440 MCOperand &DstReg = Inst.getOperand(0);
1441 MCOperand &BaseReg = Inst.getOperand(1);
1442 if (isIntN(9, MemOffset) && (MemOffset % 4 == 0) &&
1443 getContext().getRegisterInfo()->getRegClass(
1444 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
1445 BaseReg.getReg() == Mips::GP) {
1446 MCInst TmpInst;
1447 TmpInst.setLoc(IDLoc);
1448 TmpInst.setOpcode(Mips::LWGP_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00001449 TmpInst.addOperand(MCOperand::createReg(DstReg.getReg()));
1450 TmpInst.addOperand(MCOperand::createReg(Mips::GP));
1451 TmpInst.addOperand(MCOperand::createImm(MemOffset));
Jozef Koleke10a02e2015-01-28 17:27:26 +00001452 Instructions.push_back(TmpInst);
1453 return false;
1454 }
1455 }
1456 }
1457 } // for
1458 } // if load
1459
1460 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1461
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001462 MCOperand Opnd;
1463 int Imm;
1464
1465 switch (Inst.getOpcode()) {
1466 default:
1467 break;
1468 case Mips::ADDIUS5_MM:
1469 Opnd = Inst.getOperand(2);
1470 if (!Opnd.isImm())
1471 return Error(IDLoc, "expected immediate operand kind");
1472 Imm = Opnd.getImm();
1473 if (Imm < -8 || Imm > 7)
1474 return Error(IDLoc, "immediate operand value out of range");
1475 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001476 case Mips::ADDIUSP_MM:
1477 Opnd = Inst.getOperand(0);
1478 if (!Opnd.isImm())
1479 return Error(IDLoc, "expected immediate operand kind");
1480 Imm = Opnd.getImm();
1481 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1482 Imm % 4 != 0)
1483 return Error(IDLoc, "immediate operand value out of range");
1484 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001485 case Mips::SLL16_MM:
1486 case Mips::SRL16_MM:
1487 Opnd = Inst.getOperand(2);
1488 if (!Opnd.isImm())
1489 return Error(IDLoc, "expected immediate operand kind");
1490 Imm = Opnd.getImm();
1491 if (Imm < 1 || Imm > 8)
1492 return Error(IDLoc, "immediate operand value out of range");
1493 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001494 case Mips::LI16_MM:
1495 Opnd = Inst.getOperand(1);
1496 if (!Opnd.isImm())
1497 return Error(IDLoc, "expected immediate operand kind");
1498 Imm = Opnd.getImm();
1499 if (Imm < -1 || Imm > 126)
1500 return Error(IDLoc, "immediate operand value out of range");
1501 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001502 case Mips::ADDIUR2_MM:
1503 Opnd = Inst.getOperand(2);
1504 if (!Opnd.isImm())
1505 return Error(IDLoc, "expected immediate operand kind");
1506 Imm = Opnd.getImm();
1507 if (!(Imm == 1 || Imm == -1 ||
1508 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1509 return Error(IDLoc, "immediate operand value out of range");
1510 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001511 case Mips::ADDIUR1SP_MM:
1512 Opnd = Inst.getOperand(1);
1513 if (!Opnd.isImm())
1514 return Error(IDLoc, "expected immediate operand kind");
1515 Imm = Opnd.getImm();
1516 if (OffsetToAlignment(Imm, 4LL))
1517 return Error(IDLoc, "misaligned immediate operand value");
1518 if (Imm < 0 || Imm > 255)
1519 return Error(IDLoc, "immediate operand value out of range");
1520 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001521 case Mips::ANDI16_MM:
1522 Opnd = Inst.getOperand(2);
1523 if (!Opnd.isImm())
1524 return Error(IDLoc, "expected immediate operand kind");
1525 Imm = Opnd.getImm();
1526 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1527 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1528 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1529 return Error(IDLoc, "immediate operand value out of range");
1530 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001531 case Mips::LBU16_MM:
1532 Opnd = Inst.getOperand(2);
1533 if (!Opnd.isImm())
1534 return Error(IDLoc, "expected immediate operand kind");
1535 Imm = Opnd.getImm();
1536 if (Imm < -1 || Imm > 14)
1537 return Error(IDLoc, "immediate operand value out of range");
1538 break;
1539 case Mips::SB16_MM:
1540 Opnd = Inst.getOperand(2);
1541 if (!Opnd.isImm())
1542 return Error(IDLoc, "expected immediate operand kind");
1543 Imm = Opnd.getImm();
1544 if (Imm < 0 || Imm > 15)
1545 return Error(IDLoc, "immediate operand value out of range");
1546 break;
1547 case Mips::LHU16_MM:
1548 case Mips::SH16_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 < 0 || Imm > 30 || (Imm % 2 != 0))
1554 return Error(IDLoc, "immediate operand value out of range");
1555 break;
1556 case Mips::LW16_MM:
1557 case Mips::SW16_MM:
1558 Opnd = Inst.getOperand(2);
1559 if (!Opnd.isImm())
1560 return Error(IDLoc, "expected immediate operand kind");
1561 Imm = Opnd.getImm();
1562 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1563 return Error(IDLoc, "immediate operand value out of range");
1564 break;
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001565 case Mips::CACHE:
1566 case Mips::PREF:
1567 Opnd = Inst.getOperand(2);
1568 if (!Opnd.isImm())
1569 return Error(IDLoc, "expected immediate operand kind");
1570 Imm = Opnd.getImm();
1571 if (!isUInt<5>(Imm))
1572 return Error(IDLoc, "immediate operand value out of range");
1573 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001574 case Mips::ADDIUPC_MM:
1575 MCOperand Opnd = Inst.getOperand(1);
1576 if (!Opnd.isImm())
1577 return Error(IDLoc, "expected immediate operand kind");
1578 int Imm = Opnd.getImm();
1579 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1580 return Error(IDLoc, "immediate operand value out of range");
1581 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001582 }
1583 }
1584
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001585 if (needsExpansion(Inst)) {
1586 if (expandInstruction(Inst, IDLoc, Instructions))
1587 return true;
1588 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001589 Instructions.push_back(Inst);
1590
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001591 // If this instruction has a delay slot and .set reorder is active,
1592 // emit a NOP after it.
1593 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1594 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1595
Jack Carter9e65aa32013-03-22 00:05:30 +00001596 return false;
1597}
1598
Jack Carter30a59822012-10-04 04:03:53 +00001599bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1600
Jack Carterd0bd6422013-04-18 00:41:53 +00001601 switch (Inst.getOpcode()) {
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001602 case Mips::LoadImm32:
1603 case Mips::LoadImm64:
1604 case Mips::LoadAddrImm32:
1605 case Mips::LoadAddrReg32:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001606 case Mips::B_MM_Pseudo:
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001607 case Mips::LWM_MM:
1608 case Mips::SWM_MM:
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001609 case Mips::JalOneReg:
1610 case Mips::JalTwoReg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001611 return true;
1612 default:
1613 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001614 }
1615}
Jack Carter92995f12012-10-06 00:53:28 +00001616
Matheus Almeida3813d572014-06-19 14:39:14 +00001617bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001618 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001619 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001620 default: llvm_unreachable("unimplemented expansion");
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001621 case Mips::LoadImm32:
Toma Tabacu00e98672015-05-01 12:19:27 +00001622 return expandLoadImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001623 case Mips::LoadImm64:
Toma Tabacu00e98672015-05-01 12:19:27 +00001624 return expandLoadImm(Inst, false, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001625 case Mips::LoadAddrImm32:
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001626 return expandLoadAddressImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001627 case Mips::LoadAddrReg32:
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001628 return expandLoadAddressReg(Inst, true, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001629 case Mips::B_MM_Pseudo:
1630 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001631 case Mips::SWM_MM:
1632 case Mips::LWM_MM:
1633 return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001634 case Mips::JalOneReg:
1635 case Mips::JalTwoReg:
1636 return expandJalWithRegs(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001637 }
Jack Carter30a59822012-10-04 04:03:53 +00001638}
Jack Carter92995f12012-10-06 00:53:28 +00001639
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001640namespace {
Toma Tabacua2861db2015-05-01 10:26:47 +00001641template <unsigned ShiftAmount>
Toma Tabacu61145652015-04-28 13:16:06 +00001642void createLShiftOri(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001643 SmallVectorImpl<MCInst> &Instructions) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001644 MCInst tmpInst;
Toma Tabacua2861db2015-05-01 10:26:47 +00001645 if (ShiftAmount >= 32) {
1646 tmpInst.setOpcode(Mips::DSLL32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001647 tmpInst.addOperand(MCOperand::createReg(RegNo));
1648 tmpInst.addOperand(MCOperand::createReg(RegNo));
1649 tmpInst.addOperand(MCOperand::createImm(ShiftAmount - 32));
Toma Tabacua2861db2015-05-01 10:26:47 +00001650 tmpInst.setLoc(IDLoc);
1651 Instructions.push_back(tmpInst);
1652 tmpInst.clear();
1653 } else if (ShiftAmount > 0) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001654 tmpInst.setOpcode(Mips::DSLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00001655 tmpInst.addOperand(MCOperand::createReg(RegNo));
1656 tmpInst.addOperand(MCOperand::createReg(RegNo));
1657 tmpInst.addOperand(MCOperand::createImm(ShiftAmount));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001658 tmpInst.setLoc(IDLoc);
1659 Instructions.push_back(tmpInst);
1660 tmpInst.clear();
1661 }
Toma Tabacu7dea2e32015-04-28 14:06:35 +00001662 // There's no need for an ORi if the immediate is 0.
1663 if (Operand.isImm() && Operand.getImm() == 0)
1664 return;
1665
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001666 tmpInst.setOpcode(Mips::ORi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001667 tmpInst.addOperand(MCOperand::createReg(RegNo));
1668 tmpInst.addOperand(MCOperand::createReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001669 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001670 tmpInst.setLoc(IDLoc);
1671 Instructions.push_back(tmpInst);
1672}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001673
Toma Tabacua2861db2015-05-01 10:26:47 +00001674template <unsigned ShiftAmount>
Toma Tabacu61145652015-04-28 13:16:06 +00001675void createLShiftOri(int64_t Value, unsigned RegNo, SMLoc IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001676 SmallVectorImpl<MCInst> &Instructions) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001677 createLShiftOri<ShiftAmount>(MCOperand::createImm(Value), RegNo, IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001678 Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001679}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001680}
1681
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001682bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
1683 SmallVectorImpl<MCInst> &Instructions) {
1684 // Create a JALR instruction which is going to replace the pseudo-JAL.
1685 MCInst JalrInst;
1686 JalrInst.setLoc(IDLoc);
1687 const MCOperand FirstRegOp = Inst.getOperand(0);
1688 const unsigned Opcode = Inst.getOpcode();
1689
1690 if (Opcode == Mips::JalOneReg) {
1691 // jal $rs => jalr $rs
1692 if (inMicroMipsMode()) {
1693 JalrInst.setOpcode(Mips::JALR16_MM);
1694 JalrInst.addOperand(FirstRegOp);
1695 } else {
1696 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00001697 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001698 JalrInst.addOperand(FirstRegOp);
1699 }
1700 } else if (Opcode == Mips::JalTwoReg) {
1701 // jal $rd, $rs => jalr $rd, $rs
1702 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
1703 JalrInst.addOperand(FirstRegOp);
1704 const MCOperand SecondRegOp = Inst.getOperand(1);
1705 JalrInst.addOperand(SecondRegOp);
1706 }
1707 Instructions.push_back(JalrInst);
1708
1709 // If .set reorder is active, emit a NOP after it.
1710 if (AssemblerOptions.back()->isReorder()) {
1711 // This is a 32-bit NOP because these 2 pseudo-instructions
1712 // do not have a short delay slot.
1713 MCInst NopInst;
1714 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00001715 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
1716 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
1717 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001718 Instructions.push_back(NopInst);
1719 }
1720
1721 return false;
1722}
1723
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001724bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
1725 unsigned SrcReg, bool Is32BitImm, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001726 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00001727 if (!Is32BitImm && !isGP64bit()) {
1728 Error(IDLoc, "instruction requires a 64-bit architecture");
1729 return true;
1730 }
1731
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001732 bool UseSrcReg = false;
1733 if (SrcReg != Mips::NoRegister)
1734 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00001735
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001736 MCInst tmpInst;
1737
Jack Carter92995f12012-10-06 00:53:28 +00001738 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001739 // FIXME: gas has a special case for values that are 000...1111, which
1740 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001741 if (0 <= ImmValue && ImmValue <= 65535) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001742 // For unsigned and positive signed 16-bit values (0 <= j <= 65535):
Jack Carter30a59822012-10-04 04:03:53 +00001743 // li d,j => ori d,$zero,j
Toma Tabacudf7fd462015-05-13 16:02:41 +00001744 if (!UseSrcReg)
1745 SrcReg = isGP64bit() ? Mips::ZERO_64 : Mips::ZERO;
Jack Carter873c7242013-01-12 01:03:14 +00001746 tmpInst.setOpcode(Mips::ORi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001747 tmpInst.addOperand(MCOperand::createReg(DstReg));
1748 tmpInst.addOperand(MCOperand::createReg(SrcReg));
1749 tmpInst.addOperand(MCOperand::createImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001750 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001751 } else if (ImmValue < 0 && ImmValue >= -32768) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001752 // For negative signed 16-bit values (-32768 <= j < 0):
Jack Carter30a59822012-10-04 04:03:53 +00001753 // li d,j => addiu d,$zero,j
Toma Tabacudf7fd462015-05-13 16:02:41 +00001754 if (!UseSrcReg)
1755 SrcReg = Mips::ZERO;
Jack Carter873c7242013-01-12 01:03:14 +00001756 tmpInst.setOpcode(Mips::ADDiu);
Jim Grosbache9119e42015-05-13 18:37:00 +00001757 tmpInst.addOperand(MCOperand::createReg(DstReg));
1758 tmpInst.addOperand(MCOperand::createReg(SrcReg));
1759 tmpInst.addOperand(MCOperand::createImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001760 Instructions.push_back(tmpInst);
Toma Tabacua3d056f2015-05-15 09:42:11 +00001761 } else if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacue625b5f2015-05-14 14:51:32 +00001762 if (!AssemblerOptions.back()->isMacro())
1763 Warning(IDLoc, "macro instruction expanded into multiple instructions");
1764
Toma Tabacuae47f932015-04-10 13:28:16 +00001765 // For all other values which are representable as a 32-bit integer:
Jack Carter30a59822012-10-04 04:03:53 +00001766 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001767 // ori d,d,lo16(j)
Toma Tabacu79588102015-04-29 10:19:56 +00001768 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1769 uint16_t Bits15To0 = ImmValue & 0xffff;
1770
Toma Tabacua3d056f2015-05-15 09:42:11 +00001771 if (!Is32BitImm && !isInt<32>(ImmValue)) {
1772 // For DLI, expand to an ORi instead of a LUi to avoid sign-extending the
1773 // upper 32 bits.
1774 tmpInst.setOpcode(Mips::ORi);
1775 tmpInst.addOperand(MCOperand::createReg(DstReg));
1776 tmpInst.addOperand(MCOperand::createReg(Mips::ZERO));
1777 tmpInst.addOperand(MCOperand::createImm(Bits31To16));
1778 tmpInst.setLoc(IDLoc);
1779 Instructions.push_back(tmpInst);
1780 // Move the value to the upper 16 bits by doing a 16-bit left shift.
1781 createLShiftOri<16>(0, DstReg, IDLoc, Instructions);
1782 } else {
1783 tmpInst.setOpcode(Mips::LUi);
1784 tmpInst.addOperand(MCOperand::createReg(DstReg));
1785 tmpInst.addOperand(MCOperand::createImm(Bits31To16));
1786 Instructions.push_back(tmpInst);
1787 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001788 createLShiftOri<0>(Bits15To0, DstReg, IDLoc, Instructions);
1789
1790 if (UseSrcReg)
1791 createAddu(DstReg, DstReg, SrcReg, Instructions);
1792
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001793 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Toma Tabacu00e98672015-05-01 12:19:27 +00001794 if (Is32BitImm) {
1795 Error(IDLoc, "instruction requires a 32-bit immediate");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001796 return true;
1797 }
Toma Tabacue625b5f2015-05-14 14:51:32 +00001798 if (!AssemblerOptions.back()->isMacro())
1799 Warning(IDLoc, "macro instruction expanded into multiple instructions");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001800
1801 // <------- lo32 ------>
1802 // <------- hi32 ------>
1803 // <- hi16 -> <- lo16 ->
1804 // _________________________________
1805 // | | | |
Toma Tabacubda745f2015-04-27 15:21:38 +00001806 // | 16-bits | 16-bits | 16-bits |
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001807 // |__________|__________|__________|
1808 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001809 // For any 64-bit value that is representable as a 48-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001810 // li d,j => lui d,hi16(j)
1811 // ori d,d,hi16(lo32(j))
1812 // dsll d,d,16
1813 // ori d,d,lo16(lo32(j))
Toma Tabacu79588102015-04-29 10:19:56 +00001814 uint16_t Bits47To32 = (ImmValue >> 32) & 0xffff;
1815 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1816 uint16_t Bits15To0 = ImmValue & 0xffff;
1817
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001818 tmpInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001819 tmpInst.addOperand(MCOperand::createReg(DstReg));
1820 tmpInst.addOperand(MCOperand::createImm(Bits47To32));
Jack Carter30a59822012-10-04 04:03:53 +00001821 Instructions.push_back(tmpInst);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001822 createLShiftOri<0>(Bits31To16, DstReg, IDLoc, Instructions);
1823 createLShiftOri<16>(Bits15To0, DstReg, IDLoc, Instructions);
1824
1825 if (UseSrcReg)
1826 createAddu(DstReg, DstReg, SrcReg, Instructions);
1827
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001828 } else {
Toma Tabacu00e98672015-05-01 12:19:27 +00001829 if (Is32BitImm) {
1830 Error(IDLoc, "instruction requires a 32-bit immediate");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001831 return true;
1832 }
Toma Tabacue625b5f2015-05-14 14:51:32 +00001833 if (!AssemblerOptions.back()->isMacro())
1834 Warning(IDLoc, "macro instruction expanded into multiple instructions");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001835
1836 // <------- hi32 ------> <------- lo32 ------>
1837 // <- hi16 -> <- lo16 ->
1838 // ___________________________________________
1839 // | | | | |
Toma Tabacubda745f2015-04-27 15:21:38 +00001840 // | 16-bits | 16-bits | 16-bits | 16-bits |
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001841 // |__________|__________|__________|__________|
1842 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001843 // For all other values which are representable as a 64-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001844 // li d,j => lui d,hi16(j)
1845 // ori d,d,lo16(hi32(j))
1846 // dsll d,d,16
1847 // ori d,d,hi16(lo32(j))
1848 // dsll d,d,16
1849 // ori d,d,lo16(lo32(j))
Toma Tabacu79588102015-04-29 10:19:56 +00001850 uint16_t Bits63To48 = (ImmValue >> 48) & 0xffff;
1851 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(Bits63To48));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001858 Instructions.push_back(tmpInst);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001859 createLShiftOri<0>(Bits47To32, DstReg, IDLoc, Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001860
1861 // When Bits31To16 is 0, do a left shift of 32 bits instead of doing
1862 // two left shifts of 16 bits.
1863 if (Bits31To16 == 0) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001864 createLShiftOri<32>(Bits15To0, DstReg, IDLoc, Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001865 } else {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001866 createLShiftOri<16>(Bits31To16, DstReg, IDLoc, Instructions);
1867 createLShiftOri<16>(Bits15To0, DstReg, IDLoc, Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001868 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001869
1870 if (UseSrcReg)
1871 createAddu(DstReg, DstReg, SrcReg, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001872 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001873 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001874}
Jack Carter92995f12012-10-06 00:53:28 +00001875
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001876bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
1877 SmallVectorImpl<MCInst> &Instructions) {
1878 const MCOperand &ImmOp = Inst.getOperand(1);
1879 assert(ImmOp.isImm() && "expected immediate operand kind");
1880 const MCOperand &DstRegOp = Inst.getOperand(0);
1881 assert(DstRegOp.isReg() && "expected register operand kind");
1882
1883 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
1884 Is32BitImm, IDLoc, Instructions))
1885 return true;
1886
1887 return false;
1888}
1889
Matheus Almeida3813d572014-06-19 14:39:14 +00001890bool
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001891MipsAsmParser::expandLoadAddressReg(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001892 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacub5592ee2015-05-14 10:02:58 +00001893 const MCOperand &DstRegOp = Inst.getOperand(0);
1894 assert(DstRegOp.isReg() && "expected register operand kind");
1895
Jack Carter543fdf82012-10-09 23:29:45 +00001896 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001897 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1898 "expected immediate operand kind");
1899 if (!ImmOp.isImm()) {
Toma Tabacuec1de822015-05-14 10:53:40 +00001900 expandLoadAddressSym(DstRegOp, ImmOp, Is32BitImm, IDLoc, Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001901 return false;
1902 }
Jack Carter543fdf82012-10-09 23:29:45 +00001903 const MCOperand &SrcRegOp = Inst.getOperand(1);
1904 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001905
1906 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), SrcRegOp.getReg(),
1907 Is32BitImm, IDLoc, Instructions))
1908 return true;
1909
Matheus Almeida3813d572014-06-19 14:39:14 +00001910 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001911}
1912
Matheus Almeida3813d572014-06-19 14:39:14 +00001913bool
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001914MipsAsmParser::expandLoadAddressImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001915 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacub5592ee2015-05-14 10:02:58 +00001916 const MCOperand &DstRegOp = Inst.getOperand(0);
1917 assert(DstRegOp.isReg() && "expected register operand kind");
1918
Jack Carter543fdf82012-10-09 23:29:45 +00001919 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001920 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1921 "expected immediate operand kind");
1922 if (!ImmOp.isImm()) {
Toma Tabacuec1de822015-05-14 10:53:40 +00001923 expandLoadAddressSym(DstRegOp, ImmOp, Is32BitImm, IDLoc, Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001924 return false;
1925 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001926
1927 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
1928 Is32BitImm, IDLoc, Instructions))
1929 return true;
1930
Matheus Almeida3813d572014-06-19 14:39:14 +00001931 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001932}
1933
Toma Tabacuec1de822015-05-14 10:53:40 +00001934void MipsAsmParser::expandLoadAddressSym(
1935 const MCOperand &DstRegOp, const MCOperand &SymOp, bool Is32BitSym,
1936 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacue625b5f2015-05-14 14:51:32 +00001937 if (!AssemblerOptions.back()->isMacro())
1938 Warning(IDLoc, "macro instruction expanded into multiple instructions");
1939
Toma Tabacuec1de822015-05-14 10:53:40 +00001940 if (Is32BitSym && isABI_N64())
1941 Warning(IDLoc, "instruction loads the 32-bit address of a 64-bit symbol");
1942
Toma Tabacu0d64b202014-08-14 10:29:17 +00001943 MCInst tmpInst;
Toma Tabacub5592ee2015-05-14 10:02:58 +00001944 unsigned RegNo = DstRegOp.getReg();
Toma Tabacu0d64b202014-08-14 10:29:17 +00001945 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1946 const MCSymbolRefExpr *HiExpr =
1947 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1948 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1949 const MCSymbolRefExpr *LoExpr =
1950 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1951 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
Toma Tabacuec1de822015-05-14 10:53:40 +00001952 if (!Is32BitSym) {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001953 // If it's a 64-bit architecture, expand to:
1954 // la d,sym => lui d,highest(sym)
1955 // ori d,d,higher(sym)
1956 // dsll d,d,16
1957 // ori d,d,hi16(sym)
1958 // dsll d,d,16
1959 // ori d,d,lo16(sym)
1960 const MCSymbolRefExpr *HighestExpr =
1961 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1962 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1963 const MCSymbolRefExpr *HigherExpr =
1964 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1965 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1966
1967 tmpInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001968 tmpInst.addOperand(MCOperand::createReg(RegNo));
1969 tmpInst.addOperand(MCOperand::createExpr(HighestExpr));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001970 Instructions.push_back(tmpInst);
1971
Jim Grosbache9119e42015-05-13 18:37:00 +00001972 createLShiftOri<0>(MCOperand::createExpr(HigherExpr), RegNo, SMLoc(),
Toma Tabacua2861db2015-05-01 10:26:47 +00001973 Instructions);
Jim Grosbache9119e42015-05-13 18:37:00 +00001974 createLShiftOri<16>(MCOperand::createExpr(HiExpr), RegNo, SMLoc(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00001975 Instructions);
Jim Grosbache9119e42015-05-13 18:37:00 +00001976 createLShiftOri<16>(MCOperand::createExpr(LoExpr), RegNo, SMLoc(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00001977 Instructions);
1978 } else {
1979 // Otherwise, expand to:
1980 // la d,sym => lui d,hi16(sym)
1981 // ori d,d,lo16(sym)
1982 tmpInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001983 tmpInst.addOperand(MCOperand::createReg(RegNo));
1984 tmpInst.addOperand(MCOperand::createExpr(HiExpr));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001985 Instructions.push_back(tmpInst);
1986
Jim Grosbache9119e42015-05-13 18:37:00 +00001987 createLShiftOri<0>(MCOperand::createExpr(LoExpr), RegNo, SMLoc(),
Toma Tabacua2861db2015-05-01 10:26:47 +00001988 Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001989 }
1990}
1991
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00001992bool MipsAsmParser::expandUncondBranchMMPseudo(
1993 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00001994 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
1995 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001996
1997 MCOperand Offset = Inst.getOperand(0);
1998 if (Offset.isExpr()) {
1999 Inst.clear();
2000 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002001 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2002 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2003 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002004 } else {
2005 assert(Offset.isImm() && "expected immediate operand kind");
2006 if (isIntN(11, Offset.getImm())) {
2007 // If offset fits into 11 bits then this instruction becomes microMIPS
2008 // 16-bit unconditional branch instruction.
2009 Inst.setOpcode(Mips::B16_MM);
2010 } else {
2011 if (!isIntN(17, Offset.getImm()))
2012 Error(IDLoc, "branch target out of range");
2013 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2014 Error(IDLoc, "branch to misaligned address");
2015 Inst.clear();
2016 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002017 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2018 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2019 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002020 }
2021 }
2022 Instructions.push_back(Inst);
2023
Toma Tabacu234482a2015-03-16 12:03:39 +00002024 // If .set reorder is active, emit a NOP after the branch instruction.
2025 if (AssemblerOptions.back()->isReorder())
2026 createNop(true, IDLoc, Instructions);
2027
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002028 return false;
2029}
2030
Jack Carter9e65aa32013-03-22 00:05:30 +00002031void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002032 SmallVectorImpl<MCInst> &Instructions,
2033 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002034 const MCSymbolRefExpr *SR;
2035 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00002036 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002037 const MCExpr *ExprOffset;
2038 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002039 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002040 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2041 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002042 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002043 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2044 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002045 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002046 if (isImmOpnd) {
2047 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2048 ImmOffset = Inst.getOperand(2).getImm();
2049 LoOffset = ImmOffset & 0x0000ffff;
2050 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002051 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002052 if (LoOffset & 0x8000)
2053 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002054 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002055 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002056 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002057 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002058 // These are some of the types of expansions we perform here:
2059 // 1) lw $8, sym => lui $8, %hi(sym)
2060 // lw $8, %lo(sym)($8)
2061 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2062 // add $8, $8, $9
2063 // lw $8, %lo(offset)($9)
2064 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2065 // add $at, $at, $8
2066 // lw $8, %lo(offset)($at)
2067 // 4) sw $8, sym => lui $at, %hi(sym)
2068 // sw $8, %lo(sym)($at)
2069 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2070 // add $at, $at, $8
2071 // sw $8, %lo(offset)($at)
2072 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2073 // ldc1 $f0, %lo(sym)($at)
2074 //
2075 // For load instructions we can use the destination register as a temporary
2076 // if base and dst are different (examples 1 and 2) and if the base register
2077 // is general purpose otherwise we must use $at (example 6) and error if it's
2078 // not available. For stores we must use $at (examples 4 and 5) because we
2079 // must not clobber the source register setting up the offset.
2080 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2081 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2082 unsigned RegClassIDOp0 =
2083 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2084 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2085 (RegClassIDOp0 == Mips::GPR64RegClassID);
2086 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002087 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002088 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002089 // At this point we need AT to perform the expansions and we exit if it is
2090 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002091 TmpRegNum = getATReg(IDLoc);
2092 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002093 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002094 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002095
Jack Carter9e65aa32013-03-22 00:05:30 +00002096 TempInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00002097 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002098 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002099 TempInst.addOperand(MCOperand::createImm(HiOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002100 else {
2101 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002102 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00002103 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
2104 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
2105 getContext());
Jim Grosbache9119e42015-05-13 18:37:00 +00002106 TempInst.addOperand(MCOperand::createExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002107 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002108 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jim Grosbache9119e42015-05-13 18:37:00 +00002109 TempInst.addOperand(MCOperand::createExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002110 }
2111 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002112 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002113 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002114 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002115 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002116 // Add temp register to base.
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002117 if (BaseRegNum != Mips::ZERO) {
2118 TempInst.setOpcode(Mips::ADDu);
Jim Grosbache9119e42015-05-13 18:37:00 +00002119 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2120 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2121 TempInst.addOperand(MCOperand::createReg(BaseRegNum));
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002122 Instructions.push_back(TempInst);
2123 TempInst.clear();
2124 }
Alp Tokercb402912014-01-24 17:20:08 +00002125 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002126 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002127 TempInst.setOpcode(Inst.getOpcode());
Jim Grosbache9119e42015-05-13 18:37:00 +00002128 TempInst.addOperand(MCOperand::createReg(RegOpNum));
2129 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002130 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002131 TempInst.addOperand(MCOperand::createImm(LoOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002132 else {
2133 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002134 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
2135 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
2136 getContext());
Jim Grosbache9119e42015-05-13 18:37:00 +00002137 TempInst.addOperand(MCOperand::createExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002138 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002139 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jim Grosbache9119e42015-05-13 18:37:00 +00002140 TempInst.addOperand(MCOperand::createExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002141 }
2142 }
2143 Instructions.push_back(TempInst);
2144 TempInst.clear();
2145}
2146
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002147bool
2148MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2149 SmallVectorImpl<MCInst> &Instructions) {
2150 unsigned OpNum = Inst.getNumOperands();
2151 unsigned Opcode = Inst.getOpcode();
2152 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2153
2154 assert (Inst.getOperand(OpNum - 1).isImm() &&
2155 Inst.getOperand(OpNum - 2).isReg() &&
2156 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2157
2158 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2159 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2160 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2161 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2162 // It can be implemented as SWM16 or LWM16 instruction.
2163 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2164
2165 Inst.setOpcode(NewOpcode);
2166 Instructions.push_back(Inst);
2167 return false;
2168}
2169
Toma Tabacu234482a2015-03-16 12:03:39 +00002170void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
2171 SmallVectorImpl<MCInst> &Instructions) {
2172 MCInst NopInst;
2173 if (hasShortDelaySlot) {
2174 NopInst.setOpcode(Mips::MOVE16_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002175 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2176 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
Toma Tabacu234482a2015-03-16 12:03:39 +00002177 } else {
2178 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00002179 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2180 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2181 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu234482a2015-03-16 12:03:39 +00002182 }
2183 Instructions.push_back(NopInst);
2184}
2185
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002186void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
2187 unsigned TrgReg,
2188 SmallVectorImpl<MCInst> &Instructions) {
2189 MCInst AdduInst;
2190 AdduInst.setOpcode(Mips::ADDu);
Jim Grosbache9119e42015-05-13 18:37:00 +00002191 AdduInst.addOperand(MCOperand::createReg(DstReg));
2192 AdduInst.addOperand(MCOperand::createReg(SrcReg));
2193 AdduInst.addOperand(MCOperand::createReg(TrgReg));
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002194 Instructions.push_back(AdduInst);
2195}
2196
Matheus Almeida595fcab2014-06-11 15:05:56 +00002197unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
2198 // As described by the Mips32r2 spec, the registers Rd and Rs for
2199 // jalr.hb must be different.
2200 unsigned Opcode = Inst.getOpcode();
2201
2202 if (Opcode == Mips::JALR_HB &&
2203 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
2204 return Match_RequiresDifferentSrcAndDst;
2205
2206 return Match_Success;
2207}
2208
David Blaikie960ea3f2014-06-08 16:18:35 +00002209bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
2210 OperandVector &Operands,
2211 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00002212 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00002213 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00002214
Jack Carterb4dbc172012-09-05 23:34:03 +00002215 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00002216 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00002217 unsigned MatchResult =
2218 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00002219
2220 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002221 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002222 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00002223 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00002224 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00002225 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00002226 return false;
2227 }
2228 case Match_MissingFeature:
2229 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
2230 return true;
2231 case Match_InvalidOperand: {
2232 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00002233 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002234 if (ErrorInfo >= Operands.size())
2235 return Error(IDLoc, "too few operands for instruction");
2236
David Blaikie960ea3f2014-06-08 16:18:35 +00002237 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00002238 if (ErrorLoc == SMLoc())
2239 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00002240 }
2241
2242 return Error(ErrorLoc, "invalid operand for instruction");
2243 }
2244 case Match_MnemonicFail:
2245 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00002246 case Match_RequiresDifferentSrcAndDst:
2247 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00002248 }
Craig Topper589ceee2015-01-03 08:16:34 +00002249
2250 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00002251}
2252
Toma Tabacud9d344b2015-04-27 14:05:04 +00002253void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
2254 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
2255 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
2256 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002257}
2258
Daniel Sandersef638fe2014-10-03 15:37:37 +00002259void
2260MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
2261 SMRange Range, bool ShowColors) {
2262 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00002263 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00002264 ShowColors);
2265}
2266
Jack Carter1ac53222013-02-20 23:11:17 +00002267int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002268 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002269
Vladimir Medic4c299852013-11-06 11:27:05 +00002270 CC = StringSwitch<unsigned>(Name)
2271 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002272 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00002273 .Case("a0", 4)
2274 .Case("a1", 5)
2275 .Case("a2", 6)
2276 .Case("a3", 7)
2277 .Case("v0", 2)
2278 .Case("v1", 3)
2279 .Case("s0", 16)
2280 .Case("s1", 17)
2281 .Case("s2", 18)
2282 .Case("s3", 19)
2283 .Case("s4", 20)
2284 .Case("s5", 21)
2285 .Case("s6", 22)
2286 .Case("s7", 23)
2287 .Case("k0", 26)
2288 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002289 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00002290 .Case("sp", 29)
2291 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002292 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00002293 .Case("ra", 31)
2294 .Case("t0", 8)
2295 .Case("t1", 9)
2296 .Case("t2", 10)
2297 .Case("t3", 11)
2298 .Case("t4", 12)
2299 .Case("t5", 13)
2300 .Case("t6", 14)
2301 .Case("t7", 15)
2302 .Case("t8", 24)
2303 .Case("t9", 25)
2304 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002305
Toma Tabacufda445c2014-09-15 15:33:01 +00002306 if (!(isABI_N32() || isABI_N64()))
2307 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002308
Daniel Sandersef638fe2014-10-03 15:37:37 +00002309 if (12 <= CC && CC <= 15) {
2310 // Name is one of t4-t7
2311 AsmToken RegTok = getLexer().peekTok();
2312 SMRange RegRange = RegTok.getLocRange();
2313
2314 StringRef FixedName = StringSwitch<StringRef>(Name)
2315 .Case("t4", "t0")
2316 .Case("t5", "t1")
2317 .Case("t6", "t2")
2318 .Case("t7", "t3")
2319 .Default("");
2320 assert(FixedName != "" && "Register name is not one of t4-t7.");
2321
2322 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
2323 "Did you mean $" + FixedName + "?", RegRange);
2324 }
2325
Toma Tabacufda445c2014-09-15 15:33:01 +00002326 // Although SGI documentation just cuts out t0-t3 for n32/n64,
2327 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
2328 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
2329 if (8 <= CC && CC <= 11)
2330 CC += 4;
2331
2332 if (CC == -1)
2333 CC = StringSwitch<unsigned>(Name)
2334 .Case("a4", 8)
2335 .Case("a5", 9)
2336 .Case("a6", 10)
2337 .Case("a7", 11)
2338 .Case("kt0", 26)
2339 .Case("kt1", 27)
2340 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002341
2342 return CC;
2343}
Jack Carterd0bd6422013-04-18 00:41:53 +00002344
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002345int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
2346 int CC;
2347
2348 CC = StringSwitch<unsigned>(Name)
2349 .Case("hwr_cpunum", 0)
2350 .Case("hwr_synci_step", 1)
2351 .Case("hwr_cc", 2)
2352 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00002353 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002354 .Default(-1);
2355
2356 return CC;
2357}
2358
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002359int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002360
Jack Cartera63b16a2012-09-07 00:23:42 +00002361 if (Name[0] == 'f') {
2362 StringRef NumString = Name.substr(1);
2363 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002364 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002365 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002366 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00002367 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002368 return IntVal;
2369 }
2370 return -1;
2371}
Jack Cartera63b16a2012-09-07 00:23:42 +00002372
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002373int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
2374
2375 if (Name.startswith("fcc")) {
2376 StringRef NumString = Name.substr(3);
2377 unsigned IntVal;
2378 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002379 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002380 if (IntVal > 7) // There are only 8 fcc registers.
2381 return -1;
2382 return IntVal;
2383 }
2384 return -1;
2385}
2386
2387int MipsAsmParser::matchACRegisterName(StringRef Name) {
2388
Akira Hatanaka274d24c2013-08-14 01:15:52 +00002389 if (Name.startswith("ac")) {
2390 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002391 unsigned IntVal;
2392 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002393 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002394 if (IntVal > 3) // There are only 3 acc registers.
2395 return -1;
2396 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00002397 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002398 return -1;
2399}
Jack Carterd0bd6422013-04-18 00:41:53 +00002400
Jack Carter5dc8ac92013-09-25 23:50:44 +00002401int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
2402 unsigned IntVal;
2403
2404 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2405 return -1;
2406
2407 if (IntVal > 31)
2408 return -1;
2409
2410 return IntVal;
2411}
2412
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002413int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
2414 int CC;
2415
2416 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00002417 .Case("msair", 0)
2418 .Case("msacsr", 1)
2419 .Case("msaaccess", 2)
2420 .Case("msasave", 3)
2421 .Case("msamodify", 4)
2422 .Case("msarequest", 5)
2423 .Case("msamap", 6)
2424 .Case("msaunmap", 7)
2425 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002426
2427 return CC;
2428}
2429
Toma Tabacu89a712b2015-04-15 10:48:56 +00002430unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00002431 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00002432 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002433 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00002434 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00002435 return 0;
2436 }
2437 unsigned AT = getReg(
2438 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00002439 return AT;
2440}
Jack Carter0b744b32012-10-04 02:29:46 +00002441
Jack Carterd0bd6422013-04-18 00:41:53 +00002442unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00002443 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00002444}
2445
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002446unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002447 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00002448 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002449}
2450
Jack Carter873c7242013-01-12 01:03:14 +00002451int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002452 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00002453 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00002454 return -1;
2455
Jack Carter873c7242013-01-12 01:03:14 +00002456 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00002457}
2458
Toma Tabacu13964452014-09-04 13:23:44 +00002459bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002460 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002461 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002462
Jack Carter30a59822012-10-04 04:03:53 +00002463 // Check if the current operand has a custom associated parser, if so, try to
2464 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00002465 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2466 if (ResTy == MatchOperand_Success)
2467 return false;
2468 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2469 // there was a match, but an error occurred, in which case, just return that
2470 // the operand parsing failed.
2471 if (ResTy == MatchOperand_ParseFail)
2472 return true;
2473
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002474 DEBUG(dbgs() << ".. Generic Parser\n");
2475
Jack Carterb4dbc172012-09-05 23:34:03 +00002476 switch (getLexer().getKind()) {
2477 default:
2478 Error(Parser.getTok().getLoc(), "unexpected token in operand");
2479 return true;
2480 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002481 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00002482 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00002483
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002484 // Almost all registers have been parsed by custom parsers. There is only
2485 // one exception to this. $zero (and it's alias $0) will reach this point
2486 // for div, divu, and similar instructions because it is not an operand
2487 // to the instruction definition but an explicit register. Special case
2488 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00002489 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00002490 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002491
Jack Carterd0bd6422013-04-18 00:41:53 +00002492 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00002493 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002494 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00002495 return true;
2496
Jack Carter873c7242013-01-12 01:03:14 +00002497 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00002498 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00002499 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00002500 const MCExpr *Res =
2501 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00002502
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002503 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002504 return false;
2505 }
Vladimir Medic4c299852013-11-06 11:27:05 +00002506 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00002507 case AsmToken::LParen:
2508 case AsmToken::Minus:
2509 case AsmToken::Plus:
2510 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002511 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00002512 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002513 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002514 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002515 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00002516 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00002517 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002518 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002519 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002520 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00002521 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00002522 return true;
2523
Jack Carter873c7242013-01-12 01:03:14 +00002524 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2525
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002526 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00002527 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002528 } // case AsmToken::Percent
2529 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00002530 return true;
2531}
2532
Vladimir Medic4c299852013-11-06 11:27:05 +00002533const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00002534 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00002535 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00002536 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002537 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00002538 // It's a constant, evaluate reloc value.
2539 int16_t Val;
2540 switch (getVariantKind(RelocStr)) {
2541 case MCSymbolRefExpr::VK_Mips_ABS_LO:
2542 // Get the 1st 16-bits.
2543 Val = MCE->getValue() & 0xffff;
2544 break;
2545 case MCSymbolRefExpr::VK_Mips_ABS_HI:
2546 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2547 // 16 bits being negative.
2548 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2549 break;
2550 case MCSymbolRefExpr::VK_Mips_HIGHER:
2551 // Get the 3rd 16-bits.
2552 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2553 break;
2554 case MCSymbolRefExpr::VK_Mips_HIGHEST:
2555 // Get the 4th 16-bits.
2556 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2557 break;
2558 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00002559 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00002560 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00002561 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002562 }
2563
Jack Carterb5cf5902013-04-17 00:18:04 +00002564 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002565 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00002566 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00002567 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00002568 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002569 return Res;
2570 }
2571
2572 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00002573 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2574
Sasa Stankovic06c47802014-04-03 10:37:45 +00002575 // Try to create target expression.
2576 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
2577 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002578
Jack Carterd0bd6422013-04-18 00:41:53 +00002579 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2580 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00002581 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
2582 return Res;
2583 }
2584
2585 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002586 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
2587 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
2588 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002589 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002590 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002591 return Expr;
2592}
2593
2594bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2595
2596 switch (Expr->getKind()) {
2597 case MCExpr::Constant:
2598 return true;
2599 case MCExpr::SymbolRef:
2600 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2601 case MCExpr::Binary:
2602 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2603 if (!isEvaluated(BE->getLHS()))
2604 return false;
2605 return isEvaluated(BE->getRHS());
2606 }
2607 case MCExpr::Unary:
2608 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002609 case MCExpr::Target:
2610 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002611 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002612 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002613}
Jack Carterd0bd6422013-04-18 00:41:53 +00002614
Jack Carterb5cf5902013-04-17 00:18:04 +00002615bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002616 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00002617 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002618 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002619 if (Tok.isNot(AsmToken::Identifier))
2620 return true;
2621
Yaron Keren075759a2015-03-30 15:42:36 +00002622 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00002623
Jack Carterd0bd6422013-04-18 00:41:53 +00002624 Parser.Lex(); // Eat the identifier.
2625 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002626 const MCExpr *IdVal;
2627 SMLoc EndLoc;
2628
2629 if (getLexer().getKind() == AsmToken::LParen) {
2630 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002631 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002632 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002633 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002634 const AsmToken &nextTok = Parser.getTok();
2635 if (nextTok.isNot(AsmToken::Identifier))
2636 return true;
2637 Str += "(%";
2638 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002639 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002640 if (getLexer().getKind() != AsmToken::LParen)
2641 return true;
2642 } else
2643 break;
2644 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002645 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002646 return true;
2647
2648 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002649 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002650
2651 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002652 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002653
Jack Carterd0bd6422013-04-18 00:41:53 +00002654 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002655 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002656}
2657
Jack Carterb4dbc172012-09-05 23:34:03 +00002658bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2659 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002660 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002661 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002662 if (ResTy == MatchOperand_Success) {
2663 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002664 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002665 StartLoc = Operand.getStartLoc();
2666 EndLoc = Operand.getEndLoc();
2667
2668 // AFAIK, we only support numeric registers and named GPR's in CFI
2669 // directives.
2670 // Don't worry about eating tokens before failing. Using an unrecognised
2671 // register is a parse error.
2672 if (Operand.isGPRAsmReg()) {
2673 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002674 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002675 }
2676
2677 return (RegNo == (unsigned)-1);
2678 }
2679
2680 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002681 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002682}
2683
Jack Carterb5cf5902013-04-17 00:18:04 +00002684bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002685 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00002686 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002687 bool Result = true;
2688
2689 while (getLexer().getKind() == AsmToken::LParen)
2690 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002691
Jack Carterd0bd6422013-04-18 00:41:53 +00002692 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002693 default:
2694 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002695 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002696 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002697 case AsmToken::Integer:
2698 case AsmToken::Minus:
2699 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002700 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002701 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002702 else
2703 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002704 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002705 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002706 break;
Jack Carter873c7242013-01-12 01:03:14 +00002707 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002708 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002709 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002710 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002711}
2712
David Blaikie960ea3f2014-06-08 16:18:35 +00002713MipsAsmParser::OperandMatchResultTy
2714MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002715 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002716 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002717 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002718 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002719 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002720 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002721 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002722 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002723
Jack Carterb5cf5902013-04-17 00:18:04 +00002724 if (getLexer().getKind() == AsmToken::LParen) {
2725 Parser.Lex();
2726 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002727 }
2728
Jack Carterb5cf5902013-04-17 00:18:04 +00002729 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002730 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002731 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002732
Jack Carterd0bd6422013-04-18 00:41:53 +00002733 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002734 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002735 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2736 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002737 SMLoc E =
2738 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002739 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002740 return MatchOperand_Success;
2741 }
2742 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002743 SMLoc E =
2744 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002745
Jack Carterd0bd6422013-04-18 00:41:53 +00002746 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002747 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002748 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002749 S, E, *this);
2750 Operands.push_back(
2751 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002752 return MatchOperand_Success;
2753 }
2754 Error(Parser.getTok().getLoc(), "'(' expected");
2755 return MatchOperand_ParseFail;
2756 }
2757
Jack Carterd0bd6422013-04-18 00:41:53 +00002758 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002759 }
2760
Toma Tabacu13964452014-09-04 13:23:44 +00002761 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002762 if (Res != MatchOperand_Success)
2763 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002764
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002765 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002766 Error(Parser.getTok().getLoc(), "')' expected");
2767 return MatchOperand_ParseFail;
2768 }
2769
Jack Carter873c7242013-01-12 01:03:14 +00002770 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2771
Jack Carterd0bd6422013-04-18 00:41:53 +00002772 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002773
Craig Topper062a2ba2014-04-25 05:30:21 +00002774 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002775 IdVal = MCConstantExpr::Create(0, getContext());
2776
Jack Carterd0bd6422013-04-18 00:41:53 +00002777 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002778 std::unique_ptr<MipsOperand> op(
2779 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002780 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002781 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002782 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002783 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002784 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2785 int64_t Imm;
2786 if (IdVal->EvaluateAsAbsolute(Imm))
2787 IdVal = MCConstantExpr::Create(Imm, getContext());
2788 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2789 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2790 getContext());
2791 }
2792
David Blaikie960ea3f2014-06-08 16:18:35 +00002793 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002794 return MatchOperand_Success;
2795}
2796
David Blaikie960ea3f2014-06-08 16:18:35 +00002797bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002798 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00002799 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00002800 if (Sym) {
2801 SMLoc S = Parser.getTok().getLoc();
2802 const MCExpr *Expr;
2803 if (Sym->isVariable())
2804 Expr = Sym->getVariableValue();
2805 else
2806 return false;
2807 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002808 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002809 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002810 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002811 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002812 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002813 if (ResTy == MatchOperand_Success) {
2814 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002815 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002816 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002817 llvm_unreachable("Should never ParseFail");
2818 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002819 }
2820 } else if (Expr->getKind() == MCExpr::Constant) {
2821 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002822 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002823 Operands.push_back(
2824 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002825 return true;
2826 }
2827 }
2828 return false;
2829}
Jack Carterd0bd6422013-04-18 00:41:53 +00002830
Jack Carter873c7242013-01-12 01:03:14 +00002831MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002832MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002833 StringRef Identifier,
2834 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002835 int Index = matchCPURegisterName(Identifier);
2836 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002837 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002838 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2839 return MatchOperand_Success;
2840 }
2841
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002842 Index = matchHWRegsRegisterName(Identifier);
2843 if (Index != -1) {
2844 Operands.push_back(MipsOperand::createHWRegsReg(
2845 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2846 return MatchOperand_Success;
2847 }
2848
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002849 Index = matchFPURegisterName(Identifier);
2850 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002851 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002852 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2853 return MatchOperand_Success;
2854 }
2855
2856 Index = matchFCCRegisterName(Identifier);
2857 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002858 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002859 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2860 return MatchOperand_Success;
2861 }
2862
2863 Index = matchACRegisterName(Identifier);
2864 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002865 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002866 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2867 return MatchOperand_Success;
2868 }
2869
2870 Index = matchMSA128RegisterName(Identifier);
2871 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002872 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002873 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2874 return MatchOperand_Success;
2875 }
2876
2877 Index = matchMSA128CtrlRegisterName(Identifier);
2878 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002879 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002880 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2881 return MatchOperand_Success;
2882 }
2883
2884 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002885}
2886
2887MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002888MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002889 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00002890 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002891
2892 if (Token.is(AsmToken::Identifier)) {
2893 DEBUG(dbgs() << ".. identifier\n");
2894 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002895 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002896 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002897 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002898 } else if (Token.is(AsmToken::Integer)) {
2899 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002900 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002901 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2902 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002903 return MatchOperand_Success;
2904 }
2905
2906 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2907
2908 return MatchOperand_NoMatch;
2909}
2910
David Blaikie960ea3f2014-06-08 16:18:35 +00002911MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002912MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002913 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002914 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002915
2916 auto Token = Parser.getTok();
2917
2918 SMLoc S = Token.getLoc();
2919
2920 if (Token.isNot(AsmToken::Dollar)) {
2921 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2922 if (Token.is(AsmToken::Identifier)) {
2923 if (searchSymbolAlias(Operands))
2924 return MatchOperand_Success;
2925 }
2926 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2927 return MatchOperand_NoMatch;
2928 }
2929 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002930
Toma Tabacu13964452014-09-04 13:23:44 +00002931 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002932 if (ResTy == MatchOperand_Success) {
2933 Parser.Lex(); // $
2934 Parser.Lex(); // identifier
2935 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002936 return ResTy;
2937}
2938
2939MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002940MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002941 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002942 switch (getLexer().getKind()) {
2943 default:
2944 return MatchOperand_NoMatch;
2945 case AsmToken::LParen:
2946 case AsmToken::Minus:
2947 case AsmToken::Plus:
2948 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002949 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002950 case AsmToken::String:
2951 break;
2952 }
2953
2954 const MCExpr *IdVal;
2955 SMLoc S = Parser.getTok().getLoc();
2956 if (getParser().parseExpression(IdVal))
2957 return MatchOperand_ParseFail;
2958
2959 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2960 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2961 return MatchOperand_Success;
2962}
2963
David Blaikie960ea3f2014-06-08 16:18:35 +00002964MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002965MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002966 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002967 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002968
2969 SMLoc S = getLexer().getLoc();
2970
2971 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002972 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002973 if (ResTy != MatchOperand_NoMatch)
2974 return ResTy;
2975
Daniel Sanders315386c2014-04-01 10:40:14 +00002976 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002977 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002978 if (ResTy != MatchOperand_NoMatch)
2979 return ResTy;
2980
Daniel Sandersffd84362014-04-01 10:41:48 +00002981 const MCExpr *Expr = nullptr;
2982 if (Parser.parseExpression(Expr)) {
2983 // We have no way of knowing if a symbol was consumed so we must ParseFail
2984 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002985 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002986 Operands.push_back(
2987 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002988 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002989}
2990
Vladimir Medic2b953d02013-10-01 09:48:56 +00002991MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002992MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002993 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00002994 const MCExpr *IdVal;
2995 // If the first token is '$' we may have register operand.
2996 if (Parser.getTok().is(AsmToken::Dollar))
2997 return MatchOperand_NoMatch;
2998 SMLoc S = Parser.getTok().getLoc();
2999 if (getParser().parseExpression(IdVal))
3000 return MatchOperand_ParseFail;
3001 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00003002 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00003003 int64_t Val = MCE->getValue();
3004 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3005 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003006 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00003007 return MatchOperand_Success;
3008}
3009
Matheus Almeida779c5932013-11-18 12:32:49 +00003010MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003011MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003012 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00003013 switch (getLexer().getKind()) {
3014 default:
3015 return MatchOperand_NoMatch;
3016 case AsmToken::LParen:
3017 case AsmToken::Plus:
3018 case AsmToken::Minus:
3019 case AsmToken::Integer:
3020 break;
3021 }
3022
3023 const MCExpr *Expr;
3024 SMLoc S = Parser.getTok().getLoc();
3025
3026 if (getParser().parseExpression(Expr))
3027 return MatchOperand_ParseFail;
3028
3029 int64_t Val;
3030 if (!Expr->EvaluateAsAbsolute(Val)) {
3031 Error(S, "expected immediate value");
3032 return MatchOperand_ParseFail;
3033 }
3034
3035 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
3036 // and because the CPU always adds one to the immediate field, the allowed
3037 // range becomes 1..4. We'll only check the range here and will deal
3038 // with the addition/subtraction when actually decoding/encoding
3039 // the instruction.
3040 if (Val < 1 || Val > 4) {
3041 Error(S, "immediate not in range (1..4)");
3042 return MatchOperand_ParseFail;
3043 }
3044
Jack Carter3b2c96e2014-01-22 23:31:38 +00003045 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003046 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00003047 return MatchOperand_Success;
3048}
3049
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00003050MipsAsmParser::OperandMatchResultTy
3051MipsAsmParser::parseRegisterList(OperandVector &Operands) {
3052 MCAsmParser &Parser = getParser();
3053 SmallVector<unsigned, 10> Regs;
3054 unsigned RegNo;
3055 unsigned PrevReg = Mips::NoRegister;
3056 bool RegRange = false;
3057 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3058
3059 if (Parser.getTok().isNot(AsmToken::Dollar))
3060 return MatchOperand_ParseFail;
3061
3062 SMLoc S = Parser.getTok().getLoc();
3063 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
3064 SMLoc E = getLexer().getLoc();
3065 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
3066 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
3067 if (RegRange) {
3068 // Remove last register operand because registers from register range
3069 // should be inserted first.
3070 if (RegNo == Mips::RA) {
3071 Regs.push_back(RegNo);
3072 } else {
3073 unsigned TmpReg = PrevReg + 1;
3074 while (TmpReg <= RegNo) {
3075 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
3076 Error(E, "invalid register operand");
3077 return MatchOperand_ParseFail;
3078 }
3079
3080 PrevReg = TmpReg;
3081 Regs.push_back(TmpReg++);
3082 }
3083 }
3084
3085 RegRange = false;
3086 } else {
3087 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
3088 (RegNo != Mips::RA)) {
3089 Error(E, "$16 or $31 expected");
3090 return MatchOperand_ParseFail;
3091 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
3092 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3093 Error(E, "invalid register operand");
3094 return MatchOperand_ParseFail;
3095 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
3096 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3097 Error(E, "consecutive register numbers expected");
3098 return MatchOperand_ParseFail;
3099 }
3100
3101 Regs.push_back(RegNo);
3102 }
3103
3104 if (Parser.getTok().is(AsmToken::Minus))
3105 RegRange = true;
3106
3107 if (!Parser.getTok().isNot(AsmToken::Minus) &&
3108 !Parser.getTok().isNot(AsmToken::Comma)) {
3109 Error(E, "',' or '-' expected");
3110 return MatchOperand_ParseFail;
3111 }
3112
3113 Lex(); // Consume comma or minus
3114 if (Parser.getTok().isNot(AsmToken::Dollar))
3115 break;
3116
3117 PrevReg = RegNo;
3118 }
3119
3120 SMLoc E = Parser.getTok().getLoc();
3121 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3122 parseMemOperand(Operands);
3123 return MatchOperand_Success;
3124}
3125
Zoran Jovanovic2deca342014-12-16 14:59:10 +00003126MipsAsmParser::OperandMatchResultTy
3127MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
3128 MCAsmParser &Parser = getParser();
3129
3130 SMLoc S = Parser.getTok().getLoc();
3131 if (parseAnyRegister(Operands) != MatchOperand_Success)
3132 return MatchOperand_ParseFail;
3133
3134 SMLoc E = Parser.getTok().getLoc();
3135 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
3136 unsigned Reg = Op.getGPR32Reg();
3137 Operands.pop_back();
3138 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
3139 return MatchOperand_Success;
3140}
3141
Zoran Jovanovic41688672015-02-10 16:36:20 +00003142MipsAsmParser::OperandMatchResultTy
3143MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
3144 MCAsmParser &Parser = getParser();
3145 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3146 SmallVector<unsigned, 10> Regs;
3147
3148 if (Parser.getTok().isNot(AsmToken::Dollar))
3149 return MatchOperand_ParseFail;
3150
3151 SMLoc S = Parser.getTok().getLoc();
3152
3153 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3154 return MatchOperand_ParseFail;
3155
3156 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3157 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3158 Regs.push_back(RegNo);
3159
3160 SMLoc E = Parser.getTok().getLoc();
3161 if (Parser.getTok().isNot(AsmToken::Comma)) {
3162 Error(E, "',' expected");
3163 return MatchOperand_ParseFail;
3164 }
3165
3166 // Remove comma.
3167 Parser.Lex();
3168
3169 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3170 return MatchOperand_ParseFail;
3171
3172 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3173 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3174 Regs.push_back(RegNo);
3175
3176 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3177
3178 return MatchOperand_Success;
3179}
3180
Jack Carterdc1e35d2012-09-06 20:00:02 +00003181MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
3182
Vladimir Medic4c299852013-11-06 11:27:05 +00003183 MCSymbolRefExpr::VariantKind VK =
3184 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
3185 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
3186 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
3187 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
3188 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
3189 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
3190 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
3191 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
3192 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
3193 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
3194 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
3195 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
3196 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
3197 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
3198 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
3199 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
3200 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
3201 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00003202 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
3203 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
3204 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
3205 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
3206 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
3207 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00003208 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
3209 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00003210 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003211
Matheus Almeida2852af82014-04-22 10:15:54 +00003212 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00003213
Jack Carterdc1e35d2012-09-06 20:00:02 +00003214 return VK;
3215}
Jack Cartera63b16a2012-09-07 00:23:42 +00003216
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003217/// Sometimes (i.e. load/stores) the operand may be followed immediately by
3218/// either this.
3219/// ::= '(', register, ')'
3220/// handle it before we iterate so we don't get tripped up by the lack of
3221/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003222bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003223 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003224 if (getLexer().is(AsmToken::LParen)) {
3225 Operands.push_back(
3226 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
3227 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003228 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003229 SMLoc Loc = getLexer().getLoc();
3230 Parser.eatToEndOfStatement();
3231 return Error(Loc, "unexpected token in argument list");
3232 }
3233 if (Parser.getTok().isNot(AsmToken::RParen)) {
3234 SMLoc Loc = getLexer().getLoc();
3235 Parser.eatToEndOfStatement();
3236 return Error(Loc, "unexpected token, expected ')'");
3237 }
3238 Operands.push_back(
3239 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
3240 Parser.Lex();
3241 }
3242 return false;
3243}
3244
3245/// Sometimes (i.e. in MSA) the operand may be followed immediately by
3246/// either one of these.
3247/// ::= '[', register, ']'
3248/// ::= '[', integer, ']'
3249/// handle it before we iterate so we don't get tripped up by the lack of
3250/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003251bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00003252 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003253 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003254 if (getLexer().is(AsmToken::LBrac)) {
3255 Operands.push_back(
3256 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
3257 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003258 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003259 SMLoc Loc = getLexer().getLoc();
3260 Parser.eatToEndOfStatement();
3261 return Error(Loc, "unexpected token in argument list");
3262 }
3263 if (Parser.getTok().isNot(AsmToken::RBrac)) {
3264 SMLoc Loc = getLexer().getLoc();
3265 Parser.eatToEndOfStatement();
3266 return Error(Loc, "unexpected token, expected ']'");
3267 }
3268 Operands.push_back(
3269 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
3270 Parser.Lex();
3271 }
3272 return false;
3273}
3274
David Blaikie960ea3f2014-06-08 16:18:35 +00003275bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
3276 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003277 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003278 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003279
3280 // We have reached first instruction, module directive are now forbidden.
3281 getTargetStreamer().forbidModuleDirective();
3282
Vladimir Medic74593e62013-07-17 15:00:42 +00003283 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00003284 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00003285 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00003286 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00003287 }
Vladimir Medic64828a12013-07-16 10:07:14 +00003288 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003289 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003290
3291 // Read the remaining operands.
3292 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3293 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003294 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003295 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003296 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003297 return Error(Loc, "unexpected token in argument list");
3298 }
Toma Tabacu13964452014-09-04 13:23:44 +00003299 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003300 return true;
3301 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00003302
Jack Carterd0bd6422013-04-18 00:41:53 +00003303 while (getLexer().is(AsmToken::Comma)) {
3304 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00003305 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003306 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003307 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003308 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003309 return Error(Loc, "unexpected token in argument list");
3310 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003311 // Parse bracket and parenthesis suffixes before we iterate
3312 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00003313 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003314 return true;
3315 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00003316 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003317 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003318 }
3319 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003320 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3321 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003322 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003323 return Error(Loc, "unexpected token in argument list");
3324 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003325 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00003326 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00003327}
3328
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003329bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003330 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003331 SMLoc Loc = getLexer().getLoc();
3332 Parser.eatToEndOfStatement();
3333 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00003334}
3335
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003336bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003337 return Error(Loc, ErrorMsg);
3338}
3339
Jack Carter0b744b32012-10-04 02:29:46 +00003340bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003341 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003342 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00003343
3344 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00003345 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00003346
3347 Parser.Lex(); // Eat "noat".
3348
Jack Carterd0bd6422013-04-18 00:41:53 +00003349 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003350 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003351 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003352 return false;
3353 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003354
3355 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003356 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003357 return false;
3358}
Jack Carterd0bd6422013-04-18 00:41:53 +00003359
Jack Carter0b744b32012-10-04 02:29:46 +00003360bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00003361 // Line can be: ".set at", which sets $at to $1
3362 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00003363 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00003364 Parser.Lex(); // Eat "at".
3365
Jack Carter0b744b32012-10-04 02:29:46 +00003366 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003367 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00003368 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00003369
3370 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003371 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003372 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00003373 }
3374
3375 if (getLexer().isNot(AsmToken::Equal)) {
3376 reportParseError("unexpected token, expected equals sign");
3377 return false;
3378 }
3379 Parser.Lex(); // Eat "=".
3380
3381 if (getLexer().isNot(AsmToken::Dollar)) {
3382 if (getLexer().is(AsmToken::EndOfStatement)) {
3383 reportParseError("no register specified");
3384 return false;
3385 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00003386 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00003387 return false;
3388 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003389 }
3390 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00003391
Toma Tabacu16a74492015-02-13 10:30:57 +00003392 // Find out what "reg" is.
3393 unsigned AtRegNo;
3394 const AsmToken &Reg = Parser.getTok();
3395 if (Reg.is(AsmToken::Identifier)) {
3396 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
3397 } else if (Reg.is(AsmToken::Integer)) {
3398 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00003399 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00003400 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00003401 return false;
3402 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003403
3404 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00003405 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003406 reportParseError("invalid register");
3407 return false;
3408 }
3409 Parser.Lex(); // Eat "reg".
3410
3411 // If this is not the end of the statement, report an error.
3412 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3413 reportParseError("unexpected token, expected end of statement");
3414 return false;
3415 }
3416
3417 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
3418
3419 Parser.Lex(); // Consume the EndOfStatement.
3420 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003421}
3422
3423bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003424 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003425 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003426 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003427 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003428 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003429 return false;
3430 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003431 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00003432 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003433 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003434 return false;
3435}
3436
3437bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003438 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003439 Parser.Lex();
3440 // If this is not the end of the statement, report an error.
3441 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003442 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003443 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003444 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003445 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00003446 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003447 Parser.Lex(); // Consume the EndOfStatement.
3448 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003449}
3450
3451bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003452 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003453 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003454 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003455 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003456 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003457 return false;
3458 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003459 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00003460 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003461 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003462 return false;
3463}
3464
3465bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003466 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003467 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003468 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003469 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003470 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003471 return false;
3472 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003473 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00003474 reportParseError("`noreorder' must be set before `nomacro'");
3475 return false;
3476 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003477 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00003478 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003479 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003480 return false;
3481}
Jack Carterd76b2372013-03-21 21:44:16 +00003482
Daniel Sanders44934432014-08-07 12:03:36 +00003483bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003484 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003485 Parser.Lex();
3486
3487 // If this is not the end of the statement, report an error.
3488 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003489 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003490
3491 setFeatureBits(Mips::FeatureMSA, "msa");
3492 getTargetStreamer().emitDirectiveSetMsa();
3493 return false;
3494}
3495
3496bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003497 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003498 Parser.Lex();
3499
3500 // If this is not the end of the statement, report an error.
3501 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003502 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003503
3504 clearFeatureBits(Mips::FeatureMSA, "msa");
3505 getTargetStreamer().emitDirectiveSetNoMsa();
3506 return false;
3507}
3508
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003509bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003510 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003511 Parser.Lex(); // Eat "nodsp".
3512
3513 // If this is not the end of the statement, report an error.
3514 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3515 reportParseError("unexpected token, expected end of statement");
3516 return false;
3517 }
3518
3519 clearFeatureBits(Mips::FeatureDSP, "dsp");
3520 getTargetStreamer().emitDirectiveSetNoDsp();
3521 return false;
3522}
3523
Toma Tabacucc2502d2014-11-04 17:18:07 +00003524bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003525 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003526 Parser.Lex(); // Eat "mips16".
3527
Jack Carter39536722014-01-22 23:08:42 +00003528 // If this is not the end of the statement, report an error.
3529 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003530 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00003531 return false;
3532 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00003533
3534 setFeatureBits(Mips::FeatureMips16, "mips16");
3535 getTargetStreamer().emitDirectiveSetMips16();
3536 Parser.Lex(); // Consume the EndOfStatement.
3537 return false;
3538}
3539
3540bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003541 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003542 Parser.Lex(); // Eat "nomips16".
3543
3544 // If this is not the end of the statement, report an error.
3545 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3546 reportParseError("unexpected token, expected end of statement");
3547 return false;
3548 }
3549
3550 clearFeatureBits(Mips::FeatureMips16, "mips16");
3551 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00003552 Parser.Lex(); // Consume the EndOfStatement.
3553 return false;
3554}
3555
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003556bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003557 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003558 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003559 // Line can be: .set fp=32
3560 // .set fp=xx
3561 // .set fp=64
3562 Parser.Lex(); // Eat fp token
3563 AsmToken Tok = Parser.getTok();
3564 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003565 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003566 return false;
3567 }
3568 Parser.Lex(); // Eat '=' token.
3569 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003570
3571 if (!parseFpABIValue(FpAbiVal, ".set"))
3572 return false;
3573
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003574 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003575 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003576 return false;
3577 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003578 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003579 Parser.Lex(); // Consume the EndOfStatement.
3580 return false;
3581}
3582
Toma Tabacu9db22db2014-09-09 10:15:38 +00003583bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003584 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003585 SMLoc Loc = getLexer().getLoc();
3586
3587 Parser.Lex();
3588 if (getLexer().isNot(AsmToken::EndOfStatement))
3589 return reportParseError("unexpected token, expected end of statement");
3590
3591 // Always keep an element on the options "stack" to prevent the user
3592 // from changing the initial options. This is how we remember them.
3593 if (AssemblerOptions.size() == 2)
3594 return reportParseError(Loc, ".set pop with no .set push");
3595
3596 AssemblerOptions.pop_back();
3597 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
3598
3599 getTargetStreamer().emitDirectiveSetPop();
3600 return false;
3601}
3602
3603bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003604 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003605 Parser.Lex();
3606 if (getLexer().isNot(AsmToken::EndOfStatement))
3607 return reportParseError("unexpected token, expected end of statement");
3608
3609 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00003610 AssemblerOptions.push_back(
3611 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00003612
3613 getTargetStreamer().emitDirectiveSetPush();
3614 return false;
3615}
3616
Jack Carterd76b2372013-03-21 21:44:16 +00003617bool MipsAsmParser::parseSetAssignment() {
3618 StringRef Name;
3619 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00003620 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00003621
3622 if (Parser.parseIdentifier(Name))
3623 reportParseError("expected identifier after .set");
3624
3625 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003626 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00003627 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00003628
Jack Carter3b2c96e2014-01-22 23:31:38 +00003629 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00003630 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00003631
Jim Grosbach6f482002015-05-18 18:43:14 +00003632 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00003633 Sym->setVariableValue(Value);
3634
3635 return false;
3636}
Jack Carterd0bd6422013-04-18 00:41:53 +00003637
Toma Tabacu26647792014-09-09 12:52:14 +00003638bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003639 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00003640 Parser.Lex();
3641 if (getLexer().isNot(AsmToken::EndOfStatement))
3642 return reportParseError("unexpected token, expected end of statement");
3643
3644 // Reset assembler options to their initial values.
3645 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
3646 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
3647
3648 getTargetStreamer().emitDirectiveSetMips0();
3649 return false;
3650}
3651
Toma Tabacu85618b32014-08-19 14:22:52 +00003652bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003653 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00003654 Parser.Lex();
3655 if (getLexer().isNot(AsmToken::Equal))
3656 return reportParseError("unexpected token, expected equals sign");
3657
3658 Parser.Lex();
3659 StringRef Arch;
3660 if (Parser.parseIdentifier(Arch))
3661 return reportParseError("expected arch identifier");
3662
3663 StringRef ArchFeatureName =
3664 StringSwitch<StringRef>(Arch)
3665 .Case("mips1", "mips1")
3666 .Case("mips2", "mips2")
3667 .Case("mips3", "mips3")
3668 .Case("mips4", "mips4")
3669 .Case("mips5", "mips5")
3670 .Case("mips32", "mips32")
3671 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003672 .Case("mips32r3", "mips32r3")
3673 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003674 .Case("mips32r6", "mips32r6")
3675 .Case("mips64", "mips64")
3676 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003677 .Case("mips64r3", "mips64r3")
3678 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003679 .Case("mips64r6", "mips64r6")
3680 .Case("cnmips", "cnmips")
3681 .Case("r4000", "mips3") // This is an implementation of Mips3.
3682 .Default("");
3683
3684 if (ArchFeatureName.empty())
3685 return reportParseError("unsupported architecture");
3686
3687 selectArch(ArchFeatureName);
3688 getTargetStreamer().emitDirectiveSetArch(Arch);
3689 return false;
3690}
3691
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003692bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003693 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003694 Parser.Lex();
3695 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003696 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003697
Matheus Almeida2852af82014-04-22 10:15:54 +00003698 switch (Feature) {
3699 default:
3700 llvm_unreachable("Unimplemented feature");
3701 case Mips::FeatureDSP:
3702 setFeatureBits(Mips::FeatureDSP, "dsp");
3703 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003704 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003705 case Mips::FeatureMicroMips:
3706 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003707 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003708 case Mips::FeatureMips1:
3709 selectArch("mips1");
3710 getTargetStreamer().emitDirectiveSetMips1();
3711 break;
3712 case Mips::FeatureMips2:
3713 selectArch("mips2");
3714 getTargetStreamer().emitDirectiveSetMips2();
3715 break;
3716 case Mips::FeatureMips3:
3717 selectArch("mips3");
3718 getTargetStreamer().emitDirectiveSetMips3();
3719 break;
3720 case Mips::FeatureMips4:
3721 selectArch("mips4");
3722 getTargetStreamer().emitDirectiveSetMips4();
3723 break;
3724 case Mips::FeatureMips5:
3725 selectArch("mips5");
3726 getTargetStreamer().emitDirectiveSetMips5();
3727 break;
3728 case Mips::FeatureMips32:
3729 selectArch("mips32");
3730 getTargetStreamer().emitDirectiveSetMips32();
3731 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003732 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003733 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003734 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003735 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003736 case Mips::FeatureMips32r3:
3737 selectArch("mips32r3");
3738 getTargetStreamer().emitDirectiveSetMips32R3();
3739 break;
3740 case Mips::FeatureMips32r5:
3741 selectArch("mips32r5");
3742 getTargetStreamer().emitDirectiveSetMips32R5();
3743 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003744 case Mips::FeatureMips32r6:
3745 selectArch("mips32r6");
3746 getTargetStreamer().emitDirectiveSetMips32R6();
3747 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003748 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003749 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00003750 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003751 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003752 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003753 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003754 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003755 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003756 case Mips::FeatureMips64r3:
3757 selectArch("mips64r3");
3758 getTargetStreamer().emitDirectiveSetMips64R3();
3759 break;
3760 case Mips::FeatureMips64r5:
3761 selectArch("mips64r5");
3762 getTargetStreamer().emitDirectiveSetMips64R5();
3763 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003764 case Mips::FeatureMips64r6:
3765 selectArch("mips64r6");
3766 getTargetStreamer().emitDirectiveSetMips64R6();
3767 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003768 }
3769 return false;
3770}
3771
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003772bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003773 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003774 if (getLexer().isNot(AsmToken::Comma)) {
3775 SMLoc Loc = getLexer().getLoc();
3776 Parser.eatToEndOfStatement();
3777 return Error(Loc, ErrorStr);
3778 }
3779
Matheus Almeida2852af82014-04-22 10:15:54 +00003780 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003781 return true;
3782}
3783
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003784bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003785 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00003786 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003787
Toma Tabacudde4c462014-11-06 10:02:45 +00003788 if (inMips16Mode()) {
3789 reportParseError(".cpload is not supported in Mips16 mode");
3790 return false;
3791 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003792
David Blaikie960ea3f2014-06-08 16:18:35 +00003793 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00003794 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003795 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3796 reportParseError("expected register containing function address");
3797 return false;
3798 }
3799
David Blaikie960ea3f2014-06-08 16:18:35 +00003800 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
3801 if (!RegOpnd.isGPRAsmReg()) {
3802 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003803 return false;
3804 }
3805
Toma Tabacudde4c462014-11-06 10:02:45 +00003806 // If this is not the end of the statement, report an error.
3807 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3808 reportParseError("unexpected token, expected end of statement");
3809 return false;
3810 }
3811
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003812 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003813 return false;
3814}
3815
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003816bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003817 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003818 unsigned FuncReg;
3819 unsigned Save;
3820 bool SaveIsReg = true;
3821
Matheus Almeida7e815762014-06-18 13:08:59 +00003822 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003823 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003824 if (ResTy == MatchOperand_NoMatch) {
3825 reportParseError("expected register containing function address");
3826 Parser.eatToEndOfStatement();
3827 return false;
3828 }
3829
3830 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3831 if (!FuncRegOpnd.isGPRAsmReg()) {
3832 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3833 Parser.eatToEndOfStatement();
3834 return false;
3835 }
3836
3837 FuncReg = FuncRegOpnd.getGPR32Reg();
3838 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003839
Toma Tabacu65f10572014-09-16 15:00:52 +00003840 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003841 return true;
3842
Toma Tabacu13964452014-09-04 13:23:44 +00003843 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003844 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003845 const AsmToken &Tok = Parser.getTok();
3846 if (Tok.is(AsmToken::Integer)) {
3847 Save = Tok.getIntVal();
3848 SaveIsReg = false;
3849 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003850 } else {
3851 reportParseError("expected save register or stack offset");
3852 Parser.eatToEndOfStatement();
3853 return false;
3854 }
3855 } else {
3856 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3857 if (!SaveOpnd.isGPRAsmReg()) {
3858 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3859 Parser.eatToEndOfStatement();
3860 return false;
3861 }
3862 Save = SaveOpnd.getGPR32Reg();
3863 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003864
Toma Tabacu65f10572014-09-16 15:00:52 +00003865 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003866 return true;
3867
Toma Tabacu8874eac2015-02-18 13:46:53 +00003868 const MCExpr *Expr;
3869 if (Parser.parseExpression(Expr)) {
3870 reportParseError("expected expression");
3871 return false;
3872 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003873
Toma Tabacu8874eac2015-02-18 13:46:53 +00003874 if (Expr->getKind() != MCExpr::SymbolRef) {
3875 reportParseError("expected symbol");
3876 return false;
3877 }
3878 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
3879
3880 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
3881 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003882 return false;
3883}
3884
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003885bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003886 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003887 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3888 const AsmToken &Tok = Parser.getTok();
3889
3890 if (Tok.getString() == "2008") {
3891 Parser.Lex();
3892 getTargetStreamer().emitDirectiveNaN2008();
3893 return false;
3894 } else if (Tok.getString() == "legacy") {
3895 Parser.Lex();
3896 getTargetStreamer().emitDirectiveNaNLegacy();
3897 return false;
3898 }
3899 }
3900 // If we don't recognize the option passed to the .nan
3901 // directive (e.g. no option or unknown option), emit an error.
3902 reportParseError("invalid option in .nan directive");
3903 return false;
3904}
3905
Jack Carter0b744b32012-10-04 02:29:46 +00003906bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003907 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003908 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003909 const AsmToken &Tok = Parser.getTok();
3910
3911 if (Tok.getString() == "noat") {
3912 return parseSetNoAtDirective();
3913 } else if (Tok.getString() == "at") {
3914 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003915 } else if (Tok.getString() == "arch") {
3916 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003917 } else if (Tok.getString() == "fp") {
3918 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003919 } else if (Tok.getString() == "pop") {
3920 return parseSetPopDirective();
3921 } else if (Tok.getString() == "push") {
3922 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003923 } else if (Tok.getString() == "reorder") {
3924 return parseSetReorderDirective();
3925 } else if (Tok.getString() == "noreorder") {
3926 return parseSetNoReorderDirective();
3927 } else if (Tok.getString() == "macro") {
3928 return parseSetMacroDirective();
3929 } else if (Tok.getString() == "nomacro") {
3930 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003931 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00003932 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003933 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003934 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003935 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003936 getTargetStreamer().emitDirectiveSetNoMicroMips();
3937 Parser.eatToEndOfStatement();
3938 return false;
3939 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003940 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003941 } else if (Tok.getString() == "mips0") {
3942 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003943 } else if (Tok.getString() == "mips1") {
3944 return parseSetFeature(Mips::FeatureMips1);
3945 } else if (Tok.getString() == "mips2") {
3946 return parseSetFeature(Mips::FeatureMips2);
3947 } else if (Tok.getString() == "mips3") {
3948 return parseSetFeature(Mips::FeatureMips3);
3949 } else if (Tok.getString() == "mips4") {
3950 return parseSetFeature(Mips::FeatureMips4);
3951 } else if (Tok.getString() == "mips5") {
3952 return parseSetFeature(Mips::FeatureMips5);
3953 } else if (Tok.getString() == "mips32") {
3954 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003955 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003956 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003957 } else if (Tok.getString() == "mips32r3") {
3958 return parseSetFeature(Mips::FeatureMips32r3);
3959 } else if (Tok.getString() == "mips32r5") {
3960 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003961 } else if (Tok.getString() == "mips32r6") {
3962 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003963 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003964 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003965 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003966 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003967 } else if (Tok.getString() == "mips64r3") {
3968 return parseSetFeature(Mips::FeatureMips64r3);
3969 } else if (Tok.getString() == "mips64r5") {
3970 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003971 } else if (Tok.getString() == "mips64r6") {
3972 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003973 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003974 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003975 } else if (Tok.getString() == "nodsp") {
3976 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003977 } else if (Tok.getString() == "msa") {
3978 return parseSetMsaDirective();
3979 } else if (Tok.getString() == "nomsa") {
3980 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003981 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003982 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003983 parseSetAssignment();
3984 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003985 }
Jack Carter07c818d2013-01-25 01:31:34 +00003986
Jack Carter0b744b32012-10-04 02:29:46 +00003987 return true;
3988}
3989
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003990/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003991/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003992bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003993 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003994 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3995 for (;;) {
3996 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003997 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003998 return true;
3999
4000 getParser().getStreamer().EmitValue(Value, Size);
4001
4002 if (getLexer().is(AsmToken::EndOfStatement))
4003 break;
4004
Jack Carter07c818d2013-01-25 01:31:34 +00004005 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004006 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00004007 Parser.Lex();
4008 }
4009 }
4010
4011 Parser.Lex();
4012 return false;
4013}
4014
Vladimir Medic4c299852013-11-06 11:27:05 +00004015/// parseDirectiveGpWord
4016/// ::= .gpword local_sym
4017bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004018 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004019 const MCExpr *Value;
4020 // EmitGPRel32Value requires an expression, so we are using base class
4021 // method to evaluate the expression.
4022 if (getParser().parseExpression(Value))
4023 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00004024 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00004025
Vladimir Medice10c1122013-11-13 13:18:04 +00004026 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004027 return Error(getLexer().getLoc(),
4028 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00004029 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00004030 return false;
4031}
4032
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004033/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00004034/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004035bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004036 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004037 const MCExpr *Value;
4038 // EmitGPRel64Value requires an expression, so we are using base class
4039 // method to evaluate the expression.
4040 if (getParser().parseExpression(Value))
4041 return true;
4042 getParser().getStreamer().EmitGPRel64Value(Value);
4043
4044 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004045 return Error(getLexer().getLoc(),
4046 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00004047 Parser.Lex(); // Eat EndOfStatement token.
4048 return false;
4049}
4050
Jack Carter0cd3c192014-01-06 23:27:31 +00004051bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004052 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00004053 // Get the option token.
4054 AsmToken Tok = Parser.getTok();
4055 // At the moment only identifiers are supported.
4056 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004057 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00004058 Parser.eatToEndOfStatement();
4059 return false;
4060 }
4061
4062 StringRef Option = Tok.getIdentifier();
4063
4064 if (Option == "pic0") {
4065 getTargetStreamer().emitDirectiveOptionPic0();
4066 Parser.Lex();
4067 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4068 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004069 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004070 Parser.eatToEndOfStatement();
4071 }
4072 return false;
4073 }
4074
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004075 if (Option == "pic2") {
4076 getTargetStreamer().emitDirectiveOptionPic2();
4077 Parser.Lex();
4078 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4079 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004080 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004081 Parser.eatToEndOfStatement();
4082 }
4083 return false;
4084 }
4085
Jack Carter0cd3c192014-01-06 23:27:31 +00004086 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00004087 Warning(Parser.getTok().getLoc(),
4088 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00004089 Parser.eatToEndOfStatement();
4090 return false;
4091}
4092
Toma Tabacu9ca50962015-04-16 09:53:47 +00004093/// parseInsnDirective
4094/// ::= .insn
4095bool MipsAsmParser::parseInsnDirective() {
4096 // If this is not the end of the statement, report an error.
4097 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4098 reportParseError("unexpected token, expected end of statement");
4099 return false;
4100 }
4101
4102 // The actual label marking happens in
4103 // MipsELFStreamer::createPendingLabelRelocs().
4104 getTargetStreamer().emitDirectiveInsn();
4105
4106 getParser().Lex(); // Eat EndOfStatement token.
4107 return false;
4108}
4109
Daniel Sanders7e527422014-07-10 13:38:23 +00004110/// parseDirectiveModule
4111/// ::= .module oddspreg
4112/// ::= .module nooddspreg
4113/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004114bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004115 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004116 MCAsmLexer &Lexer = getLexer();
4117 SMLoc L = Lexer.getLoc();
4118
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004119 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004120 // TODO : get a better message.
4121 reportParseError(".module directive must appear before any code");
4122 return false;
4123 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004124
Toma Tabacuc405c822015-01-23 10:40:19 +00004125 StringRef Option;
4126 if (Parser.parseIdentifier(Option)) {
4127 reportParseError("expected .module option identifier");
4128 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004129 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004130
Toma Tabacuc405c822015-01-23 10:40:19 +00004131 if (Option == "oddspreg") {
4132 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
4133 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4134
4135 // If this is not the end of the statement, report an error.
4136 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4137 reportParseError("unexpected token, expected end of statement");
4138 return false;
4139 }
4140
4141 return false; // parseDirectiveModule has finished successfully.
4142 } else if (Option == "nooddspreg") {
4143 if (!isABI_O32()) {
4144 Error(L, "'.module nooddspreg' requires the O32 ABI");
4145 return false;
4146 }
4147
4148 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
4149 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4150
4151 // If this is not the end of the statement, report an error.
4152 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4153 reportParseError("unexpected token, expected end of statement");
4154 return false;
4155 }
4156
4157 return false; // parseDirectiveModule has finished successfully.
4158 } else if (Option == "fp") {
4159 return parseDirectiveModuleFP();
4160 } else {
4161 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
4162 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004163}
4164
4165/// parseDirectiveModuleFP
4166/// ::= =32
4167/// ::= =xx
4168/// ::= =64
4169bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004170 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004171 MCAsmLexer &Lexer = getLexer();
4172
4173 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004174 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004175 return false;
4176 }
4177 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004178
Daniel Sanders7e527422014-07-10 13:38:23 +00004179 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004180 if (!parseFpABIValue(FpABI, ".module"))
4181 return false;
4182
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004183 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004184 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004185 return false;
4186 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004187
Daniel Sanders7201a3e2014-07-08 10:35:52 +00004188 // Emit appropriate flags.
4189 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00004190 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004191 return false;
4192}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004193
Daniel Sanders7e527422014-07-10 13:38:23 +00004194bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004195 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004196 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004197 MCAsmLexer &Lexer = getLexer();
4198
4199 if (Lexer.is(AsmToken::Identifier)) {
4200 StringRef Value = Parser.getTok().getString();
4201 Parser.Lex();
4202
4203 if (Value != "xx") {
4204 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4205 return false;
4206 }
4207
4208 if (!isABI_O32()) {
4209 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
4210 return false;
4211 }
4212
Daniel Sanders7e527422014-07-10 13:38:23 +00004213 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004214 return true;
4215 }
4216
4217 if (Lexer.is(AsmToken::Integer)) {
4218 unsigned Value = Parser.getTok().getIntVal();
4219 Parser.Lex();
4220
4221 if (Value != 32 && Value != 64) {
4222 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4223 return false;
4224 }
4225
4226 if (Value == 32) {
4227 if (!isABI_O32()) {
4228 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
4229 return false;
4230 }
4231
Daniel Sanders7e527422014-07-10 13:38:23 +00004232 FpABI = MipsABIFlagsSection::FpABIKind::S32;
4233 } else
4234 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004235
Daniel Sanders7e527422014-07-10 13:38:23 +00004236 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004237 }
4238
4239 return false;
4240}
4241
Jack Carter0b744b32012-10-04 02:29:46 +00004242bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004243 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004244 StringRef IDVal = DirectiveID.getString();
4245
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004246 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004247 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00004248 if (IDVal == ".dword") {
4249 parseDataDirective(8, DirectiveID.getLoc());
4250 return false;
4251 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004252 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004253 StringRef SymbolName;
4254
4255 if (Parser.parseIdentifier(SymbolName)) {
4256 reportParseError("expected identifier after .ent");
4257 return false;
4258 }
4259
4260 // There's an undocumented extension that allows an integer to
4261 // follow the name of the procedure which AFAICS is ignored by GAS.
4262 // Example: .ent foo,2
4263 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4264 if (getLexer().isNot(AsmToken::Comma)) {
4265 // Even though we accept this undocumented extension for compatibility
4266 // reasons, the additional integer argument does not actually change
4267 // the behaviour of the '.ent' directive, so we would like to discourage
4268 // its use. We do this by not referring to the extended version in
4269 // error messages which are not directly related to its use.
4270 reportParseError("unexpected token, expected end of statement");
4271 return false;
4272 }
4273 Parser.Lex(); // Eat the comma.
4274 const MCExpr *DummyNumber;
4275 int64_t DummyNumberVal;
4276 // If the user was explicitly trying to use the extended version,
4277 // we still give helpful extension-related error messages.
4278 if (Parser.parseExpression(DummyNumber)) {
4279 reportParseError("expected number after comma");
4280 return false;
4281 }
4282 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
4283 reportParseError("expected an absolute expression after comma");
4284 return false;
4285 }
4286 }
4287
4288 // If this is not the end of the statement, report an error.
4289 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4290 reportParseError("unexpected token, expected end of statement");
4291 return false;
4292 }
4293
Jim Grosbach6f482002015-05-18 18:43:14 +00004294 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004295
4296 getTargetStreamer().emitDirectiveEnt(*Sym);
4297 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00004298 return false;
4299 }
4300
Jack Carter07c818d2013-01-25 01:31:34 +00004301 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004302 StringRef SymbolName;
4303
4304 if (Parser.parseIdentifier(SymbolName)) {
4305 reportParseError("expected identifier after .end");
4306 return false;
4307 }
4308
4309 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4310 reportParseError("unexpected token, expected end of statement");
4311 return false;
4312 }
4313
4314 if (CurrentFn == nullptr) {
4315 reportParseError(".end used without .ent");
4316 return false;
4317 }
4318
4319 if ((SymbolName != CurrentFn->getName())) {
4320 reportParseError(".end symbol does not match .ent symbol");
4321 return false;
4322 }
4323
4324 getTargetStreamer().emitDirectiveEnd(SymbolName);
4325 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00004326 return false;
4327 }
4328
Jack Carter07c818d2013-01-25 01:31:34 +00004329 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004330 // .frame $stack_reg, frame_size_in_bytes, $return_reg
4331 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004332 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004333 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4334 reportParseError("expected stack register");
4335 return false;
4336 }
4337
4338 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4339 if (!StackRegOpnd.isGPRAsmReg()) {
4340 reportParseError(StackRegOpnd.getStartLoc(),
4341 "expected general purpose register");
4342 return false;
4343 }
4344 unsigned StackReg = StackRegOpnd.getGPR32Reg();
4345
4346 if (Parser.getTok().is(AsmToken::Comma))
4347 Parser.Lex();
4348 else {
4349 reportParseError("unexpected token, expected comma");
4350 return false;
4351 }
4352
4353 // Parse the frame size.
4354 const MCExpr *FrameSize;
4355 int64_t FrameSizeVal;
4356
4357 if (Parser.parseExpression(FrameSize)) {
4358 reportParseError("expected frame size value");
4359 return false;
4360 }
4361
4362 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
4363 reportParseError("frame size not an absolute expression");
4364 return false;
4365 }
4366
4367 if (Parser.getTok().is(AsmToken::Comma))
4368 Parser.Lex();
4369 else {
4370 reportParseError("unexpected token, expected comma");
4371 return false;
4372 }
4373
4374 // Parse the return register.
4375 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00004376 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004377 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4378 reportParseError("expected return register");
4379 return false;
4380 }
4381
4382 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4383 if (!ReturnRegOpnd.isGPRAsmReg()) {
4384 reportParseError(ReturnRegOpnd.getStartLoc(),
4385 "expected general purpose register");
4386 return false;
4387 }
4388
4389 // If this is not the end of the statement, report an error.
4390 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4391 reportParseError("unexpected token, expected end of statement");
4392 return false;
4393 }
4394
4395 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
4396 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00004397 return false;
4398 }
4399
Jack Carter07c818d2013-01-25 01:31:34 +00004400 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00004401 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00004402 }
4403
Daniel Sandersd97a6342014-08-13 10:07:34 +00004404 if (IDVal == ".mask" || IDVal == ".fmask") {
4405 // .mask bitmask, frame_offset
4406 // bitmask: One bit for each register used.
4407 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
4408 // first register is expected to be saved.
4409 // Examples:
4410 // .mask 0x80000000, -4
4411 // .fmask 0x80000000, -4
4412 //
Jack Carterbe332172012-09-07 00:48:02 +00004413
Daniel Sandersd97a6342014-08-13 10:07:34 +00004414 // Parse the bitmask
4415 const MCExpr *BitMask;
4416 int64_t BitMaskVal;
4417
4418 if (Parser.parseExpression(BitMask)) {
4419 reportParseError("expected bitmask value");
4420 return false;
4421 }
4422
4423 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
4424 reportParseError("bitmask not an absolute expression");
4425 return false;
4426 }
4427
4428 if (Parser.getTok().is(AsmToken::Comma))
4429 Parser.Lex();
4430 else {
4431 reportParseError("unexpected token, expected comma");
4432 return false;
4433 }
4434
4435 // Parse the frame_offset
4436 const MCExpr *FrameOffset;
4437 int64_t FrameOffsetVal;
4438
4439 if (Parser.parseExpression(FrameOffset)) {
4440 reportParseError("expected frame offset value");
4441 return false;
4442 }
4443
4444 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
4445 reportParseError("frame offset not an absolute expression");
4446 return false;
4447 }
4448
4449 // If this is not the end of the statement, report an error.
4450 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4451 reportParseError("unexpected token, expected end of statement");
4452 return false;
4453 }
4454
4455 if (IDVal == ".mask")
4456 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
4457 else
4458 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00004459 return false;
4460 }
4461
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004462 if (IDVal == ".nan")
4463 return parseDirectiveNaN();
4464
Jack Carter07c818d2013-01-25 01:31:34 +00004465 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004466 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00004467 return false;
4468 }
4469
Rafael Espindolab59fb732014-03-28 18:50:26 +00004470 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004471 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004472 return false;
4473 }
4474
Jack Carter07c818d2013-01-25 01:31:34 +00004475 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004476 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00004477 return false;
4478 }
4479
Jack Carter0cd3c192014-01-06 23:27:31 +00004480 if (IDVal == ".option")
4481 return parseDirectiveOption();
4482
4483 if (IDVal == ".abicalls") {
4484 getTargetStreamer().emitDirectiveAbiCalls();
4485 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004486 Error(Parser.getTok().getLoc(),
4487 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004488 // Clear line
4489 Parser.eatToEndOfStatement();
4490 }
4491 return false;
4492 }
4493
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004494 if (IDVal == ".cpsetup")
4495 return parseDirectiveCPSetup();
4496
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004497 if (IDVal == ".module")
4498 return parseDirectiveModule();
4499
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004500 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
4501 return parseInternalDirectiveReallowModule();
4502
Toma Tabacu9ca50962015-04-16 09:53:47 +00004503 if (IDVal == ".insn")
4504 return parseInsnDirective();
4505
Rafael Espindola870c4e92012-01-11 03:56:41 +00004506 return true;
4507}
4508
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004509bool MipsAsmParser::parseInternalDirectiveReallowModule() {
4510 // If this is not the end of the statement, report an error.
4511 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4512 reportParseError("unexpected token, expected end of statement");
4513 return false;
4514 }
4515
4516 getTargetStreamer().reallowModuleDirective();
4517
4518 getParser().Lex(); // Eat EndOfStatement token.
4519 return false;
4520}
4521
Rafael Espindola870c4e92012-01-11 03:56:41 +00004522extern "C" void LLVMInitializeMipsAsmParser() {
4523 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
4524 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
4525 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
4526 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
4527}
Jack Carterb4dbc172012-09-05 23:34:03 +00004528
4529#define GET_REGISTER_MATCHER
4530#define GET_MATCHER_IMPLEMENTATION
4531#include "MipsGenAsmMatcher.inc"