blob: fcec18e1875b05337537ffbd4f2d4fd84fceb6a1 [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);
Toma Tabacu81496c12015-05-20 08:54:45 +0000451
452 void warnIfNoMacro(SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000453};
454}
455
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000456namespace {
457
458/// MipsOperand - Instances of this class represent a parsed Mips machine
459/// instruction.
460class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000461public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000462 /// Broad categories of register classes
463 /// The exact class is finalized by the render method.
464 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000465 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000466 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000467 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000468 RegKind_FCC = 4, /// FCC
469 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
470 RegKind_MSACtrl = 16, /// MSA control registers
471 RegKind_COP2 = 32, /// COP2
472 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
473 /// context).
474 RegKind_CCR = 128, /// CCR
475 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000476 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000477
478 /// Potentially any (e.g. $1)
479 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
480 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000481 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000482 };
483
484private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000485 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000486 k_Immediate, /// An immediate (possibly involving symbol references)
487 k_Memory, /// Base + Offset Memory Address
488 k_PhysRegister, /// A physical register from the Mips namespace
489 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000490 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000491 k_RegList, /// A physical register list
492 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000493 } Kind;
494
David Blaikie960ea3f2014-06-08 16:18:35 +0000495public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000496 MipsOperand(KindTy K, MipsAsmParser &Parser)
497 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
498
David Blaikie960ea3f2014-06-08 16:18:35 +0000499private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000500 /// For diagnostics, and checking the assembler temporary
501 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000502
Eric Christopher8996c5d2013-03-15 00:42:55 +0000503 struct Token {
504 const char *Data;
505 unsigned Length;
506 };
507
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000508 struct PhysRegOp {
509 unsigned Num; /// Register Number
510 };
511
512 struct RegIdxOp {
513 unsigned Index; /// Index into the register class
514 RegKind Kind; /// Bitfield of the kinds it could possibly be
515 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000516 };
517
518 struct ImmOp {
519 const MCExpr *Val;
520 };
521
522 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000523 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000524 const MCExpr *Off;
525 };
526
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000527 struct RegListOp {
528 SmallVector<unsigned, 10> *List;
529 };
530
Jack Carterb4dbc172012-09-05 23:34:03 +0000531 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000532 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000533 struct PhysRegOp PhysReg;
534 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000535 struct ImmOp Imm;
536 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000537 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000538 };
539
540 SMLoc StartLoc, EndLoc;
541
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000542 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000543 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
544 const MCRegisterInfo *RegInfo,
545 SMLoc S, SMLoc E,
546 MipsAsmParser &Parser) {
547 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000548 Op->RegIdx.Index = Index;
549 Op->RegIdx.RegInfo = RegInfo;
550 Op->RegIdx.Kind = RegKind;
551 Op->StartLoc = S;
552 Op->EndLoc = E;
553 return Op;
554 }
555
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000556public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000557 /// Coerce the register to GPR32 and return the real register for the current
558 /// target.
559 unsigned getGPR32Reg() const {
560 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000561 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000562 unsigned ClassID = Mips::GPR32RegClassID;
563 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000564 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000565
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000566 /// Coerce the register to GPR32 and return the real register for the current
567 /// target.
568 unsigned getGPRMM16Reg() const {
569 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
570 unsigned ClassID = Mips::GPR32RegClassID;
571 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
572 }
573
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000574 /// Coerce the register to GPR64 and return the real register for the current
575 /// target.
576 unsigned getGPR64Reg() const {
577 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
578 unsigned ClassID = Mips::GPR64RegClassID;
579 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000580 }
581
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000582private:
583 /// Coerce the register to AFGR64 and return the real register for the current
584 /// target.
585 unsigned getAFGR64Reg() const {
586 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
587 if (RegIdx.Index % 2 != 0)
588 AsmParser.Warning(StartLoc, "Float register should be even.");
589 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
590 .getRegister(RegIdx.Index / 2);
591 }
592
593 /// Coerce the register to FGR64 and return the real register for the current
594 /// target.
595 unsigned getFGR64Reg() const {
596 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
597 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
598 .getRegister(RegIdx.Index);
599 }
600
601 /// Coerce the register to FGR32 and return the real register for the current
602 /// target.
603 unsigned getFGR32Reg() const {
604 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
605 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
606 .getRegister(RegIdx.Index);
607 }
608
609 /// Coerce the register to FGRH32 and return the real register for the current
610 /// target.
611 unsigned getFGRH32Reg() const {
612 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
613 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
614 .getRegister(RegIdx.Index);
615 }
616
617 /// Coerce the register to FCC and return the real register for the current
618 /// target.
619 unsigned getFCCReg() const {
620 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
621 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
622 .getRegister(RegIdx.Index);
623 }
624
625 /// Coerce the register to MSA128 and return the real register for the current
626 /// target.
627 unsigned getMSA128Reg() const {
628 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
629 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
630 // identical
631 unsigned ClassID = Mips::MSA128BRegClassID;
632 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
633 }
634
635 /// Coerce the register to MSACtrl and return the real register for the
636 /// current target.
637 unsigned getMSACtrlReg() const {
638 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
639 unsigned ClassID = Mips::MSACtrlRegClassID;
640 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
641 }
642
643 /// Coerce the register to COP2 and return the real register for the
644 /// current target.
645 unsigned getCOP2Reg() const {
646 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
647 unsigned ClassID = Mips::COP2RegClassID;
648 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
649 }
650
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000651 /// Coerce the register to COP3 and return the real register for the
652 /// current target.
653 unsigned getCOP3Reg() const {
654 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
655 unsigned ClassID = Mips::COP3RegClassID;
656 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
657 }
658
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000659 /// Coerce the register to ACC64DSP and return the real register for the
660 /// current target.
661 unsigned getACC64DSPReg() const {
662 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
663 unsigned ClassID = Mips::ACC64DSPRegClassID;
664 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
665 }
666
667 /// Coerce the register to HI32DSP and return the real register for the
668 /// current target.
669 unsigned getHI32DSPReg() const {
670 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
671 unsigned ClassID = Mips::HI32DSPRegClassID;
672 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
673 }
674
675 /// Coerce the register to LO32DSP and return the real register for the
676 /// current target.
677 unsigned getLO32DSPReg() const {
678 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
679 unsigned ClassID = Mips::LO32DSPRegClassID;
680 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
681 }
682
683 /// Coerce the register to CCR and return the real register for the
684 /// current target.
685 unsigned getCCRReg() const {
686 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
687 unsigned ClassID = Mips::CCRRegClassID;
688 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
689 }
690
691 /// Coerce the register to HWRegs and return the real register for the
692 /// current target.
693 unsigned getHWRegsReg() const {
694 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
695 unsigned ClassID = Mips::HWRegsRegClassID;
696 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
697 }
698
699public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000700 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000701 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000702 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000703 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000704 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000705 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000706 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000707 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000708 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000709
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000710 void addRegOperands(MCInst &Inst, unsigned N) const {
711 llvm_unreachable("Use a custom parser instead");
712 }
713
Daniel Sanders21bce302014-04-01 12:35:23 +0000714 /// Render the operand to an MCInst as a GPR32
715 /// Asserts if the wrong number of operands are requested, or the operand
716 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000717 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
718 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000719 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000720 }
721
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000722 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
723 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000724 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000725 }
726
Jozef Kolek1904fa22014-11-24 14:25:53 +0000727 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
728 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000729 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000730 }
731
Zoran Jovanovic41688672015-02-10 16:36:20 +0000732 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
733 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000734 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000735 }
736
Daniel Sanders21bce302014-04-01 12:35:23 +0000737 /// Render the operand to an MCInst as a GPR64
738 /// Asserts if the wrong number of operands are requested, or the operand
739 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000740 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
741 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000742 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000743 }
744
745 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
746 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000747 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000748 }
749
750 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
751 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000752 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000753 }
754
755 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
756 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000757 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000758 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000759 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000760 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
761 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000762 }
763
764 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
765 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000766 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000767 }
768
769 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
770 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000771 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000772 }
773
774 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
775 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000776 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000777 }
778
779 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
780 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000781 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000782 }
783
784 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
785 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000786 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000787 }
788
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000789 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
790 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000791 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000792 }
793
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000794 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
795 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000796 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000797 }
798
799 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
800 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000801 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000802 }
803
804 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
805 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000806 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000807 }
808
809 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
810 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000811 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000812 }
813
814 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
815 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000816 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000817 }
818
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000819 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000820 assert(N == 1 && "Invalid number of operands!");
821 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000822 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000823 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000824
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000825 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000826 assert(N == 2 && "Invalid number of operands!");
827
Jim Grosbache9119e42015-05-13 18:37:00 +0000828 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000829
830 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000831 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000832 }
833
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000834 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
835 assert(N == 2 && "Invalid number of operands!");
836
Jim Grosbache9119e42015-05-13 18:37:00 +0000837 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000838
839 const MCExpr *Expr = getMemOff();
840 addExpr(Inst, Expr);
841 }
842
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000843 void addRegListOperands(MCInst &Inst, unsigned N) const {
844 assert(N == 1 && "Invalid number of operands!");
845
846 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000847 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000848 }
849
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000850 void addRegPairOperands(MCInst &Inst, unsigned N) const {
851 assert(N == 2 && "Invalid number of operands!");
852 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +0000853 Inst.addOperand(MCOperand::createReg(RegNo++));
854 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000855 }
856
Zoran Jovanovic41688672015-02-10 16:36:20 +0000857 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
858 assert(N == 2 && "Invalid number of operands!");
859 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000860 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000861 }
862
Craig Topper56c590a2014-04-29 07:58:02 +0000863 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000864 // As a special case until we sort out the definition of div/divu, pretend
865 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
866 if (isGPRAsmReg() && RegIdx.Index == 0)
867 return true;
868
869 return Kind == k_PhysRegister;
870 }
871 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000872 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000873 bool isConstantImm() const {
874 return isImm() && dyn_cast<MCConstantExpr>(getImm());
875 }
Craig Topper56c590a2014-04-29 07:58:02 +0000876 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000877 // Note: It's not possible to pretend that other operand kinds are tokens.
878 // The matcher emitter checks tokens first.
879 return Kind == k_Token;
880 }
Craig Topper56c590a2014-04-29 07:58:02 +0000881 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000882 bool isConstantMemOff() const {
883 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
884 }
885 template <unsigned Bits> bool isMemWithSimmOffset() const {
886 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
887 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000888 bool isMemWithGRPMM16Base() const {
889 return isMem() && getMemBase()->isMM16AsmReg();
890 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000891 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
892 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
893 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
894 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000895 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
896 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
897 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
898 && (getMemBase()->getGPR32Reg() == Mips::SP);
899 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000900 bool isRegList16() const {
901 if (!isRegList())
902 return false;
903
904 int Size = RegList.List->size();
905 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
906 RegList.List->back() != Mips::RA)
907 return false;
908
909 int PrevReg = *RegList.List->begin();
910 for (int i = 1; i < Size - 1; i++) {
911 int Reg = (*(RegList.List))[i];
912 if ( Reg != PrevReg + 1)
913 return false;
914 PrevReg = Reg;
915 }
916
917 return true;
918 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000919 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000920 bool isLSAImm() const {
921 if (!isConstantImm())
922 return false;
923 int64_t Val = getConstantImm();
924 return 1 <= Val && Val <= 4;
925 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000926 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +0000927 bool isMovePRegPair() const {
928 if (Kind != k_RegList || RegList.List->size() != 2)
929 return false;
930
931 unsigned R0 = RegList.List->front();
932 unsigned R1 = RegList.List->back();
933
934 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
935 (R0 == Mips::A1 && R1 == Mips::A3) ||
936 (R0 == Mips::A2 && R1 == Mips::A3) ||
937 (R0 == Mips::A0 && R1 == Mips::S5) ||
938 (R0 == Mips::A0 && R1 == Mips::S6) ||
939 (R0 == Mips::A0 && R1 == Mips::A1) ||
940 (R0 == Mips::A0 && R1 == Mips::A2) ||
941 (R0 == Mips::A0 && R1 == Mips::A3))
942 return true;
943
944 return false;
945 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000946
947 StringRef getToken() const {
948 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000949 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000950 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000951 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000952
Craig Topper56c590a2014-04-29 07:58:02 +0000953 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000954 // As a special case until we sort out the definition of div/divu, pretend
955 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
956 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
957 RegIdx.Kind & RegKind_GPR)
958 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000959
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000960 assert(Kind == k_PhysRegister && "Invalid access!");
961 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000962 }
963
Jack Carterb4dbc172012-09-05 23:34:03 +0000964 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000965 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000966 return Imm.Val;
967 }
968
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000969 int64_t getConstantImm() const {
970 const MCExpr *Val = getImm();
971 return static_cast<const MCConstantExpr *>(Val)->getValue();
972 }
973
974 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000975 assert((Kind == k_Memory) && "Invalid access!");
976 return Mem.Base;
977 }
978
979 const MCExpr *getMemOff() const {
980 assert((Kind == k_Memory) && "Invalid access!");
981 return Mem.Off;
982 }
983
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000984 int64_t getConstantMemOff() const {
985 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
986 }
987
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000988 const SmallVectorImpl<unsigned> &getRegList() const {
989 assert((Kind == k_RegList) && "Invalid access!");
990 return *(RegList.List);
991 }
992
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000993 unsigned getRegPair() const {
994 assert((Kind == k_RegPair) && "Invalid access!");
995 return RegIdx.Index;
996 }
997
David Blaikie960ea3f2014-06-08 16:18:35 +0000998 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
999 MipsAsmParser &Parser) {
1000 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001001 Op->Tok.Data = Str.data();
1002 Op->Tok.Length = Str.size();
1003 Op->StartLoc = S;
1004 Op->EndLoc = S;
1005 return Op;
1006 }
1007
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001008 /// Create a numeric register (e.g. $1). The exact register remains
1009 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001010 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001011 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001012 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001013 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001014 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001015 }
1016
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001017 /// Create a register that is definitely a GPR.
1018 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001019 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001020 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001021 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001022 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001023 }
1024
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001025 /// Create a register that is definitely a FGR.
1026 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001027 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001028 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001029 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001030 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1031 }
1032
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001033 /// Create a register that is definitely a HWReg.
1034 /// This is typically only used for named registers such as $hwr_cpunum.
1035 static std::unique_ptr<MipsOperand>
1036 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1037 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1038 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1039 }
1040
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001041 /// Create a register that is definitely an FCC.
1042 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001043 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001044 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001045 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001046 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1047 }
1048
1049 /// Create a register that is definitely an ACC.
1050 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001051 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001052 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001053 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001054 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1055 }
1056
1057 /// Create a register that is definitely an MSA128.
1058 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001059 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001060 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001061 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001062 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1063 }
1064
1065 /// Create a register that is definitely an MSACtrl.
1066 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001067 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001068 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001069 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001070 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1071 }
1072
David Blaikie960ea3f2014-06-08 16:18:35 +00001073 static std::unique_ptr<MipsOperand>
1074 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1075 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001076 Op->Imm.Val = Val;
1077 Op->StartLoc = S;
1078 Op->EndLoc = E;
1079 return Op;
1080 }
1081
David Blaikie960ea3f2014-06-08 16:18:35 +00001082 static std::unique_ptr<MipsOperand>
1083 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1084 SMLoc E, MipsAsmParser &Parser) {
1085 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1086 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001087 Op->Mem.Off = Off;
1088 Op->StartLoc = S;
1089 Op->EndLoc = E;
1090 return Op;
1091 }
1092
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001093 static std::unique_ptr<MipsOperand>
1094 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1095 MipsAsmParser &Parser) {
1096 assert (Regs.size() > 0 && "Empty list not allowed");
1097
1098 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001099 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001100 Op->StartLoc = StartLoc;
1101 Op->EndLoc = EndLoc;
1102 return Op;
1103 }
1104
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001105 static std::unique_ptr<MipsOperand>
1106 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1107 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1108 Op->RegIdx.Index = RegNo;
1109 Op->StartLoc = S;
1110 Op->EndLoc = E;
1111 return Op;
1112 }
1113
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001114 bool isGPRAsmReg() const {
1115 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001116 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001117 bool isMM16AsmReg() const {
1118 if (!(isRegIdx() && RegIdx.Kind))
1119 return false;
1120 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1121 || RegIdx.Index == 16 || RegIdx.Index == 17);
1122 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001123 bool isMM16AsmRegZero() const {
1124 if (!(isRegIdx() && RegIdx.Kind))
1125 return false;
1126 return (RegIdx.Index == 0 ||
1127 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1128 RegIdx.Index == 17);
1129 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001130 bool isMM16AsmRegMoveP() const {
1131 if (!(isRegIdx() && RegIdx.Kind))
1132 return false;
1133 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1134 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1135 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001136 bool isFGRAsmReg() const {
1137 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1138 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001139 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001140 bool isHWRegsAsmReg() const {
1141 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001142 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001143 bool isCCRAsmReg() const {
1144 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001145 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001146 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001147 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1148 return false;
1149 if (!AsmParser.hasEightFccRegisters())
1150 return RegIdx.Index == 0;
1151 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001152 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001153 bool isACCAsmReg() const {
1154 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001155 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001156 bool isCOP2AsmReg() const {
1157 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001158 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001159 bool isCOP3AsmReg() const {
1160 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1161 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001162 bool isMSA128AsmReg() const {
1163 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001164 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001165 bool isMSACtrlAsmReg() const {
1166 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001167 }
1168
Jack Carterb4dbc172012-09-05 23:34:03 +00001169 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001170 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001171 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001172 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001173
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001174 virtual ~MipsOperand() {
1175 switch (Kind) {
1176 case k_Immediate:
1177 break;
1178 case k_Memory:
1179 delete Mem.Base;
1180 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001181 case k_RegList:
1182 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001183 case k_PhysRegister:
1184 case k_RegisterIndex:
1185 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001186 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001187 break;
1188 }
1189 }
1190
Craig Topper56c590a2014-04-29 07:58:02 +00001191 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001192 switch (Kind) {
1193 case k_Immediate:
1194 OS << "Imm<";
1195 Imm.Val->print(OS);
1196 OS << ">";
1197 break;
1198 case k_Memory:
1199 OS << "Mem<";
1200 Mem.Base->print(OS);
1201 OS << ", ";
1202 Mem.Off->print(OS);
1203 OS << ">";
1204 break;
1205 case k_PhysRegister:
1206 OS << "PhysReg<" << PhysReg.Num << ">";
1207 break;
1208 case k_RegisterIndex:
1209 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1210 break;
1211 case k_Token:
1212 OS << Tok.Data;
1213 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001214 case k_RegList:
1215 OS << "RegList< ";
1216 for (auto Reg : (*RegList.List))
1217 OS << Reg << " ";
1218 OS << ">";
1219 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001220 case k_RegPair:
1221 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1222 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001223 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001224 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001225}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001226} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001227
Jack Carter9e65aa32013-03-22 00:05:30 +00001228namespace llvm {
1229extern const MCInstrDesc MipsInsts[];
1230}
1231static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1232 return MipsInsts[Opcode];
1233}
1234
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001235static bool hasShortDelaySlot(unsigned Opcode) {
1236 switch (Opcode) {
1237 case Mips::JALS_MM:
1238 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001239 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001240 case Mips::BGEZALS_MM:
1241 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001242 return true;
1243 default:
1244 return false;
1245 }
1246}
1247
Jack Carter9e65aa32013-03-22 00:05:30 +00001248bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001249 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001250 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001251
Jack Carter9e65aa32013-03-22 00:05:30 +00001252 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001253
1254 if (MCID.isBranch() || MCID.isCall()) {
1255 const unsigned Opcode = Inst.getOpcode();
1256 MCOperand Offset;
1257
1258 switch (Opcode) {
1259 default:
1260 break;
Kai Nackee0245392015-01-27 19:11:28 +00001261 case Mips::BBIT0:
1262 case Mips::BBIT032:
1263 case Mips::BBIT1:
1264 case Mips::BBIT132:
1265 assert(hasCnMips() && "instruction only valid for octeon cpus");
1266 // Fall through
1267
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001268 case Mips::BEQ:
1269 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001270 case Mips::BEQ_MM:
1271 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001272 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001273 Offset = Inst.getOperand(2);
1274 if (!Offset.isImm())
1275 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001276 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001277 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001278 if (OffsetToAlignment(Offset.getImm(),
1279 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001280 return Error(IDLoc, "branch to misaligned address");
1281 break;
1282 case Mips::BGEZ:
1283 case Mips::BGTZ:
1284 case Mips::BLEZ:
1285 case Mips::BLTZ:
1286 case Mips::BGEZAL:
1287 case Mips::BLTZAL:
1288 case Mips::BC1F:
1289 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001290 case Mips::BGEZ_MM:
1291 case Mips::BGTZ_MM:
1292 case Mips::BLEZ_MM:
1293 case Mips::BLTZ_MM:
1294 case Mips::BGEZAL_MM:
1295 case Mips::BLTZAL_MM:
1296 case Mips::BC1F_MM:
1297 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001298 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001299 Offset = Inst.getOperand(1);
1300 if (!Offset.isImm())
1301 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001302 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001303 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001304 if (OffsetToAlignment(Offset.getImm(),
1305 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001306 return Error(IDLoc, "branch to misaligned address");
1307 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001308 case Mips::BEQZ16_MM:
1309 case Mips::BNEZ16_MM:
1310 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1311 Offset = Inst.getOperand(1);
1312 if (!Offset.isImm())
1313 break; // We'll deal with this situation later on when applying fixups.
1314 if (!isIntN(8, Offset.getImm()))
1315 return Error(IDLoc, "branch target out of range");
1316 if (OffsetToAlignment(Offset.getImm(), 2LL))
1317 return Error(IDLoc, "branch to misaligned address");
1318 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001319 }
1320 }
1321
Daniel Sandersa84989a2014-06-16 13:25:35 +00001322 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1323 // We still accept it but it is a normal nop.
1324 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1325 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1326 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1327 "nop instruction");
1328 }
1329
Kai Nackee0245392015-01-27 19:11:28 +00001330 if (hasCnMips()) {
1331 const unsigned Opcode = Inst.getOpcode();
1332 MCOperand Opnd;
1333 int Imm;
1334
1335 switch (Opcode) {
1336 default:
1337 break;
1338
1339 case Mips::BBIT0:
1340 case Mips::BBIT032:
1341 case Mips::BBIT1:
1342 case Mips::BBIT132:
1343 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1344 // The offset is handled above
1345 Opnd = Inst.getOperand(1);
1346 if (!Opnd.isImm())
1347 return Error(IDLoc, "expected immediate operand kind");
1348 Imm = Opnd.getImm();
1349 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1350 Opcode == Mips::BBIT1 ? 63 : 31))
1351 return Error(IDLoc, "immediate operand value out of range");
1352 if (Imm > 31) {
1353 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1354 : Mips::BBIT132);
1355 Inst.getOperand(1).setImm(Imm - 32);
1356 }
1357 break;
1358
1359 case Mips::CINS:
1360 case Mips::CINS32:
1361 case Mips::EXTS:
1362 case Mips::EXTS32:
1363 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1364 // Check length
1365 Opnd = Inst.getOperand(3);
1366 if (!Opnd.isImm())
1367 return Error(IDLoc, "expected immediate operand kind");
1368 Imm = Opnd.getImm();
1369 if (Imm < 0 || Imm > 31)
1370 return Error(IDLoc, "immediate operand value out of range");
1371 // Check position
1372 Opnd = Inst.getOperand(2);
1373 if (!Opnd.isImm())
1374 return Error(IDLoc, "expected immediate operand kind");
1375 Imm = Opnd.getImm();
1376 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1377 Opcode == Mips::EXTS ? 63 : 31))
1378 return Error(IDLoc, "immediate operand value out of range");
1379 if (Imm > 31) {
1380 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1381 Inst.getOperand(2).setImm(Imm - 32);
1382 }
1383 break;
1384
1385 case Mips::SEQi:
1386 case Mips::SNEi:
1387 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1388 Opnd = Inst.getOperand(2);
1389 if (!Opnd.isImm())
1390 return Error(IDLoc, "expected immediate operand kind");
1391 Imm = Opnd.getImm();
1392 if (!isInt<10>(Imm))
1393 return Error(IDLoc, "immediate operand value out of range");
1394 break;
1395 }
1396 }
1397
Jack Carter9e65aa32013-03-22 00:05:30 +00001398 if (MCID.mayLoad() || MCID.mayStore()) {
1399 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001400 // reference or immediate we may have to expand instructions.
1401 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001402 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001403 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1404 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001405 MCOperand &Op = Inst.getOperand(i);
1406 if (Op.isImm()) {
1407 int MemOffset = Op.getImm();
1408 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001409 // Offset can't exceed 16bit value.
1410 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001411 return false;
1412 }
1413 } else if (Op.isExpr()) {
1414 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001415 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001416 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001417 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001418 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001419 // Expand symbol.
1420 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001421 return false;
1422 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001423 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001424 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001425 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001426 }
1427 }
1428 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001429 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001430 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001431
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001432 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001433 if (MCID.mayLoad()) {
1434 // Try to create 16-bit GP relative load instruction.
1435 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1436 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1437 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1438 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1439 MCOperand &Op = Inst.getOperand(i);
1440 if (Op.isImm()) {
1441 int MemOffset = Op.getImm();
1442 MCOperand &DstReg = Inst.getOperand(0);
1443 MCOperand &BaseReg = Inst.getOperand(1);
1444 if (isIntN(9, MemOffset) && (MemOffset % 4 == 0) &&
1445 getContext().getRegisterInfo()->getRegClass(
1446 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
1447 BaseReg.getReg() == Mips::GP) {
1448 MCInst TmpInst;
1449 TmpInst.setLoc(IDLoc);
1450 TmpInst.setOpcode(Mips::LWGP_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00001451 TmpInst.addOperand(MCOperand::createReg(DstReg.getReg()));
1452 TmpInst.addOperand(MCOperand::createReg(Mips::GP));
1453 TmpInst.addOperand(MCOperand::createImm(MemOffset));
Jozef Koleke10a02e2015-01-28 17:27:26 +00001454 Instructions.push_back(TmpInst);
1455 return false;
1456 }
1457 }
1458 }
1459 } // for
1460 } // if load
1461
1462 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1463
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001464 MCOperand Opnd;
1465 int Imm;
1466
1467 switch (Inst.getOpcode()) {
1468 default:
1469 break;
1470 case Mips::ADDIUS5_MM:
1471 Opnd = Inst.getOperand(2);
1472 if (!Opnd.isImm())
1473 return Error(IDLoc, "expected immediate operand kind");
1474 Imm = Opnd.getImm();
1475 if (Imm < -8 || Imm > 7)
1476 return Error(IDLoc, "immediate operand value out of range");
1477 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001478 case Mips::ADDIUSP_MM:
1479 Opnd = Inst.getOperand(0);
1480 if (!Opnd.isImm())
1481 return Error(IDLoc, "expected immediate operand kind");
1482 Imm = Opnd.getImm();
1483 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1484 Imm % 4 != 0)
1485 return Error(IDLoc, "immediate operand value out of range");
1486 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001487 case Mips::SLL16_MM:
1488 case Mips::SRL16_MM:
1489 Opnd = Inst.getOperand(2);
1490 if (!Opnd.isImm())
1491 return Error(IDLoc, "expected immediate operand kind");
1492 Imm = Opnd.getImm();
1493 if (Imm < 1 || Imm > 8)
1494 return Error(IDLoc, "immediate operand value out of range");
1495 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001496 case Mips::LI16_MM:
1497 Opnd = Inst.getOperand(1);
1498 if (!Opnd.isImm())
1499 return Error(IDLoc, "expected immediate operand kind");
1500 Imm = Opnd.getImm();
1501 if (Imm < -1 || Imm > 126)
1502 return Error(IDLoc, "immediate operand value out of range");
1503 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001504 case Mips::ADDIUR2_MM:
1505 Opnd = Inst.getOperand(2);
1506 if (!Opnd.isImm())
1507 return Error(IDLoc, "expected immediate operand kind");
1508 Imm = Opnd.getImm();
1509 if (!(Imm == 1 || Imm == -1 ||
1510 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1511 return Error(IDLoc, "immediate operand value out of range");
1512 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001513 case Mips::ADDIUR1SP_MM:
1514 Opnd = Inst.getOperand(1);
1515 if (!Opnd.isImm())
1516 return Error(IDLoc, "expected immediate operand kind");
1517 Imm = Opnd.getImm();
1518 if (OffsetToAlignment(Imm, 4LL))
1519 return Error(IDLoc, "misaligned immediate operand value");
1520 if (Imm < 0 || Imm > 255)
1521 return Error(IDLoc, "immediate operand value out of range");
1522 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001523 case Mips::ANDI16_MM:
1524 Opnd = Inst.getOperand(2);
1525 if (!Opnd.isImm())
1526 return Error(IDLoc, "expected immediate operand kind");
1527 Imm = Opnd.getImm();
1528 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1529 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1530 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1531 return Error(IDLoc, "immediate operand value out of range");
1532 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001533 case Mips::LBU16_MM:
1534 Opnd = Inst.getOperand(2);
1535 if (!Opnd.isImm())
1536 return Error(IDLoc, "expected immediate operand kind");
1537 Imm = Opnd.getImm();
1538 if (Imm < -1 || Imm > 14)
1539 return Error(IDLoc, "immediate operand value out of range");
1540 break;
1541 case Mips::SB16_MM:
1542 Opnd = Inst.getOperand(2);
1543 if (!Opnd.isImm())
1544 return Error(IDLoc, "expected immediate operand kind");
1545 Imm = Opnd.getImm();
1546 if (Imm < 0 || Imm > 15)
1547 return Error(IDLoc, "immediate operand value out of range");
1548 break;
1549 case Mips::LHU16_MM:
1550 case Mips::SH16_MM:
1551 Opnd = Inst.getOperand(2);
1552 if (!Opnd.isImm())
1553 return Error(IDLoc, "expected immediate operand kind");
1554 Imm = Opnd.getImm();
1555 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1556 return Error(IDLoc, "immediate operand value out of range");
1557 break;
1558 case Mips::LW16_MM:
1559 case Mips::SW16_MM:
1560 Opnd = Inst.getOperand(2);
1561 if (!Opnd.isImm())
1562 return Error(IDLoc, "expected immediate operand kind");
1563 Imm = Opnd.getImm();
1564 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1565 return Error(IDLoc, "immediate operand value out of range");
1566 break;
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001567 case Mips::CACHE:
1568 case Mips::PREF:
1569 Opnd = Inst.getOperand(2);
1570 if (!Opnd.isImm())
1571 return Error(IDLoc, "expected immediate operand kind");
1572 Imm = Opnd.getImm();
1573 if (!isUInt<5>(Imm))
1574 return Error(IDLoc, "immediate operand value out of range");
1575 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001576 case Mips::ADDIUPC_MM:
1577 MCOperand Opnd = Inst.getOperand(1);
1578 if (!Opnd.isImm())
1579 return Error(IDLoc, "expected immediate operand kind");
1580 int Imm = Opnd.getImm();
1581 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1582 return Error(IDLoc, "immediate operand value out of range");
1583 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001584 }
1585 }
1586
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001587 if (needsExpansion(Inst)) {
1588 if (expandInstruction(Inst, IDLoc, Instructions))
1589 return true;
1590 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001591 Instructions.push_back(Inst);
1592
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001593 // If this instruction has a delay slot and .set reorder is active,
1594 // emit a NOP after it.
1595 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1596 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1597
Jack Carter9e65aa32013-03-22 00:05:30 +00001598 return false;
1599}
1600
Jack Carter30a59822012-10-04 04:03:53 +00001601bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1602
Jack Carterd0bd6422013-04-18 00:41:53 +00001603 switch (Inst.getOpcode()) {
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001604 case Mips::LoadImm32:
1605 case Mips::LoadImm64:
1606 case Mips::LoadAddrImm32:
1607 case Mips::LoadAddrReg32:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001608 case Mips::B_MM_Pseudo:
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001609 case Mips::LWM_MM:
1610 case Mips::SWM_MM:
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001611 case Mips::JalOneReg:
1612 case Mips::JalTwoReg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001613 return true;
1614 default:
1615 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001616 }
1617}
Jack Carter92995f12012-10-06 00:53:28 +00001618
Matheus Almeida3813d572014-06-19 14:39:14 +00001619bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001620 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001621 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001622 default: llvm_unreachable("unimplemented expansion");
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001623 case Mips::LoadImm32:
Toma Tabacu00e98672015-05-01 12:19:27 +00001624 return expandLoadImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001625 case Mips::LoadImm64:
Toma Tabacu00e98672015-05-01 12:19:27 +00001626 return expandLoadImm(Inst, false, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001627 case Mips::LoadAddrImm32:
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001628 return expandLoadAddressImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001629 case Mips::LoadAddrReg32:
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001630 return expandLoadAddressReg(Inst, true, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001631 case Mips::B_MM_Pseudo:
1632 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001633 case Mips::SWM_MM:
1634 case Mips::LWM_MM:
1635 return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001636 case Mips::JalOneReg:
1637 case Mips::JalTwoReg:
1638 return expandJalWithRegs(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001639 }
Jack Carter30a59822012-10-04 04:03:53 +00001640}
Jack Carter92995f12012-10-06 00:53:28 +00001641
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001642namespace {
Toma Tabacua2861db2015-05-01 10:26:47 +00001643template <unsigned ShiftAmount>
Toma Tabacu61145652015-04-28 13:16:06 +00001644void createLShiftOri(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001645 SmallVectorImpl<MCInst> &Instructions) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001646 MCInst tmpInst;
Toma Tabacua2861db2015-05-01 10:26:47 +00001647 if (ShiftAmount >= 32) {
1648 tmpInst.setOpcode(Mips::DSLL32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001649 tmpInst.addOperand(MCOperand::createReg(RegNo));
1650 tmpInst.addOperand(MCOperand::createReg(RegNo));
1651 tmpInst.addOperand(MCOperand::createImm(ShiftAmount - 32));
Toma Tabacua2861db2015-05-01 10:26:47 +00001652 tmpInst.setLoc(IDLoc);
1653 Instructions.push_back(tmpInst);
1654 tmpInst.clear();
1655 } else if (ShiftAmount > 0) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001656 tmpInst.setOpcode(Mips::DSLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00001657 tmpInst.addOperand(MCOperand::createReg(RegNo));
1658 tmpInst.addOperand(MCOperand::createReg(RegNo));
1659 tmpInst.addOperand(MCOperand::createImm(ShiftAmount));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001660 tmpInst.setLoc(IDLoc);
1661 Instructions.push_back(tmpInst);
1662 tmpInst.clear();
1663 }
Toma Tabacu7dea2e32015-04-28 14:06:35 +00001664 // There's no need for an ORi if the immediate is 0.
1665 if (Operand.isImm() && Operand.getImm() == 0)
1666 return;
1667
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001668 tmpInst.setOpcode(Mips::ORi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001669 tmpInst.addOperand(MCOperand::createReg(RegNo));
1670 tmpInst.addOperand(MCOperand::createReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001671 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001672 tmpInst.setLoc(IDLoc);
1673 Instructions.push_back(tmpInst);
1674}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001675
Toma Tabacua2861db2015-05-01 10:26:47 +00001676template <unsigned ShiftAmount>
Toma Tabacu61145652015-04-28 13:16:06 +00001677void createLShiftOri(int64_t Value, unsigned RegNo, SMLoc IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001678 SmallVectorImpl<MCInst> &Instructions) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001679 createLShiftOri<ShiftAmount>(MCOperand::createImm(Value), RegNo, IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001680 Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001681}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001682}
1683
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001684bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
1685 SmallVectorImpl<MCInst> &Instructions) {
1686 // Create a JALR instruction which is going to replace the pseudo-JAL.
1687 MCInst JalrInst;
1688 JalrInst.setLoc(IDLoc);
1689 const MCOperand FirstRegOp = Inst.getOperand(0);
1690 const unsigned Opcode = Inst.getOpcode();
1691
1692 if (Opcode == Mips::JalOneReg) {
1693 // jal $rs => jalr $rs
1694 if (inMicroMipsMode()) {
1695 JalrInst.setOpcode(Mips::JALR16_MM);
1696 JalrInst.addOperand(FirstRegOp);
1697 } else {
1698 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00001699 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001700 JalrInst.addOperand(FirstRegOp);
1701 }
1702 } else if (Opcode == Mips::JalTwoReg) {
1703 // jal $rd, $rs => jalr $rd, $rs
1704 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
1705 JalrInst.addOperand(FirstRegOp);
1706 const MCOperand SecondRegOp = Inst.getOperand(1);
1707 JalrInst.addOperand(SecondRegOp);
1708 }
1709 Instructions.push_back(JalrInst);
1710
1711 // If .set reorder is active, emit a NOP after it.
1712 if (AssemblerOptions.back()->isReorder()) {
1713 // This is a 32-bit NOP because these 2 pseudo-instructions
1714 // do not have a short delay slot.
1715 MCInst NopInst;
1716 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00001717 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
1718 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
1719 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001720 Instructions.push_back(NopInst);
1721 }
1722
1723 return false;
1724}
1725
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001726bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
1727 unsigned SrcReg, bool Is32BitImm, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001728 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00001729 if (!Is32BitImm && !isGP64bit()) {
1730 Error(IDLoc, "instruction requires a 64-bit architecture");
1731 return true;
1732 }
1733
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001734 bool UseSrcReg = false;
1735 if (SrcReg != Mips::NoRegister)
1736 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00001737
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001738 MCInst tmpInst;
1739
Jack Carter92995f12012-10-06 00:53:28 +00001740 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001741 // FIXME: gas has a special case for values that are 000...1111, which
1742 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001743 if (0 <= ImmValue && ImmValue <= 65535) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001744 // For unsigned and positive signed 16-bit values (0 <= j <= 65535):
Jack Carter30a59822012-10-04 04:03:53 +00001745 // li d,j => ori d,$zero,j
Toma Tabacudf7fd462015-05-13 16:02:41 +00001746 if (!UseSrcReg)
1747 SrcReg = isGP64bit() ? Mips::ZERO_64 : Mips::ZERO;
Jack Carter873c7242013-01-12 01:03:14 +00001748 tmpInst.setOpcode(Mips::ORi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001749 tmpInst.addOperand(MCOperand::createReg(DstReg));
1750 tmpInst.addOperand(MCOperand::createReg(SrcReg));
1751 tmpInst.addOperand(MCOperand::createImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001752 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001753 } else if (ImmValue < 0 && ImmValue >= -32768) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001754 // For negative signed 16-bit values (-32768 <= j < 0):
Jack Carter30a59822012-10-04 04:03:53 +00001755 // li d,j => addiu d,$zero,j
Toma Tabacudf7fd462015-05-13 16:02:41 +00001756 if (!UseSrcReg)
1757 SrcReg = Mips::ZERO;
Jack Carter873c7242013-01-12 01:03:14 +00001758 tmpInst.setOpcode(Mips::ADDiu);
Jim Grosbache9119e42015-05-13 18:37:00 +00001759 tmpInst.addOperand(MCOperand::createReg(DstReg));
1760 tmpInst.addOperand(MCOperand::createReg(SrcReg));
1761 tmpInst.addOperand(MCOperand::createImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001762 Instructions.push_back(tmpInst);
Toma Tabacua3d056f2015-05-15 09:42:11 +00001763 } else if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00001764 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00001765
Toma Tabacuae47f932015-04-10 13:28:16 +00001766 // For all other values which are representable as a 32-bit integer:
Jack Carter30a59822012-10-04 04:03:53 +00001767 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001768 // ori d,d,lo16(j)
Toma Tabacu79588102015-04-29 10:19:56 +00001769 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1770 uint16_t Bits15To0 = ImmValue & 0xffff;
1771
Toma Tabacua3d056f2015-05-15 09:42:11 +00001772 if (!Is32BitImm && !isInt<32>(ImmValue)) {
1773 // For DLI, expand to an ORi instead of a LUi to avoid sign-extending the
1774 // upper 32 bits.
1775 tmpInst.setOpcode(Mips::ORi);
1776 tmpInst.addOperand(MCOperand::createReg(DstReg));
1777 tmpInst.addOperand(MCOperand::createReg(Mips::ZERO));
1778 tmpInst.addOperand(MCOperand::createImm(Bits31To16));
1779 tmpInst.setLoc(IDLoc);
1780 Instructions.push_back(tmpInst);
1781 // Move the value to the upper 16 bits by doing a 16-bit left shift.
1782 createLShiftOri<16>(0, DstReg, IDLoc, Instructions);
1783 } else {
1784 tmpInst.setOpcode(Mips::LUi);
1785 tmpInst.addOperand(MCOperand::createReg(DstReg));
1786 tmpInst.addOperand(MCOperand::createImm(Bits31To16));
1787 Instructions.push_back(tmpInst);
1788 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001789 createLShiftOri<0>(Bits15To0, DstReg, IDLoc, Instructions);
1790
1791 if (UseSrcReg)
1792 createAddu(DstReg, DstReg, SrcReg, Instructions);
1793
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001794 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Toma Tabacu00e98672015-05-01 12:19:27 +00001795 if (Is32BitImm) {
1796 Error(IDLoc, "instruction requires a 32-bit immediate");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001797 return true;
1798 }
Toma Tabacu81496c12015-05-20 08:54:45 +00001799 warnIfNoMacro(IDLoc);
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 Tabacu81496c12015-05-20 08:54:45 +00001833 warnIfNoMacro(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001834
1835 // <------- hi32 ------> <------- lo32 ------>
1836 // <- hi16 -> <- lo16 ->
1837 // ___________________________________________
1838 // | | | | |
Toma Tabacubda745f2015-04-27 15:21:38 +00001839 // | 16-bits | 16-bits | 16-bits | 16-bits |
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001840 // |__________|__________|__________|__________|
1841 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001842 // For all other values which are representable as a 64-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001843 // li d,j => lui d,hi16(j)
1844 // ori d,d,lo16(hi32(j))
1845 // dsll d,d,16
1846 // ori d,d,hi16(lo32(j))
1847 // dsll d,d,16
1848 // ori d,d,lo16(lo32(j))
Toma Tabacu79588102015-04-29 10:19:56 +00001849 uint16_t Bits63To48 = (ImmValue >> 48) & 0xffff;
1850 uint16_t Bits47To32 = (ImmValue >> 32) & 0xffff;
1851 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1852 uint16_t Bits15To0 = ImmValue & 0xffff;
1853
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001854 tmpInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001855 tmpInst.addOperand(MCOperand::createReg(DstReg));
1856 tmpInst.addOperand(MCOperand::createImm(Bits63To48));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001857 Instructions.push_back(tmpInst);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001858 createLShiftOri<0>(Bits47To32, DstReg, IDLoc, Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001859
1860 // When Bits31To16 is 0, do a left shift of 32 bits instead of doing
1861 // two left shifts of 16 bits.
1862 if (Bits31To16 == 0) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001863 createLShiftOri<32>(Bits15To0, DstReg, IDLoc, Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001864 } else {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001865 createLShiftOri<16>(Bits31To16, DstReg, IDLoc, Instructions);
1866 createLShiftOri<16>(Bits15To0, DstReg, IDLoc, Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001867 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001868
1869 if (UseSrcReg)
1870 createAddu(DstReg, DstReg, SrcReg, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001871 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001872 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001873}
Jack Carter92995f12012-10-06 00:53:28 +00001874
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001875bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
1876 SmallVectorImpl<MCInst> &Instructions) {
1877 const MCOperand &ImmOp = Inst.getOperand(1);
1878 assert(ImmOp.isImm() && "expected immediate operand kind");
1879 const MCOperand &DstRegOp = Inst.getOperand(0);
1880 assert(DstRegOp.isReg() && "expected register operand kind");
1881
1882 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
1883 Is32BitImm, IDLoc, Instructions))
1884 return true;
1885
1886 return false;
1887}
1888
Matheus Almeida3813d572014-06-19 14:39:14 +00001889bool
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001890MipsAsmParser::expandLoadAddressReg(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001891 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacub5592ee2015-05-14 10:02:58 +00001892 const MCOperand &DstRegOp = Inst.getOperand(0);
1893 assert(DstRegOp.isReg() && "expected register operand kind");
1894
Jack Carter543fdf82012-10-09 23:29:45 +00001895 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001896 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1897 "expected immediate operand kind");
1898 if (!ImmOp.isImm()) {
Toma Tabacuec1de822015-05-14 10:53:40 +00001899 expandLoadAddressSym(DstRegOp, ImmOp, Is32BitImm, IDLoc, Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001900 return false;
1901 }
Jack Carter543fdf82012-10-09 23:29:45 +00001902 const MCOperand &SrcRegOp = Inst.getOperand(1);
1903 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001904
1905 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), SrcRegOp.getReg(),
1906 Is32BitImm, IDLoc, Instructions))
1907 return true;
1908
Matheus Almeida3813d572014-06-19 14:39:14 +00001909 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001910}
1911
Matheus Almeida3813d572014-06-19 14:39:14 +00001912bool
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001913MipsAsmParser::expandLoadAddressImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001914 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacub5592ee2015-05-14 10:02:58 +00001915 const MCOperand &DstRegOp = Inst.getOperand(0);
1916 assert(DstRegOp.isReg() && "expected register operand kind");
1917
Jack Carter543fdf82012-10-09 23:29:45 +00001918 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001919 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1920 "expected immediate operand kind");
1921 if (!ImmOp.isImm()) {
Toma Tabacuec1de822015-05-14 10:53:40 +00001922 expandLoadAddressSym(DstRegOp, ImmOp, Is32BitImm, IDLoc, Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001923 return false;
1924 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001925
1926 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
1927 Is32BitImm, IDLoc, Instructions))
1928 return true;
1929
Matheus Almeida3813d572014-06-19 14:39:14 +00001930 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001931}
1932
Toma Tabacuec1de822015-05-14 10:53:40 +00001933void MipsAsmParser::expandLoadAddressSym(
1934 const MCOperand &DstRegOp, const MCOperand &SymOp, bool Is32BitSym,
1935 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00001936 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00001937
Toma Tabacuec1de822015-05-14 10:53:40 +00001938 if (Is32BitSym && isABI_N64())
1939 Warning(IDLoc, "instruction loads the 32-bit address of a 64-bit symbol");
1940
Toma Tabacu0d64b202014-08-14 10:29:17 +00001941 MCInst tmpInst;
Toma Tabacub5592ee2015-05-14 10:02:58 +00001942 unsigned RegNo = DstRegOp.getReg();
Toma Tabacu0d64b202014-08-14 10:29:17 +00001943 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1944 const MCSymbolRefExpr *HiExpr =
1945 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1946 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1947 const MCSymbolRefExpr *LoExpr =
1948 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1949 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
Toma Tabacuec1de822015-05-14 10:53:40 +00001950 if (!Is32BitSym) {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001951 // If it's a 64-bit architecture, expand to:
1952 // la d,sym => lui d,highest(sym)
1953 // ori d,d,higher(sym)
1954 // dsll d,d,16
1955 // ori d,d,hi16(sym)
1956 // dsll d,d,16
1957 // ori d,d,lo16(sym)
1958 const MCSymbolRefExpr *HighestExpr =
1959 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1960 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1961 const MCSymbolRefExpr *HigherExpr =
1962 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1963 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1964
1965 tmpInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001966 tmpInst.addOperand(MCOperand::createReg(RegNo));
1967 tmpInst.addOperand(MCOperand::createExpr(HighestExpr));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001968 Instructions.push_back(tmpInst);
1969
Jim Grosbache9119e42015-05-13 18:37:00 +00001970 createLShiftOri<0>(MCOperand::createExpr(HigherExpr), RegNo, SMLoc(),
Toma Tabacua2861db2015-05-01 10:26:47 +00001971 Instructions);
Jim Grosbache9119e42015-05-13 18:37:00 +00001972 createLShiftOri<16>(MCOperand::createExpr(HiExpr), RegNo, SMLoc(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00001973 Instructions);
Jim Grosbache9119e42015-05-13 18:37:00 +00001974 createLShiftOri<16>(MCOperand::createExpr(LoExpr), RegNo, SMLoc(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00001975 Instructions);
1976 } else {
1977 // Otherwise, expand to:
1978 // la d,sym => lui d,hi16(sym)
1979 // ori d,d,lo16(sym)
1980 tmpInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001981 tmpInst.addOperand(MCOperand::createReg(RegNo));
1982 tmpInst.addOperand(MCOperand::createExpr(HiExpr));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001983 Instructions.push_back(tmpInst);
1984
Jim Grosbache9119e42015-05-13 18:37:00 +00001985 createLShiftOri<0>(MCOperand::createExpr(LoExpr), RegNo, SMLoc(),
Toma Tabacua2861db2015-05-01 10:26:47 +00001986 Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001987 }
1988}
1989
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00001990bool MipsAsmParser::expandUncondBranchMMPseudo(
1991 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00001992 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
1993 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001994
1995 MCOperand Offset = Inst.getOperand(0);
1996 if (Offset.isExpr()) {
1997 Inst.clear();
1998 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00001999 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2000 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2001 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002002 } else {
2003 assert(Offset.isImm() && "expected immediate operand kind");
2004 if (isIntN(11, Offset.getImm())) {
2005 // If offset fits into 11 bits then this instruction becomes microMIPS
2006 // 16-bit unconditional branch instruction.
2007 Inst.setOpcode(Mips::B16_MM);
2008 } else {
2009 if (!isIntN(17, Offset.getImm()))
2010 Error(IDLoc, "branch target out of range");
2011 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2012 Error(IDLoc, "branch to misaligned address");
2013 Inst.clear();
2014 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002015 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2016 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2017 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002018 }
2019 }
2020 Instructions.push_back(Inst);
2021
Toma Tabacu234482a2015-03-16 12:03:39 +00002022 // If .set reorder is active, emit a NOP after the branch instruction.
2023 if (AssemblerOptions.back()->isReorder())
2024 createNop(true, IDLoc, Instructions);
2025
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002026 return false;
2027}
2028
Jack Carter9e65aa32013-03-22 00:05:30 +00002029void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002030 SmallVectorImpl<MCInst> &Instructions,
2031 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002032 const MCSymbolRefExpr *SR;
2033 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00002034 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002035 const MCExpr *ExprOffset;
2036 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002037 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002038 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2039 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002040 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002041 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2042 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002043 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002044 if (isImmOpnd) {
2045 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2046 ImmOffset = Inst.getOperand(2).getImm();
2047 LoOffset = ImmOffset & 0x0000ffff;
2048 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002049 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002050 if (LoOffset & 0x8000)
2051 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002052 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002053 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002054 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002055 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002056 // These are some of the types of expansions we perform here:
2057 // 1) lw $8, sym => lui $8, %hi(sym)
2058 // lw $8, %lo(sym)($8)
2059 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2060 // add $8, $8, $9
2061 // lw $8, %lo(offset)($9)
2062 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2063 // add $at, $at, $8
2064 // lw $8, %lo(offset)($at)
2065 // 4) sw $8, sym => lui $at, %hi(sym)
2066 // sw $8, %lo(sym)($at)
2067 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2068 // add $at, $at, $8
2069 // sw $8, %lo(offset)($at)
2070 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2071 // ldc1 $f0, %lo(sym)($at)
2072 //
2073 // For load instructions we can use the destination register as a temporary
2074 // if base and dst are different (examples 1 and 2) and if the base register
2075 // is general purpose otherwise we must use $at (example 6) and error if it's
2076 // not available. For stores we must use $at (examples 4 and 5) because we
2077 // must not clobber the source register setting up the offset.
2078 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2079 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2080 unsigned RegClassIDOp0 =
2081 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2082 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2083 (RegClassIDOp0 == Mips::GPR64RegClassID);
2084 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002085 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002086 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002087 // At this point we need AT to perform the expansions and we exit if it is
2088 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002089 TmpRegNum = getATReg(IDLoc);
2090 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002091 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002092 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002093
Jack Carter9e65aa32013-03-22 00:05:30 +00002094 TempInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00002095 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002096 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002097 TempInst.addOperand(MCOperand::createImm(HiOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002098 else {
2099 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002100 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00002101 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
2102 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
2103 getContext());
Jim Grosbache9119e42015-05-13 18:37:00 +00002104 TempInst.addOperand(MCOperand::createExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002105 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002106 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jim Grosbache9119e42015-05-13 18:37:00 +00002107 TempInst.addOperand(MCOperand::createExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002108 }
2109 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002110 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002111 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002112 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002113 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002114 // Add temp register to base.
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002115 if (BaseRegNum != Mips::ZERO) {
2116 TempInst.setOpcode(Mips::ADDu);
Jim Grosbache9119e42015-05-13 18:37:00 +00002117 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2118 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2119 TempInst.addOperand(MCOperand::createReg(BaseRegNum));
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002120 Instructions.push_back(TempInst);
2121 TempInst.clear();
2122 }
Alp Tokercb402912014-01-24 17:20:08 +00002123 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002124 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002125 TempInst.setOpcode(Inst.getOpcode());
Jim Grosbache9119e42015-05-13 18:37:00 +00002126 TempInst.addOperand(MCOperand::createReg(RegOpNum));
2127 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002128 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002129 TempInst.addOperand(MCOperand::createImm(LoOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002130 else {
2131 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002132 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
2133 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
2134 getContext());
Jim Grosbache9119e42015-05-13 18:37:00 +00002135 TempInst.addOperand(MCOperand::createExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002136 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002137 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jim Grosbache9119e42015-05-13 18:37:00 +00002138 TempInst.addOperand(MCOperand::createExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002139 }
2140 }
2141 Instructions.push_back(TempInst);
2142 TempInst.clear();
2143}
2144
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002145bool
2146MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2147 SmallVectorImpl<MCInst> &Instructions) {
2148 unsigned OpNum = Inst.getNumOperands();
2149 unsigned Opcode = Inst.getOpcode();
2150 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2151
2152 assert (Inst.getOperand(OpNum - 1).isImm() &&
2153 Inst.getOperand(OpNum - 2).isReg() &&
2154 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2155
2156 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2157 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2158 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2159 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2160 // It can be implemented as SWM16 or LWM16 instruction.
2161 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2162
2163 Inst.setOpcode(NewOpcode);
2164 Instructions.push_back(Inst);
2165 return false;
2166}
2167
Toma Tabacu234482a2015-03-16 12:03:39 +00002168void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
2169 SmallVectorImpl<MCInst> &Instructions) {
2170 MCInst NopInst;
2171 if (hasShortDelaySlot) {
2172 NopInst.setOpcode(Mips::MOVE16_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002173 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2174 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
Toma Tabacu234482a2015-03-16 12:03:39 +00002175 } else {
2176 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00002177 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2178 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2179 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu234482a2015-03-16 12:03:39 +00002180 }
2181 Instructions.push_back(NopInst);
2182}
2183
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002184void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
2185 unsigned TrgReg,
2186 SmallVectorImpl<MCInst> &Instructions) {
2187 MCInst AdduInst;
2188 AdduInst.setOpcode(Mips::ADDu);
Jim Grosbache9119e42015-05-13 18:37:00 +00002189 AdduInst.addOperand(MCOperand::createReg(DstReg));
2190 AdduInst.addOperand(MCOperand::createReg(SrcReg));
2191 AdduInst.addOperand(MCOperand::createReg(TrgReg));
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002192 Instructions.push_back(AdduInst);
2193}
2194
Matheus Almeida595fcab2014-06-11 15:05:56 +00002195unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
2196 // As described by the Mips32r2 spec, the registers Rd and Rs for
2197 // jalr.hb must be different.
2198 unsigned Opcode = Inst.getOpcode();
2199
2200 if (Opcode == Mips::JALR_HB &&
2201 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
2202 return Match_RequiresDifferentSrcAndDst;
2203
2204 return Match_Success;
2205}
2206
David Blaikie960ea3f2014-06-08 16:18:35 +00002207bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
2208 OperandVector &Operands,
2209 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00002210 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00002211 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00002212
Jack Carterb4dbc172012-09-05 23:34:03 +00002213 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00002214 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00002215 unsigned MatchResult =
2216 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00002217
2218 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002219 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002220 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00002221 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00002222 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00002223 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00002224 return false;
2225 }
2226 case Match_MissingFeature:
2227 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
2228 return true;
2229 case Match_InvalidOperand: {
2230 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00002231 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002232 if (ErrorInfo >= Operands.size())
2233 return Error(IDLoc, "too few operands for instruction");
2234
David Blaikie960ea3f2014-06-08 16:18:35 +00002235 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00002236 if (ErrorLoc == SMLoc())
2237 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00002238 }
2239
2240 return Error(ErrorLoc, "invalid operand for instruction");
2241 }
2242 case Match_MnemonicFail:
2243 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00002244 case Match_RequiresDifferentSrcAndDst:
2245 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00002246 }
Craig Topper589ceee2015-01-03 08:16:34 +00002247
2248 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00002249}
2250
Toma Tabacud9d344b2015-04-27 14:05:04 +00002251void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
2252 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
2253 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
2254 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002255}
2256
Toma Tabacu81496c12015-05-20 08:54:45 +00002257void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
2258 if (!AssemblerOptions.back()->isMacro())
2259 Warning(Loc, "macro instruction expanded into multiple instructions");
2260}
2261
Daniel Sandersef638fe2014-10-03 15:37:37 +00002262void
2263MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
2264 SMRange Range, bool ShowColors) {
2265 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00002266 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00002267 ShowColors);
2268}
2269
Jack Carter1ac53222013-02-20 23:11:17 +00002270int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002271 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002272
Vladimir Medic4c299852013-11-06 11:27:05 +00002273 CC = StringSwitch<unsigned>(Name)
2274 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002275 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00002276 .Case("a0", 4)
2277 .Case("a1", 5)
2278 .Case("a2", 6)
2279 .Case("a3", 7)
2280 .Case("v0", 2)
2281 .Case("v1", 3)
2282 .Case("s0", 16)
2283 .Case("s1", 17)
2284 .Case("s2", 18)
2285 .Case("s3", 19)
2286 .Case("s4", 20)
2287 .Case("s5", 21)
2288 .Case("s6", 22)
2289 .Case("s7", 23)
2290 .Case("k0", 26)
2291 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002292 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00002293 .Case("sp", 29)
2294 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002295 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00002296 .Case("ra", 31)
2297 .Case("t0", 8)
2298 .Case("t1", 9)
2299 .Case("t2", 10)
2300 .Case("t3", 11)
2301 .Case("t4", 12)
2302 .Case("t5", 13)
2303 .Case("t6", 14)
2304 .Case("t7", 15)
2305 .Case("t8", 24)
2306 .Case("t9", 25)
2307 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002308
Toma Tabacufda445c2014-09-15 15:33:01 +00002309 if (!(isABI_N32() || isABI_N64()))
2310 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002311
Daniel Sandersef638fe2014-10-03 15:37:37 +00002312 if (12 <= CC && CC <= 15) {
2313 // Name is one of t4-t7
2314 AsmToken RegTok = getLexer().peekTok();
2315 SMRange RegRange = RegTok.getLocRange();
2316
2317 StringRef FixedName = StringSwitch<StringRef>(Name)
2318 .Case("t4", "t0")
2319 .Case("t5", "t1")
2320 .Case("t6", "t2")
2321 .Case("t7", "t3")
2322 .Default("");
2323 assert(FixedName != "" && "Register name is not one of t4-t7.");
2324
2325 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
2326 "Did you mean $" + FixedName + "?", RegRange);
2327 }
2328
Toma Tabacufda445c2014-09-15 15:33:01 +00002329 // Although SGI documentation just cuts out t0-t3 for n32/n64,
2330 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
2331 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
2332 if (8 <= CC && CC <= 11)
2333 CC += 4;
2334
2335 if (CC == -1)
2336 CC = StringSwitch<unsigned>(Name)
2337 .Case("a4", 8)
2338 .Case("a5", 9)
2339 .Case("a6", 10)
2340 .Case("a7", 11)
2341 .Case("kt0", 26)
2342 .Case("kt1", 27)
2343 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002344
2345 return CC;
2346}
Jack Carterd0bd6422013-04-18 00:41:53 +00002347
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002348int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
2349 int CC;
2350
2351 CC = StringSwitch<unsigned>(Name)
2352 .Case("hwr_cpunum", 0)
2353 .Case("hwr_synci_step", 1)
2354 .Case("hwr_cc", 2)
2355 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00002356 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002357 .Default(-1);
2358
2359 return CC;
2360}
2361
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002362int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002363
Jack Cartera63b16a2012-09-07 00:23:42 +00002364 if (Name[0] == 'f') {
2365 StringRef NumString = Name.substr(1);
2366 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002367 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002368 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002369 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00002370 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002371 return IntVal;
2372 }
2373 return -1;
2374}
Jack Cartera63b16a2012-09-07 00:23:42 +00002375
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002376int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
2377
2378 if (Name.startswith("fcc")) {
2379 StringRef NumString = Name.substr(3);
2380 unsigned IntVal;
2381 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002382 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002383 if (IntVal > 7) // There are only 8 fcc registers.
2384 return -1;
2385 return IntVal;
2386 }
2387 return -1;
2388}
2389
2390int MipsAsmParser::matchACRegisterName(StringRef Name) {
2391
Akira Hatanaka274d24c2013-08-14 01:15:52 +00002392 if (Name.startswith("ac")) {
2393 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002394 unsigned IntVal;
2395 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002396 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002397 if (IntVal > 3) // There are only 3 acc registers.
2398 return -1;
2399 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00002400 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002401 return -1;
2402}
Jack Carterd0bd6422013-04-18 00:41:53 +00002403
Jack Carter5dc8ac92013-09-25 23:50:44 +00002404int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
2405 unsigned IntVal;
2406
2407 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2408 return -1;
2409
2410 if (IntVal > 31)
2411 return -1;
2412
2413 return IntVal;
2414}
2415
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002416int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
2417 int CC;
2418
2419 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00002420 .Case("msair", 0)
2421 .Case("msacsr", 1)
2422 .Case("msaaccess", 2)
2423 .Case("msasave", 3)
2424 .Case("msamodify", 4)
2425 .Case("msarequest", 5)
2426 .Case("msamap", 6)
2427 .Case("msaunmap", 7)
2428 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002429
2430 return CC;
2431}
2432
Toma Tabacu89a712b2015-04-15 10:48:56 +00002433unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00002434 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00002435 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002436 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00002437 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00002438 return 0;
2439 }
2440 unsigned AT = getReg(
2441 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00002442 return AT;
2443}
Jack Carter0b744b32012-10-04 02:29:46 +00002444
Jack Carterd0bd6422013-04-18 00:41:53 +00002445unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00002446 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00002447}
2448
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002449unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002450 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00002451 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002452}
2453
Jack Carter873c7242013-01-12 01:03:14 +00002454int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002455 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00002456 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00002457 return -1;
2458
Jack Carter873c7242013-01-12 01:03:14 +00002459 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00002460}
2461
Toma Tabacu13964452014-09-04 13:23:44 +00002462bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002463 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002464 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002465
Jack Carter30a59822012-10-04 04:03:53 +00002466 // Check if the current operand has a custom associated parser, if so, try to
2467 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00002468 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2469 if (ResTy == MatchOperand_Success)
2470 return false;
2471 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2472 // there was a match, but an error occurred, in which case, just return that
2473 // the operand parsing failed.
2474 if (ResTy == MatchOperand_ParseFail)
2475 return true;
2476
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002477 DEBUG(dbgs() << ".. Generic Parser\n");
2478
Jack Carterb4dbc172012-09-05 23:34:03 +00002479 switch (getLexer().getKind()) {
2480 default:
2481 Error(Parser.getTok().getLoc(), "unexpected token in operand");
2482 return true;
2483 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002484 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00002485 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00002486
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002487 // Almost all registers have been parsed by custom parsers. There is only
2488 // one exception to this. $zero (and it's alias $0) will reach this point
2489 // for div, divu, and similar instructions because it is not an operand
2490 // to the instruction definition but an explicit register. Special case
2491 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00002492 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00002493 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002494
Jack Carterd0bd6422013-04-18 00:41:53 +00002495 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00002496 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002497 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00002498 return true;
2499
Jack Carter873c7242013-01-12 01:03:14 +00002500 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00002501 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00002502 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00002503 const MCExpr *Res =
2504 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00002505
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002506 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002507 return false;
2508 }
Vladimir Medic4c299852013-11-06 11:27:05 +00002509 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00002510 case AsmToken::LParen:
2511 case AsmToken::Minus:
2512 case AsmToken::Plus:
2513 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002514 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00002515 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002516 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002517 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002518 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00002519 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00002520 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002521 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002522 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002523 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00002524 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00002525 return true;
2526
Jack Carter873c7242013-01-12 01:03:14 +00002527 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2528
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002529 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00002530 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002531 } // case AsmToken::Percent
2532 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00002533 return true;
2534}
2535
Vladimir Medic4c299852013-11-06 11:27:05 +00002536const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00002537 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00002538 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00002539 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002540 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00002541 // It's a constant, evaluate reloc value.
2542 int16_t Val;
2543 switch (getVariantKind(RelocStr)) {
2544 case MCSymbolRefExpr::VK_Mips_ABS_LO:
2545 // Get the 1st 16-bits.
2546 Val = MCE->getValue() & 0xffff;
2547 break;
2548 case MCSymbolRefExpr::VK_Mips_ABS_HI:
2549 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2550 // 16 bits being negative.
2551 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2552 break;
2553 case MCSymbolRefExpr::VK_Mips_HIGHER:
2554 // Get the 3rd 16-bits.
2555 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2556 break;
2557 case MCSymbolRefExpr::VK_Mips_HIGHEST:
2558 // Get the 4th 16-bits.
2559 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2560 break;
2561 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00002562 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00002563 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00002564 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002565 }
2566
Jack Carterb5cf5902013-04-17 00:18:04 +00002567 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002568 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00002569 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00002570 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00002571 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002572 return Res;
2573 }
2574
2575 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00002576 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2577
Sasa Stankovic06c47802014-04-03 10:37:45 +00002578 // Try to create target expression.
2579 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
2580 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002581
Jack Carterd0bd6422013-04-18 00:41:53 +00002582 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2583 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00002584 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
2585 return Res;
2586 }
2587
2588 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002589 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
2590 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
2591 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002592 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002593 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002594 return Expr;
2595}
2596
2597bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2598
2599 switch (Expr->getKind()) {
2600 case MCExpr::Constant:
2601 return true;
2602 case MCExpr::SymbolRef:
2603 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2604 case MCExpr::Binary:
2605 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2606 if (!isEvaluated(BE->getLHS()))
2607 return false;
2608 return isEvaluated(BE->getRHS());
2609 }
2610 case MCExpr::Unary:
2611 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002612 case MCExpr::Target:
2613 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002614 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002615 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002616}
Jack Carterd0bd6422013-04-18 00:41:53 +00002617
Jack Carterb5cf5902013-04-17 00:18:04 +00002618bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002619 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00002620 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002621 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002622 if (Tok.isNot(AsmToken::Identifier))
2623 return true;
2624
Yaron Keren075759a2015-03-30 15:42:36 +00002625 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00002626
Jack Carterd0bd6422013-04-18 00:41:53 +00002627 Parser.Lex(); // Eat the identifier.
2628 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002629 const MCExpr *IdVal;
2630 SMLoc EndLoc;
2631
2632 if (getLexer().getKind() == AsmToken::LParen) {
2633 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002634 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002635 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002636 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002637 const AsmToken &nextTok = Parser.getTok();
2638 if (nextTok.isNot(AsmToken::Identifier))
2639 return true;
2640 Str += "(%";
2641 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002642 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002643 if (getLexer().getKind() != AsmToken::LParen)
2644 return true;
2645 } else
2646 break;
2647 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002648 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002649 return true;
2650
2651 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002652 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002653
2654 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002655 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002656
Jack Carterd0bd6422013-04-18 00:41:53 +00002657 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002658 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002659}
2660
Jack Carterb4dbc172012-09-05 23:34:03 +00002661bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2662 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002663 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002664 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002665 if (ResTy == MatchOperand_Success) {
2666 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002667 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002668 StartLoc = Operand.getStartLoc();
2669 EndLoc = Operand.getEndLoc();
2670
2671 // AFAIK, we only support numeric registers and named GPR's in CFI
2672 // directives.
2673 // Don't worry about eating tokens before failing. Using an unrecognised
2674 // register is a parse error.
2675 if (Operand.isGPRAsmReg()) {
2676 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002677 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002678 }
2679
2680 return (RegNo == (unsigned)-1);
2681 }
2682
2683 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002684 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002685}
2686
Jack Carterb5cf5902013-04-17 00:18:04 +00002687bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002688 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00002689 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002690 bool Result = true;
2691
2692 while (getLexer().getKind() == AsmToken::LParen)
2693 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002694
Jack Carterd0bd6422013-04-18 00:41:53 +00002695 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002696 default:
2697 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002698 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002699 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002700 case AsmToken::Integer:
2701 case AsmToken::Minus:
2702 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002703 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002704 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002705 else
2706 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002707 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002708 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002709 break;
Jack Carter873c7242013-01-12 01:03:14 +00002710 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002711 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002712 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002713 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002714}
2715
David Blaikie960ea3f2014-06-08 16:18:35 +00002716MipsAsmParser::OperandMatchResultTy
2717MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002718 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002719 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002720 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002721 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002722 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002723 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002724 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002725 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002726
Jack Carterb5cf5902013-04-17 00:18:04 +00002727 if (getLexer().getKind() == AsmToken::LParen) {
2728 Parser.Lex();
2729 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002730 }
2731
Jack Carterb5cf5902013-04-17 00:18:04 +00002732 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002733 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002734 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002735
Jack Carterd0bd6422013-04-18 00:41:53 +00002736 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002737 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002738 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2739 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002740 SMLoc E =
2741 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002742 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002743 return MatchOperand_Success;
2744 }
2745 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002746 SMLoc E =
2747 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002748
Jack Carterd0bd6422013-04-18 00:41:53 +00002749 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002750 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002751 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002752 S, E, *this);
2753 Operands.push_back(
2754 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002755 return MatchOperand_Success;
2756 }
2757 Error(Parser.getTok().getLoc(), "'(' expected");
2758 return MatchOperand_ParseFail;
2759 }
2760
Jack Carterd0bd6422013-04-18 00:41:53 +00002761 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002762 }
2763
Toma Tabacu13964452014-09-04 13:23:44 +00002764 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002765 if (Res != MatchOperand_Success)
2766 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002767
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002768 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002769 Error(Parser.getTok().getLoc(), "')' expected");
2770 return MatchOperand_ParseFail;
2771 }
2772
Jack Carter873c7242013-01-12 01:03:14 +00002773 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2774
Jack Carterd0bd6422013-04-18 00:41:53 +00002775 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002776
Craig Topper062a2ba2014-04-25 05:30:21 +00002777 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002778 IdVal = MCConstantExpr::Create(0, getContext());
2779
Jack Carterd0bd6422013-04-18 00:41:53 +00002780 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002781 std::unique_ptr<MipsOperand> op(
2782 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002783 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002784 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002785 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002786 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002787 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2788 int64_t Imm;
2789 if (IdVal->EvaluateAsAbsolute(Imm))
2790 IdVal = MCConstantExpr::Create(Imm, getContext());
2791 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2792 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2793 getContext());
2794 }
2795
David Blaikie960ea3f2014-06-08 16:18:35 +00002796 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002797 return MatchOperand_Success;
2798}
2799
David Blaikie960ea3f2014-06-08 16:18:35 +00002800bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002801 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00002802 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00002803 if (Sym) {
2804 SMLoc S = Parser.getTok().getLoc();
2805 const MCExpr *Expr;
2806 if (Sym->isVariable())
2807 Expr = Sym->getVariableValue();
2808 else
2809 return false;
2810 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002811 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002812 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002813 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002814 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002815 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002816 if (ResTy == MatchOperand_Success) {
2817 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002818 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002819 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002820 llvm_unreachable("Should never ParseFail");
2821 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002822 }
2823 } else if (Expr->getKind() == MCExpr::Constant) {
2824 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002825 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002826 Operands.push_back(
2827 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002828 return true;
2829 }
2830 }
2831 return false;
2832}
Jack Carterd0bd6422013-04-18 00:41:53 +00002833
Jack Carter873c7242013-01-12 01:03:14 +00002834MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002835MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002836 StringRef Identifier,
2837 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002838 int Index = matchCPURegisterName(Identifier);
2839 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002840 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002841 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2842 return MatchOperand_Success;
2843 }
2844
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002845 Index = matchHWRegsRegisterName(Identifier);
2846 if (Index != -1) {
2847 Operands.push_back(MipsOperand::createHWRegsReg(
2848 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2849 return MatchOperand_Success;
2850 }
2851
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002852 Index = matchFPURegisterName(Identifier);
2853 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002854 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002855 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2856 return MatchOperand_Success;
2857 }
2858
2859 Index = matchFCCRegisterName(Identifier);
2860 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002861 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002862 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2863 return MatchOperand_Success;
2864 }
2865
2866 Index = matchACRegisterName(Identifier);
2867 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002868 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002869 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2870 return MatchOperand_Success;
2871 }
2872
2873 Index = matchMSA128RegisterName(Identifier);
2874 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002875 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002876 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2877 return MatchOperand_Success;
2878 }
2879
2880 Index = matchMSA128CtrlRegisterName(Identifier);
2881 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002882 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002883 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2884 return MatchOperand_Success;
2885 }
2886
2887 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002888}
2889
2890MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002891MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002892 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00002893 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002894
2895 if (Token.is(AsmToken::Identifier)) {
2896 DEBUG(dbgs() << ".. identifier\n");
2897 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002898 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002899 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002900 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002901 } else if (Token.is(AsmToken::Integer)) {
2902 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002903 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002904 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2905 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002906 return MatchOperand_Success;
2907 }
2908
2909 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2910
2911 return MatchOperand_NoMatch;
2912}
2913
David Blaikie960ea3f2014-06-08 16:18:35 +00002914MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002915MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002916 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002917 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002918
2919 auto Token = Parser.getTok();
2920
2921 SMLoc S = Token.getLoc();
2922
2923 if (Token.isNot(AsmToken::Dollar)) {
2924 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2925 if (Token.is(AsmToken::Identifier)) {
2926 if (searchSymbolAlias(Operands))
2927 return MatchOperand_Success;
2928 }
2929 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2930 return MatchOperand_NoMatch;
2931 }
2932 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002933
Toma Tabacu13964452014-09-04 13:23:44 +00002934 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002935 if (ResTy == MatchOperand_Success) {
2936 Parser.Lex(); // $
2937 Parser.Lex(); // identifier
2938 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002939 return ResTy;
2940}
2941
2942MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002943MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002944 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002945 switch (getLexer().getKind()) {
2946 default:
2947 return MatchOperand_NoMatch;
2948 case AsmToken::LParen:
2949 case AsmToken::Minus:
2950 case AsmToken::Plus:
2951 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002952 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002953 case AsmToken::String:
2954 break;
2955 }
2956
2957 const MCExpr *IdVal;
2958 SMLoc S = Parser.getTok().getLoc();
2959 if (getParser().parseExpression(IdVal))
2960 return MatchOperand_ParseFail;
2961
2962 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2963 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2964 return MatchOperand_Success;
2965}
2966
David Blaikie960ea3f2014-06-08 16:18:35 +00002967MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002968MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002969 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002970 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002971
2972 SMLoc S = getLexer().getLoc();
2973
2974 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002975 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002976 if (ResTy != MatchOperand_NoMatch)
2977 return ResTy;
2978
Daniel Sanders315386c2014-04-01 10:40:14 +00002979 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002980 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002981 if (ResTy != MatchOperand_NoMatch)
2982 return ResTy;
2983
Daniel Sandersffd84362014-04-01 10:41:48 +00002984 const MCExpr *Expr = nullptr;
2985 if (Parser.parseExpression(Expr)) {
2986 // We have no way of knowing if a symbol was consumed so we must ParseFail
2987 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002988 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002989 Operands.push_back(
2990 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002991 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002992}
2993
Vladimir Medic2b953d02013-10-01 09:48:56 +00002994MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002995MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002996 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00002997 const MCExpr *IdVal;
2998 // If the first token is '$' we may have register operand.
2999 if (Parser.getTok().is(AsmToken::Dollar))
3000 return MatchOperand_NoMatch;
3001 SMLoc S = Parser.getTok().getLoc();
3002 if (getParser().parseExpression(IdVal))
3003 return MatchOperand_ParseFail;
3004 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00003005 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00003006 int64_t Val = MCE->getValue();
3007 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3008 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003009 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00003010 return MatchOperand_Success;
3011}
3012
Matheus Almeida779c5932013-11-18 12:32:49 +00003013MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003014MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003015 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00003016 switch (getLexer().getKind()) {
3017 default:
3018 return MatchOperand_NoMatch;
3019 case AsmToken::LParen:
3020 case AsmToken::Plus:
3021 case AsmToken::Minus:
3022 case AsmToken::Integer:
3023 break;
3024 }
3025
3026 const MCExpr *Expr;
3027 SMLoc S = Parser.getTok().getLoc();
3028
3029 if (getParser().parseExpression(Expr))
3030 return MatchOperand_ParseFail;
3031
3032 int64_t Val;
3033 if (!Expr->EvaluateAsAbsolute(Val)) {
3034 Error(S, "expected immediate value");
3035 return MatchOperand_ParseFail;
3036 }
3037
3038 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
3039 // and because the CPU always adds one to the immediate field, the allowed
3040 // range becomes 1..4. We'll only check the range here and will deal
3041 // with the addition/subtraction when actually decoding/encoding
3042 // the instruction.
3043 if (Val < 1 || Val > 4) {
3044 Error(S, "immediate not in range (1..4)");
3045 return MatchOperand_ParseFail;
3046 }
3047
Jack Carter3b2c96e2014-01-22 23:31:38 +00003048 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003049 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00003050 return MatchOperand_Success;
3051}
3052
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00003053MipsAsmParser::OperandMatchResultTy
3054MipsAsmParser::parseRegisterList(OperandVector &Operands) {
3055 MCAsmParser &Parser = getParser();
3056 SmallVector<unsigned, 10> Regs;
3057 unsigned RegNo;
3058 unsigned PrevReg = Mips::NoRegister;
3059 bool RegRange = false;
3060 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3061
3062 if (Parser.getTok().isNot(AsmToken::Dollar))
3063 return MatchOperand_ParseFail;
3064
3065 SMLoc S = Parser.getTok().getLoc();
3066 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
3067 SMLoc E = getLexer().getLoc();
3068 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
3069 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
3070 if (RegRange) {
3071 // Remove last register operand because registers from register range
3072 // should be inserted first.
3073 if (RegNo == Mips::RA) {
3074 Regs.push_back(RegNo);
3075 } else {
3076 unsigned TmpReg = PrevReg + 1;
3077 while (TmpReg <= RegNo) {
3078 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
3079 Error(E, "invalid register operand");
3080 return MatchOperand_ParseFail;
3081 }
3082
3083 PrevReg = TmpReg;
3084 Regs.push_back(TmpReg++);
3085 }
3086 }
3087
3088 RegRange = false;
3089 } else {
3090 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
3091 (RegNo != Mips::RA)) {
3092 Error(E, "$16 or $31 expected");
3093 return MatchOperand_ParseFail;
3094 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
3095 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3096 Error(E, "invalid register operand");
3097 return MatchOperand_ParseFail;
3098 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
3099 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3100 Error(E, "consecutive register numbers expected");
3101 return MatchOperand_ParseFail;
3102 }
3103
3104 Regs.push_back(RegNo);
3105 }
3106
3107 if (Parser.getTok().is(AsmToken::Minus))
3108 RegRange = true;
3109
3110 if (!Parser.getTok().isNot(AsmToken::Minus) &&
3111 !Parser.getTok().isNot(AsmToken::Comma)) {
3112 Error(E, "',' or '-' expected");
3113 return MatchOperand_ParseFail;
3114 }
3115
3116 Lex(); // Consume comma or minus
3117 if (Parser.getTok().isNot(AsmToken::Dollar))
3118 break;
3119
3120 PrevReg = RegNo;
3121 }
3122
3123 SMLoc E = Parser.getTok().getLoc();
3124 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3125 parseMemOperand(Operands);
3126 return MatchOperand_Success;
3127}
3128
Zoran Jovanovic2deca342014-12-16 14:59:10 +00003129MipsAsmParser::OperandMatchResultTy
3130MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
3131 MCAsmParser &Parser = getParser();
3132
3133 SMLoc S = Parser.getTok().getLoc();
3134 if (parseAnyRegister(Operands) != MatchOperand_Success)
3135 return MatchOperand_ParseFail;
3136
3137 SMLoc E = Parser.getTok().getLoc();
3138 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
3139 unsigned Reg = Op.getGPR32Reg();
3140 Operands.pop_back();
3141 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
3142 return MatchOperand_Success;
3143}
3144
Zoran Jovanovic41688672015-02-10 16:36:20 +00003145MipsAsmParser::OperandMatchResultTy
3146MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
3147 MCAsmParser &Parser = getParser();
3148 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3149 SmallVector<unsigned, 10> Regs;
3150
3151 if (Parser.getTok().isNot(AsmToken::Dollar))
3152 return MatchOperand_ParseFail;
3153
3154 SMLoc S = Parser.getTok().getLoc();
3155
3156 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3157 return MatchOperand_ParseFail;
3158
3159 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3160 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3161 Regs.push_back(RegNo);
3162
3163 SMLoc E = Parser.getTok().getLoc();
3164 if (Parser.getTok().isNot(AsmToken::Comma)) {
3165 Error(E, "',' expected");
3166 return MatchOperand_ParseFail;
3167 }
3168
3169 // Remove comma.
3170 Parser.Lex();
3171
3172 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3173 return MatchOperand_ParseFail;
3174
3175 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3176 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3177 Regs.push_back(RegNo);
3178
3179 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3180
3181 return MatchOperand_Success;
3182}
3183
Jack Carterdc1e35d2012-09-06 20:00:02 +00003184MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
3185
Vladimir Medic4c299852013-11-06 11:27:05 +00003186 MCSymbolRefExpr::VariantKind VK =
3187 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
3188 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
3189 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
3190 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
3191 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
3192 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
3193 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
3194 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
3195 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
3196 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
3197 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
3198 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
3199 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
3200 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
3201 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
3202 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
3203 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
3204 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00003205 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
3206 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
3207 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
3208 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
3209 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
3210 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00003211 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
3212 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00003213 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003214
Matheus Almeida2852af82014-04-22 10:15:54 +00003215 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00003216
Jack Carterdc1e35d2012-09-06 20:00:02 +00003217 return VK;
3218}
Jack Cartera63b16a2012-09-07 00:23:42 +00003219
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003220/// Sometimes (i.e. load/stores) the operand may be followed immediately by
3221/// either this.
3222/// ::= '(', register, ')'
3223/// handle it before we iterate so we don't get tripped up by the lack of
3224/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003225bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003226 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003227 if (getLexer().is(AsmToken::LParen)) {
3228 Operands.push_back(
3229 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
3230 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003231 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003232 SMLoc Loc = getLexer().getLoc();
3233 Parser.eatToEndOfStatement();
3234 return Error(Loc, "unexpected token in argument list");
3235 }
3236 if (Parser.getTok().isNot(AsmToken::RParen)) {
3237 SMLoc Loc = getLexer().getLoc();
3238 Parser.eatToEndOfStatement();
3239 return Error(Loc, "unexpected token, expected ')'");
3240 }
3241 Operands.push_back(
3242 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
3243 Parser.Lex();
3244 }
3245 return false;
3246}
3247
3248/// Sometimes (i.e. in MSA) the operand may be followed immediately by
3249/// either one of these.
3250/// ::= '[', register, ']'
3251/// ::= '[', integer, ']'
3252/// handle it before we iterate so we don't get tripped up by the lack of
3253/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003254bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00003255 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003256 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003257 if (getLexer().is(AsmToken::LBrac)) {
3258 Operands.push_back(
3259 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
3260 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003261 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003262 SMLoc Loc = getLexer().getLoc();
3263 Parser.eatToEndOfStatement();
3264 return Error(Loc, "unexpected token in argument list");
3265 }
3266 if (Parser.getTok().isNot(AsmToken::RBrac)) {
3267 SMLoc Loc = getLexer().getLoc();
3268 Parser.eatToEndOfStatement();
3269 return Error(Loc, "unexpected token, expected ']'");
3270 }
3271 Operands.push_back(
3272 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
3273 Parser.Lex();
3274 }
3275 return false;
3276}
3277
David Blaikie960ea3f2014-06-08 16:18:35 +00003278bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
3279 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003280 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003281 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003282
3283 // We have reached first instruction, module directive are now forbidden.
3284 getTargetStreamer().forbidModuleDirective();
3285
Vladimir Medic74593e62013-07-17 15:00:42 +00003286 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00003287 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00003288 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00003289 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00003290 }
Vladimir Medic64828a12013-07-16 10:07:14 +00003291 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003292 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003293
3294 // Read the remaining operands.
3295 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3296 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003297 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003298 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003299 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003300 return Error(Loc, "unexpected token in argument list");
3301 }
Toma Tabacu13964452014-09-04 13:23:44 +00003302 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003303 return true;
3304 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00003305
Jack Carterd0bd6422013-04-18 00:41:53 +00003306 while (getLexer().is(AsmToken::Comma)) {
3307 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00003308 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003309 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003310 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003311 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003312 return Error(Loc, "unexpected token in argument list");
3313 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003314 // Parse bracket and parenthesis suffixes before we iterate
3315 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00003316 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003317 return true;
3318 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00003319 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003320 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003321 }
3322 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003323 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3324 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003325 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003326 return Error(Loc, "unexpected token in argument list");
3327 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003328 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00003329 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00003330}
3331
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003332bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003333 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003334 SMLoc Loc = getLexer().getLoc();
3335 Parser.eatToEndOfStatement();
3336 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00003337}
3338
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003339bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003340 return Error(Loc, ErrorMsg);
3341}
3342
Jack Carter0b744b32012-10-04 02:29:46 +00003343bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003344 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003345 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00003346
3347 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00003348 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00003349
3350 Parser.Lex(); // Eat "noat".
3351
Jack Carterd0bd6422013-04-18 00:41:53 +00003352 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003353 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003354 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003355 return false;
3356 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003357
3358 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003359 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003360 return false;
3361}
Jack Carterd0bd6422013-04-18 00:41:53 +00003362
Jack Carter0b744b32012-10-04 02:29:46 +00003363bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00003364 // Line can be: ".set at", which sets $at to $1
3365 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00003366 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00003367 Parser.Lex(); // Eat "at".
3368
Jack Carter0b744b32012-10-04 02:29:46 +00003369 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003370 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00003371 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00003372
3373 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003374 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003375 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00003376 }
3377
3378 if (getLexer().isNot(AsmToken::Equal)) {
3379 reportParseError("unexpected token, expected equals sign");
3380 return false;
3381 }
3382 Parser.Lex(); // Eat "=".
3383
3384 if (getLexer().isNot(AsmToken::Dollar)) {
3385 if (getLexer().is(AsmToken::EndOfStatement)) {
3386 reportParseError("no register specified");
3387 return false;
3388 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00003389 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00003390 return false;
3391 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003392 }
3393 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00003394
Toma Tabacu16a74492015-02-13 10:30:57 +00003395 // Find out what "reg" is.
3396 unsigned AtRegNo;
3397 const AsmToken &Reg = Parser.getTok();
3398 if (Reg.is(AsmToken::Identifier)) {
3399 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
3400 } else if (Reg.is(AsmToken::Integer)) {
3401 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00003402 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00003403 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00003404 return false;
3405 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003406
3407 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00003408 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003409 reportParseError("invalid register");
3410 return false;
3411 }
3412 Parser.Lex(); // Eat "reg".
3413
3414 // If this is not the end of the statement, report an error.
3415 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3416 reportParseError("unexpected token, expected end of statement");
3417 return false;
3418 }
3419
3420 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
3421
3422 Parser.Lex(); // Consume the EndOfStatement.
3423 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003424}
3425
3426bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003427 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003428 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003429 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003430 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003431 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003432 return false;
3433 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003434 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00003435 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003436 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003437 return false;
3438}
3439
3440bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003441 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003442 Parser.Lex();
3443 // If this is not the end of the statement, report an error.
3444 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003445 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003446 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003447 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003448 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00003449 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003450 Parser.Lex(); // Consume the EndOfStatement.
3451 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003452}
3453
3454bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003455 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003456 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003457 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003458 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003459 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003460 return false;
3461 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003462 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00003463 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003464 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003465 return false;
3466}
3467
3468bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003469 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003470 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003471 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003472 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003473 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003474 return false;
3475 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003476 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00003477 reportParseError("`noreorder' must be set before `nomacro'");
3478 return false;
3479 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003480 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00003481 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003482 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003483 return false;
3484}
Jack Carterd76b2372013-03-21 21:44:16 +00003485
Daniel Sanders44934432014-08-07 12:03:36 +00003486bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003487 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003488 Parser.Lex();
3489
3490 // If this is not the end of the statement, report an error.
3491 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003492 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003493
3494 setFeatureBits(Mips::FeatureMSA, "msa");
3495 getTargetStreamer().emitDirectiveSetMsa();
3496 return false;
3497}
3498
3499bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003500 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003501 Parser.Lex();
3502
3503 // If this is not the end of the statement, report an error.
3504 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003505 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003506
3507 clearFeatureBits(Mips::FeatureMSA, "msa");
3508 getTargetStreamer().emitDirectiveSetNoMsa();
3509 return false;
3510}
3511
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003512bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003513 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003514 Parser.Lex(); // Eat "nodsp".
3515
3516 // If this is not the end of the statement, report an error.
3517 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3518 reportParseError("unexpected token, expected end of statement");
3519 return false;
3520 }
3521
3522 clearFeatureBits(Mips::FeatureDSP, "dsp");
3523 getTargetStreamer().emitDirectiveSetNoDsp();
3524 return false;
3525}
3526
Toma Tabacucc2502d2014-11-04 17:18:07 +00003527bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003528 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003529 Parser.Lex(); // Eat "mips16".
3530
Jack Carter39536722014-01-22 23:08:42 +00003531 // If this is not the end of the statement, report an error.
3532 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003533 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00003534 return false;
3535 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00003536
3537 setFeatureBits(Mips::FeatureMips16, "mips16");
3538 getTargetStreamer().emitDirectiveSetMips16();
3539 Parser.Lex(); // Consume the EndOfStatement.
3540 return false;
3541}
3542
3543bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003544 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003545 Parser.Lex(); // Eat "nomips16".
3546
3547 // If this is not the end of the statement, report an error.
3548 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3549 reportParseError("unexpected token, expected end of statement");
3550 return false;
3551 }
3552
3553 clearFeatureBits(Mips::FeatureMips16, "mips16");
3554 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00003555 Parser.Lex(); // Consume the EndOfStatement.
3556 return false;
3557}
3558
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003559bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003560 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003561 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003562 // Line can be: .set fp=32
3563 // .set fp=xx
3564 // .set fp=64
3565 Parser.Lex(); // Eat fp token
3566 AsmToken Tok = Parser.getTok();
3567 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003568 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003569 return false;
3570 }
3571 Parser.Lex(); // Eat '=' token.
3572 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003573
3574 if (!parseFpABIValue(FpAbiVal, ".set"))
3575 return false;
3576
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003577 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003578 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003579 return false;
3580 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003581 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003582 Parser.Lex(); // Consume the EndOfStatement.
3583 return false;
3584}
3585
Toma Tabacu9db22db2014-09-09 10:15:38 +00003586bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003587 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003588 SMLoc Loc = getLexer().getLoc();
3589
3590 Parser.Lex();
3591 if (getLexer().isNot(AsmToken::EndOfStatement))
3592 return reportParseError("unexpected token, expected end of statement");
3593
3594 // Always keep an element on the options "stack" to prevent the user
3595 // from changing the initial options. This is how we remember them.
3596 if (AssemblerOptions.size() == 2)
3597 return reportParseError(Loc, ".set pop with no .set push");
3598
3599 AssemblerOptions.pop_back();
3600 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
3601
3602 getTargetStreamer().emitDirectiveSetPop();
3603 return false;
3604}
3605
3606bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003607 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003608 Parser.Lex();
3609 if (getLexer().isNot(AsmToken::EndOfStatement))
3610 return reportParseError("unexpected token, expected end of statement");
3611
3612 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00003613 AssemblerOptions.push_back(
3614 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00003615
3616 getTargetStreamer().emitDirectiveSetPush();
3617 return false;
3618}
3619
Jack Carterd76b2372013-03-21 21:44:16 +00003620bool MipsAsmParser::parseSetAssignment() {
3621 StringRef Name;
3622 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00003623 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00003624
3625 if (Parser.parseIdentifier(Name))
3626 reportParseError("expected identifier after .set");
3627
3628 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003629 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00003630 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00003631
Jack Carter3b2c96e2014-01-22 23:31:38 +00003632 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00003633 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00003634
Jim Grosbach6f482002015-05-18 18:43:14 +00003635 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00003636 Sym->setVariableValue(Value);
3637
3638 return false;
3639}
Jack Carterd0bd6422013-04-18 00:41:53 +00003640
Toma Tabacu26647792014-09-09 12:52:14 +00003641bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003642 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00003643 Parser.Lex();
3644 if (getLexer().isNot(AsmToken::EndOfStatement))
3645 return reportParseError("unexpected token, expected end of statement");
3646
3647 // Reset assembler options to their initial values.
3648 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
3649 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
3650
3651 getTargetStreamer().emitDirectiveSetMips0();
3652 return false;
3653}
3654
Toma Tabacu85618b32014-08-19 14:22:52 +00003655bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003656 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00003657 Parser.Lex();
3658 if (getLexer().isNot(AsmToken::Equal))
3659 return reportParseError("unexpected token, expected equals sign");
3660
3661 Parser.Lex();
3662 StringRef Arch;
3663 if (Parser.parseIdentifier(Arch))
3664 return reportParseError("expected arch identifier");
3665
3666 StringRef ArchFeatureName =
3667 StringSwitch<StringRef>(Arch)
3668 .Case("mips1", "mips1")
3669 .Case("mips2", "mips2")
3670 .Case("mips3", "mips3")
3671 .Case("mips4", "mips4")
3672 .Case("mips5", "mips5")
3673 .Case("mips32", "mips32")
3674 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003675 .Case("mips32r3", "mips32r3")
3676 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003677 .Case("mips32r6", "mips32r6")
3678 .Case("mips64", "mips64")
3679 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003680 .Case("mips64r3", "mips64r3")
3681 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003682 .Case("mips64r6", "mips64r6")
3683 .Case("cnmips", "cnmips")
3684 .Case("r4000", "mips3") // This is an implementation of Mips3.
3685 .Default("");
3686
3687 if (ArchFeatureName.empty())
3688 return reportParseError("unsupported architecture");
3689
3690 selectArch(ArchFeatureName);
3691 getTargetStreamer().emitDirectiveSetArch(Arch);
3692 return false;
3693}
3694
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003695bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003696 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003697 Parser.Lex();
3698 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003699 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003700
Matheus Almeida2852af82014-04-22 10:15:54 +00003701 switch (Feature) {
3702 default:
3703 llvm_unreachable("Unimplemented feature");
3704 case Mips::FeatureDSP:
3705 setFeatureBits(Mips::FeatureDSP, "dsp");
3706 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003707 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003708 case Mips::FeatureMicroMips:
3709 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003710 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003711 case Mips::FeatureMips1:
3712 selectArch("mips1");
3713 getTargetStreamer().emitDirectiveSetMips1();
3714 break;
3715 case Mips::FeatureMips2:
3716 selectArch("mips2");
3717 getTargetStreamer().emitDirectiveSetMips2();
3718 break;
3719 case Mips::FeatureMips3:
3720 selectArch("mips3");
3721 getTargetStreamer().emitDirectiveSetMips3();
3722 break;
3723 case Mips::FeatureMips4:
3724 selectArch("mips4");
3725 getTargetStreamer().emitDirectiveSetMips4();
3726 break;
3727 case Mips::FeatureMips5:
3728 selectArch("mips5");
3729 getTargetStreamer().emitDirectiveSetMips5();
3730 break;
3731 case Mips::FeatureMips32:
3732 selectArch("mips32");
3733 getTargetStreamer().emitDirectiveSetMips32();
3734 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003735 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003736 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003737 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003738 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003739 case Mips::FeatureMips32r3:
3740 selectArch("mips32r3");
3741 getTargetStreamer().emitDirectiveSetMips32R3();
3742 break;
3743 case Mips::FeatureMips32r5:
3744 selectArch("mips32r5");
3745 getTargetStreamer().emitDirectiveSetMips32R5();
3746 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003747 case Mips::FeatureMips32r6:
3748 selectArch("mips32r6");
3749 getTargetStreamer().emitDirectiveSetMips32R6();
3750 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003751 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003752 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00003753 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003754 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003755 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003756 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003757 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003758 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003759 case Mips::FeatureMips64r3:
3760 selectArch("mips64r3");
3761 getTargetStreamer().emitDirectiveSetMips64R3();
3762 break;
3763 case Mips::FeatureMips64r5:
3764 selectArch("mips64r5");
3765 getTargetStreamer().emitDirectiveSetMips64R5();
3766 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003767 case Mips::FeatureMips64r6:
3768 selectArch("mips64r6");
3769 getTargetStreamer().emitDirectiveSetMips64R6();
3770 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003771 }
3772 return false;
3773}
3774
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003775bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003776 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003777 if (getLexer().isNot(AsmToken::Comma)) {
3778 SMLoc Loc = getLexer().getLoc();
3779 Parser.eatToEndOfStatement();
3780 return Error(Loc, ErrorStr);
3781 }
3782
Matheus Almeida2852af82014-04-22 10:15:54 +00003783 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003784 return true;
3785}
3786
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003787bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003788 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00003789 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003790
Toma Tabacudde4c462014-11-06 10:02:45 +00003791 if (inMips16Mode()) {
3792 reportParseError(".cpload is not supported in Mips16 mode");
3793 return false;
3794 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003795
David Blaikie960ea3f2014-06-08 16:18:35 +00003796 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00003797 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003798 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3799 reportParseError("expected register containing function address");
3800 return false;
3801 }
3802
David Blaikie960ea3f2014-06-08 16:18:35 +00003803 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
3804 if (!RegOpnd.isGPRAsmReg()) {
3805 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003806 return false;
3807 }
3808
Toma Tabacudde4c462014-11-06 10:02:45 +00003809 // If this is not the end of the statement, report an error.
3810 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3811 reportParseError("unexpected token, expected end of statement");
3812 return false;
3813 }
3814
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003815 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003816 return false;
3817}
3818
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003819bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003820 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003821 unsigned FuncReg;
3822 unsigned Save;
3823 bool SaveIsReg = true;
3824
Matheus Almeida7e815762014-06-18 13:08:59 +00003825 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003826 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003827 if (ResTy == MatchOperand_NoMatch) {
3828 reportParseError("expected register containing function address");
3829 Parser.eatToEndOfStatement();
3830 return false;
3831 }
3832
3833 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3834 if (!FuncRegOpnd.isGPRAsmReg()) {
3835 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3836 Parser.eatToEndOfStatement();
3837 return false;
3838 }
3839
3840 FuncReg = FuncRegOpnd.getGPR32Reg();
3841 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003842
Toma Tabacu65f10572014-09-16 15:00:52 +00003843 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003844 return true;
3845
Toma Tabacu13964452014-09-04 13:23:44 +00003846 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003847 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003848 const AsmToken &Tok = Parser.getTok();
3849 if (Tok.is(AsmToken::Integer)) {
3850 Save = Tok.getIntVal();
3851 SaveIsReg = false;
3852 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003853 } else {
3854 reportParseError("expected save register or stack offset");
3855 Parser.eatToEndOfStatement();
3856 return false;
3857 }
3858 } else {
3859 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3860 if (!SaveOpnd.isGPRAsmReg()) {
3861 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3862 Parser.eatToEndOfStatement();
3863 return false;
3864 }
3865 Save = SaveOpnd.getGPR32Reg();
3866 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003867
Toma Tabacu65f10572014-09-16 15:00:52 +00003868 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003869 return true;
3870
Toma Tabacu8874eac2015-02-18 13:46:53 +00003871 const MCExpr *Expr;
3872 if (Parser.parseExpression(Expr)) {
3873 reportParseError("expected expression");
3874 return false;
3875 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003876
Toma Tabacu8874eac2015-02-18 13:46:53 +00003877 if (Expr->getKind() != MCExpr::SymbolRef) {
3878 reportParseError("expected symbol");
3879 return false;
3880 }
3881 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
3882
3883 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
3884 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003885 return false;
3886}
3887
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003888bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003889 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003890 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3891 const AsmToken &Tok = Parser.getTok();
3892
3893 if (Tok.getString() == "2008") {
3894 Parser.Lex();
3895 getTargetStreamer().emitDirectiveNaN2008();
3896 return false;
3897 } else if (Tok.getString() == "legacy") {
3898 Parser.Lex();
3899 getTargetStreamer().emitDirectiveNaNLegacy();
3900 return false;
3901 }
3902 }
3903 // If we don't recognize the option passed to the .nan
3904 // directive (e.g. no option or unknown option), emit an error.
3905 reportParseError("invalid option in .nan directive");
3906 return false;
3907}
3908
Jack Carter0b744b32012-10-04 02:29:46 +00003909bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003910 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003911 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003912 const AsmToken &Tok = Parser.getTok();
3913
3914 if (Tok.getString() == "noat") {
3915 return parseSetNoAtDirective();
3916 } else if (Tok.getString() == "at") {
3917 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003918 } else if (Tok.getString() == "arch") {
3919 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003920 } else if (Tok.getString() == "fp") {
3921 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003922 } else if (Tok.getString() == "pop") {
3923 return parseSetPopDirective();
3924 } else if (Tok.getString() == "push") {
3925 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003926 } else if (Tok.getString() == "reorder") {
3927 return parseSetReorderDirective();
3928 } else if (Tok.getString() == "noreorder") {
3929 return parseSetNoReorderDirective();
3930 } else if (Tok.getString() == "macro") {
3931 return parseSetMacroDirective();
3932 } else if (Tok.getString() == "nomacro") {
3933 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003934 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00003935 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003936 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003937 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003938 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003939 getTargetStreamer().emitDirectiveSetNoMicroMips();
3940 Parser.eatToEndOfStatement();
3941 return false;
3942 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003943 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003944 } else if (Tok.getString() == "mips0") {
3945 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003946 } else if (Tok.getString() == "mips1") {
3947 return parseSetFeature(Mips::FeatureMips1);
3948 } else if (Tok.getString() == "mips2") {
3949 return parseSetFeature(Mips::FeatureMips2);
3950 } else if (Tok.getString() == "mips3") {
3951 return parseSetFeature(Mips::FeatureMips3);
3952 } else if (Tok.getString() == "mips4") {
3953 return parseSetFeature(Mips::FeatureMips4);
3954 } else if (Tok.getString() == "mips5") {
3955 return parseSetFeature(Mips::FeatureMips5);
3956 } else if (Tok.getString() == "mips32") {
3957 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003958 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003959 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003960 } else if (Tok.getString() == "mips32r3") {
3961 return parseSetFeature(Mips::FeatureMips32r3);
3962 } else if (Tok.getString() == "mips32r5") {
3963 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003964 } else if (Tok.getString() == "mips32r6") {
3965 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003966 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003967 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003968 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003969 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003970 } else if (Tok.getString() == "mips64r3") {
3971 return parseSetFeature(Mips::FeatureMips64r3);
3972 } else if (Tok.getString() == "mips64r5") {
3973 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003974 } else if (Tok.getString() == "mips64r6") {
3975 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003976 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003977 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003978 } else if (Tok.getString() == "nodsp") {
3979 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003980 } else if (Tok.getString() == "msa") {
3981 return parseSetMsaDirective();
3982 } else if (Tok.getString() == "nomsa") {
3983 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003984 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003985 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003986 parseSetAssignment();
3987 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003988 }
Jack Carter07c818d2013-01-25 01:31:34 +00003989
Jack Carter0b744b32012-10-04 02:29:46 +00003990 return true;
3991}
3992
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003993/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003994/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003995bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003996 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003997 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3998 for (;;) {
3999 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004000 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00004001 return true;
4002
4003 getParser().getStreamer().EmitValue(Value, Size);
4004
4005 if (getLexer().is(AsmToken::EndOfStatement))
4006 break;
4007
Jack Carter07c818d2013-01-25 01:31:34 +00004008 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004009 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00004010 Parser.Lex();
4011 }
4012 }
4013
4014 Parser.Lex();
4015 return false;
4016}
4017
Vladimir Medic4c299852013-11-06 11:27:05 +00004018/// parseDirectiveGpWord
4019/// ::= .gpword local_sym
4020bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004021 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004022 const MCExpr *Value;
4023 // EmitGPRel32Value requires an expression, so we are using base class
4024 // method to evaluate the expression.
4025 if (getParser().parseExpression(Value))
4026 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00004027 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00004028
Vladimir Medice10c1122013-11-13 13:18:04 +00004029 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004030 return Error(getLexer().getLoc(),
4031 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00004032 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00004033 return false;
4034}
4035
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004036/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00004037/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004038bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004039 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004040 const MCExpr *Value;
4041 // EmitGPRel64Value requires an expression, so we are using base class
4042 // method to evaluate the expression.
4043 if (getParser().parseExpression(Value))
4044 return true;
4045 getParser().getStreamer().EmitGPRel64Value(Value);
4046
4047 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004048 return Error(getLexer().getLoc(),
4049 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00004050 Parser.Lex(); // Eat EndOfStatement token.
4051 return false;
4052}
4053
Jack Carter0cd3c192014-01-06 23:27:31 +00004054bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004055 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00004056 // Get the option token.
4057 AsmToken Tok = Parser.getTok();
4058 // At the moment only identifiers are supported.
4059 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004060 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00004061 Parser.eatToEndOfStatement();
4062 return false;
4063 }
4064
4065 StringRef Option = Tok.getIdentifier();
4066
4067 if (Option == "pic0") {
4068 getTargetStreamer().emitDirectiveOptionPic0();
4069 Parser.Lex();
4070 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4071 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004072 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004073 Parser.eatToEndOfStatement();
4074 }
4075 return false;
4076 }
4077
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004078 if (Option == "pic2") {
4079 getTargetStreamer().emitDirectiveOptionPic2();
4080 Parser.Lex();
4081 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4082 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004083 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004084 Parser.eatToEndOfStatement();
4085 }
4086 return false;
4087 }
4088
Jack Carter0cd3c192014-01-06 23:27:31 +00004089 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00004090 Warning(Parser.getTok().getLoc(),
4091 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00004092 Parser.eatToEndOfStatement();
4093 return false;
4094}
4095
Toma Tabacu9ca50962015-04-16 09:53:47 +00004096/// parseInsnDirective
4097/// ::= .insn
4098bool MipsAsmParser::parseInsnDirective() {
4099 // If this is not the end of the statement, report an error.
4100 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4101 reportParseError("unexpected token, expected end of statement");
4102 return false;
4103 }
4104
4105 // The actual label marking happens in
4106 // MipsELFStreamer::createPendingLabelRelocs().
4107 getTargetStreamer().emitDirectiveInsn();
4108
4109 getParser().Lex(); // Eat EndOfStatement token.
4110 return false;
4111}
4112
Daniel Sanders7e527422014-07-10 13:38:23 +00004113/// parseDirectiveModule
4114/// ::= .module oddspreg
4115/// ::= .module nooddspreg
4116/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004117bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004118 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004119 MCAsmLexer &Lexer = getLexer();
4120 SMLoc L = Lexer.getLoc();
4121
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004122 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004123 // TODO : get a better message.
4124 reportParseError(".module directive must appear before any code");
4125 return false;
4126 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004127
Toma Tabacuc405c822015-01-23 10:40:19 +00004128 StringRef Option;
4129 if (Parser.parseIdentifier(Option)) {
4130 reportParseError("expected .module option identifier");
4131 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004132 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004133
Toma Tabacuc405c822015-01-23 10:40:19 +00004134 if (Option == "oddspreg") {
4135 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
4136 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4137
4138 // If this is not the end of the statement, report an error.
4139 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4140 reportParseError("unexpected token, expected end of statement");
4141 return false;
4142 }
4143
4144 return false; // parseDirectiveModule has finished successfully.
4145 } else if (Option == "nooddspreg") {
4146 if (!isABI_O32()) {
4147 Error(L, "'.module nooddspreg' requires the O32 ABI");
4148 return false;
4149 }
4150
4151 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
4152 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4153
4154 // If this is not the end of the statement, report an error.
4155 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4156 reportParseError("unexpected token, expected end of statement");
4157 return false;
4158 }
4159
4160 return false; // parseDirectiveModule has finished successfully.
4161 } else if (Option == "fp") {
4162 return parseDirectiveModuleFP();
4163 } else {
4164 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
4165 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004166}
4167
4168/// parseDirectiveModuleFP
4169/// ::= =32
4170/// ::= =xx
4171/// ::= =64
4172bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004173 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004174 MCAsmLexer &Lexer = getLexer();
4175
4176 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004177 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004178 return false;
4179 }
4180 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004181
Daniel Sanders7e527422014-07-10 13:38:23 +00004182 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004183 if (!parseFpABIValue(FpABI, ".module"))
4184 return false;
4185
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004186 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004187 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004188 return false;
4189 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004190
Daniel Sanders7201a3e2014-07-08 10:35:52 +00004191 // Emit appropriate flags.
4192 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00004193 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004194 return false;
4195}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004196
Daniel Sanders7e527422014-07-10 13:38:23 +00004197bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004198 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004199 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004200 MCAsmLexer &Lexer = getLexer();
4201
4202 if (Lexer.is(AsmToken::Identifier)) {
4203 StringRef Value = Parser.getTok().getString();
4204 Parser.Lex();
4205
4206 if (Value != "xx") {
4207 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4208 return false;
4209 }
4210
4211 if (!isABI_O32()) {
4212 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
4213 return false;
4214 }
4215
Daniel Sanders7e527422014-07-10 13:38:23 +00004216 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004217 return true;
4218 }
4219
4220 if (Lexer.is(AsmToken::Integer)) {
4221 unsigned Value = Parser.getTok().getIntVal();
4222 Parser.Lex();
4223
4224 if (Value != 32 && Value != 64) {
4225 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4226 return false;
4227 }
4228
4229 if (Value == 32) {
4230 if (!isABI_O32()) {
4231 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
4232 return false;
4233 }
4234
Daniel Sanders7e527422014-07-10 13:38:23 +00004235 FpABI = MipsABIFlagsSection::FpABIKind::S32;
4236 } else
4237 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004238
Daniel Sanders7e527422014-07-10 13:38:23 +00004239 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004240 }
4241
4242 return false;
4243}
4244
Jack Carter0b744b32012-10-04 02:29:46 +00004245bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004246 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004247 StringRef IDVal = DirectiveID.getString();
4248
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004249 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004250 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00004251 if (IDVal == ".dword") {
4252 parseDataDirective(8, DirectiveID.getLoc());
4253 return false;
4254 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004255 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004256 StringRef SymbolName;
4257
4258 if (Parser.parseIdentifier(SymbolName)) {
4259 reportParseError("expected identifier after .ent");
4260 return false;
4261 }
4262
4263 // There's an undocumented extension that allows an integer to
4264 // follow the name of the procedure which AFAICS is ignored by GAS.
4265 // Example: .ent foo,2
4266 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4267 if (getLexer().isNot(AsmToken::Comma)) {
4268 // Even though we accept this undocumented extension for compatibility
4269 // reasons, the additional integer argument does not actually change
4270 // the behaviour of the '.ent' directive, so we would like to discourage
4271 // its use. We do this by not referring to the extended version in
4272 // error messages which are not directly related to its use.
4273 reportParseError("unexpected token, expected end of statement");
4274 return false;
4275 }
4276 Parser.Lex(); // Eat the comma.
4277 const MCExpr *DummyNumber;
4278 int64_t DummyNumberVal;
4279 // If the user was explicitly trying to use the extended version,
4280 // we still give helpful extension-related error messages.
4281 if (Parser.parseExpression(DummyNumber)) {
4282 reportParseError("expected number after comma");
4283 return false;
4284 }
4285 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
4286 reportParseError("expected an absolute expression after comma");
4287 return false;
4288 }
4289 }
4290
4291 // If this is not the end of the statement, report an error.
4292 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4293 reportParseError("unexpected token, expected end of statement");
4294 return false;
4295 }
4296
Jim Grosbach6f482002015-05-18 18:43:14 +00004297 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004298
4299 getTargetStreamer().emitDirectiveEnt(*Sym);
4300 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00004301 return false;
4302 }
4303
Jack Carter07c818d2013-01-25 01:31:34 +00004304 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004305 StringRef SymbolName;
4306
4307 if (Parser.parseIdentifier(SymbolName)) {
4308 reportParseError("expected identifier after .end");
4309 return false;
4310 }
4311
4312 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4313 reportParseError("unexpected token, expected end of statement");
4314 return false;
4315 }
4316
4317 if (CurrentFn == nullptr) {
4318 reportParseError(".end used without .ent");
4319 return false;
4320 }
4321
4322 if ((SymbolName != CurrentFn->getName())) {
4323 reportParseError(".end symbol does not match .ent symbol");
4324 return false;
4325 }
4326
4327 getTargetStreamer().emitDirectiveEnd(SymbolName);
4328 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00004329 return false;
4330 }
4331
Jack Carter07c818d2013-01-25 01:31:34 +00004332 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004333 // .frame $stack_reg, frame_size_in_bytes, $return_reg
4334 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004335 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004336 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4337 reportParseError("expected stack register");
4338 return false;
4339 }
4340
4341 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4342 if (!StackRegOpnd.isGPRAsmReg()) {
4343 reportParseError(StackRegOpnd.getStartLoc(),
4344 "expected general purpose register");
4345 return false;
4346 }
4347 unsigned StackReg = StackRegOpnd.getGPR32Reg();
4348
4349 if (Parser.getTok().is(AsmToken::Comma))
4350 Parser.Lex();
4351 else {
4352 reportParseError("unexpected token, expected comma");
4353 return false;
4354 }
4355
4356 // Parse the frame size.
4357 const MCExpr *FrameSize;
4358 int64_t FrameSizeVal;
4359
4360 if (Parser.parseExpression(FrameSize)) {
4361 reportParseError("expected frame size value");
4362 return false;
4363 }
4364
4365 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
4366 reportParseError("frame size not an absolute expression");
4367 return false;
4368 }
4369
4370 if (Parser.getTok().is(AsmToken::Comma))
4371 Parser.Lex();
4372 else {
4373 reportParseError("unexpected token, expected comma");
4374 return false;
4375 }
4376
4377 // Parse the return register.
4378 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00004379 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004380 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4381 reportParseError("expected return register");
4382 return false;
4383 }
4384
4385 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4386 if (!ReturnRegOpnd.isGPRAsmReg()) {
4387 reportParseError(ReturnRegOpnd.getStartLoc(),
4388 "expected general purpose register");
4389 return false;
4390 }
4391
4392 // If this is not the end of the statement, report an error.
4393 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4394 reportParseError("unexpected token, expected end of statement");
4395 return false;
4396 }
4397
4398 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
4399 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00004400 return false;
4401 }
4402
Jack Carter07c818d2013-01-25 01:31:34 +00004403 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00004404 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00004405 }
4406
Daniel Sandersd97a6342014-08-13 10:07:34 +00004407 if (IDVal == ".mask" || IDVal == ".fmask") {
4408 // .mask bitmask, frame_offset
4409 // bitmask: One bit for each register used.
4410 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
4411 // first register is expected to be saved.
4412 // Examples:
4413 // .mask 0x80000000, -4
4414 // .fmask 0x80000000, -4
4415 //
Jack Carterbe332172012-09-07 00:48:02 +00004416
Daniel Sandersd97a6342014-08-13 10:07:34 +00004417 // Parse the bitmask
4418 const MCExpr *BitMask;
4419 int64_t BitMaskVal;
4420
4421 if (Parser.parseExpression(BitMask)) {
4422 reportParseError("expected bitmask value");
4423 return false;
4424 }
4425
4426 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
4427 reportParseError("bitmask not an absolute expression");
4428 return false;
4429 }
4430
4431 if (Parser.getTok().is(AsmToken::Comma))
4432 Parser.Lex();
4433 else {
4434 reportParseError("unexpected token, expected comma");
4435 return false;
4436 }
4437
4438 // Parse the frame_offset
4439 const MCExpr *FrameOffset;
4440 int64_t FrameOffsetVal;
4441
4442 if (Parser.parseExpression(FrameOffset)) {
4443 reportParseError("expected frame offset value");
4444 return false;
4445 }
4446
4447 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
4448 reportParseError("frame offset not an absolute expression");
4449 return false;
4450 }
4451
4452 // If this is not the end of the statement, report an error.
4453 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4454 reportParseError("unexpected token, expected end of statement");
4455 return false;
4456 }
4457
4458 if (IDVal == ".mask")
4459 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
4460 else
4461 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00004462 return false;
4463 }
4464
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004465 if (IDVal == ".nan")
4466 return parseDirectiveNaN();
4467
Jack Carter07c818d2013-01-25 01:31:34 +00004468 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004469 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00004470 return false;
4471 }
4472
Rafael Espindolab59fb732014-03-28 18:50:26 +00004473 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004474 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004475 return false;
4476 }
4477
Jack Carter07c818d2013-01-25 01:31:34 +00004478 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004479 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00004480 return false;
4481 }
4482
Jack Carter0cd3c192014-01-06 23:27:31 +00004483 if (IDVal == ".option")
4484 return parseDirectiveOption();
4485
4486 if (IDVal == ".abicalls") {
4487 getTargetStreamer().emitDirectiveAbiCalls();
4488 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004489 Error(Parser.getTok().getLoc(),
4490 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004491 // Clear line
4492 Parser.eatToEndOfStatement();
4493 }
4494 return false;
4495 }
4496
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004497 if (IDVal == ".cpsetup")
4498 return parseDirectiveCPSetup();
4499
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004500 if (IDVal == ".module")
4501 return parseDirectiveModule();
4502
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004503 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
4504 return parseInternalDirectiveReallowModule();
4505
Toma Tabacu9ca50962015-04-16 09:53:47 +00004506 if (IDVal == ".insn")
4507 return parseInsnDirective();
4508
Rafael Espindola870c4e92012-01-11 03:56:41 +00004509 return true;
4510}
4511
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004512bool MipsAsmParser::parseInternalDirectiveReallowModule() {
4513 // If this is not the end of the statement, report an error.
4514 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4515 reportParseError("unexpected token, expected end of statement");
4516 return false;
4517 }
4518
4519 getTargetStreamer().reallowModuleDirective();
4520
4521 getParser().Lex(); // Eat EndOfStatement token.
4522 return false;
4523}
4524
Rafael Espindola870c4e92012-01-11 03:56:41 +00004525extern "C" void LLVMInitializeMipsAsmParser() {
4526 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
4527 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
4528 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
4529 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
4530}
Jack Carterb4dbc172012-09-05 23:34:03 +00004531
4532#define GET_REGISTER_MATCHER
4533#define GET_MATCHER_IMPLEMENTATION
4534#include "MipsGenAsmMatcher.inc"